vcl/source/gdi/outdev2.cxx | 84 ++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 39 deletions(-)
New commits: commit 7a9ea6e5696af0816651675d8f7538198cdce4da Author: Muthu Subramanian <sumu...@suse.com> Date: Thu Mar 29 16:08:56 2012 +0530 n714787: Duplicate code removal. (cherry picked from commit 27d9df17c13b22aed7d9194d9dfcf7980b632b3c) Signed-off-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/source/gdi/outdev2.cxx b/vcl/source/gdi/outdev2.cxx index 23a7952..2b2e375 100644 --- a/vcl/source/gdi/outdev2.cxx +++ b/vcl/source/gdi/outdev2.cxx @@ -1623,6 +1623,36 @@ namespace (int)nDstAlpha*nDestColor*nSourceAlpha/255 ) / (int)nResAlpha : 0; return sal_uInt8( c ); } + +inline BitmapColor lcl_AlphaBlend( int nX, int nY, + const long nMapX, + const long nMapY, + BitmapReadAccess* pP, + BitmapReadAccess* pA, + BitmapReadAccess* pB, + BitmapWriteAccess* pAlphaW, + sal_uInt8& nResAlpha ) +{ + BitmapColor aDstCol,aSrcCol; + aSrcCol = pP->GetColor( nMapY, nMapX ); + aDstCol = pB->GetColor( nY, nX ); + + // vcl stores transparency, not alpha - invert it + const sal_uInt8 nSrcAlpha = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex(); + const sal_uInt8 nDstAlpha = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex(); + + // Perform porter-duff compositing 'over' operation + // + // Co = Cs + Cd*(1-As) + // Ad = As + Ad*(1-As) + nResAlpha = (int)nSrcAlpha + (int)nDstAlpha - (int)nDstAlpha*nSrcAlpha/255; + + aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetRed() ) ); + aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetBlue() ) ); + aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetGreen() ) ); + + return aDstCol; +} } // ------------------------------------------------------------------------ @@ -1638,9 +1668,10 @@ Bitmap OutputDevice::ImplBlendWithAlpha( Bitmap aBmp, const long* pMapX, const long* pMapY ) { - BitmapColor aDstCol,aSrcCol; + BitmapColor aDstCol; Bitmap res; int nX, nY; + sal_uInt8 nResAlpha; OSL_ENSURE(mpAlphaVDev, "ImplBlendWithAlpha(): call me only with valid alpha VDev!" ); @@ -1673,22 +1704,7 @@ Bitmap OutputDevice::ImplBlendWithAlpha( Bitmap aBmp, const long nMapX = pMapX[ nX ]; const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ]; - aSrcCol = pP->GetColor( nMapY, nMapX ); - aDstCol = pB->GetColor( nY, nX ); - - // vcl stores transparency, not alpha - invert it - const sal_uInt8 nSrcAlpha = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex(); - const sal_uInt8 nDstAlpha = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex(); - - // Perform porter-duff compositing 'over' operation - // - // Co = Cs + Cd*(1-As) - // Ad = As + Ad*(1-As) - const sal_uInt8 nResAlpha = (int)nSrcAlpha + (int)nDstAlpha - (int)nDstAlpha*nSrcAlpha/255; - - aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetRed() ) ); - aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetBlue() ) ); - aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetGreen() ) ); + aDstCol = lcl_AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB, pAlphaW, nResAlpha ); aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] + nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] + @@ -1719,23 +1735,7 @@ Bitmap OutputDevice::ImplBlendWithAlpha( Bitmap aBmp, for( nX = 0; nX < nDstWidth; nX++ ) { const long nMapX = pMapX[ nX ]; - - aSrcCol = pP->GetColor( nMapY, nMapX ); - aDstCol = pB->GetColor( nY, nX ); - - // vcl stores transparency, not alpha - invert it - const sal_uInt8 nSrcAlpha = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex(); - const sal_uInt8 nDstAlpha = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex(); - - // Perform porter-duff compositing 'over' operation - // - // Co = Cs + Cd*(1-As) - // Ad = As + Ad*(1-As) - const sal_uInt8 nResAlpha = (int)nSrcAlpha + (int)nDstAlpha - (int)nDstAlpha*nSrcAlpha/255; - - aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetRed() ) ); - aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetBlue() ) ); - aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetGreen() ) ); + aDstCol = lcl_AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB, pAlphaW, nResAlpha ); pB->SetPixel( nY, nX, aDstCol ); pAlphaW->SetPixel( nY, nX, Color(255L-nResAlpha, 255L-nResAlpha, 255L-nResAlpha) ); commit 821362c208cb519d41cba09260694846bddfc080 Author: Thorsten Behrens <tbehr...@suse.com> Date: Tue Mar 27 02:54:42 2012 +0200 Fix vcl alpha blending n#714787 The way alpha compositing took place in vcl's alpha vdev was subtly wrong - it was supposed to implement porter-duff 'over', but didn't. This is now fixed also for cases where the source surface contains alpha, and needs to blend correctly into fully-transparent background. For reference: http://en.wikipedia.org/wiki/Alpha_compositing (cherry picked from commit 06c16e1e26a0137a0048085cdf1c7758d3ac96cd) Signed-off-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/source/gdi/outdev2.cxx b/vcl/source/gdi/outdev2.cxx index d8d847e..23a7952 100644 --- a/vcl/source/gdi/outdev2.cxx +++ b/vcl/source/gdi/outdev2.cxx @@ -1614,11 +1614,14 @@ void OutputDevice::DrawPixel( const Polygon& rPts, const Color& rColor ) namespace { - sal_uInt8 lcl_calcColor( const sal_uInt8 nSourceColor, const sal_uInt8 nSourceOpaq, const sal_uInt8 nDestColor ) + // Co = Cs + Cd*(1-As) premultiplied alpha -or- + // Co = (AsCs + AdCd*(1-As)) / Ao + inline sal_uInt8 lcl_calcColor( const sal_uInt8 nSourceColor, const sal_uInt8 nSourceAlpha, + const sal_uInt8 nDstAlpha, const sal_uInt8 nResAlpha, const sal_uInt8 nDestColor ) { - int c = ( (int)nDestColor * ( 255 - nSourceOpaq ) ) - + (int)nSourceOpaq * (int)nSourceColor; - return sal_uInt8( c / 255 ); + int c = nResAlpha ? ( (int)nSourceAlpha*nSourceColor + (int)nDstAlpha*nDestColor - + (int)nDstAlpha*nDestColor*nSourceAlpha/255 ) / (int)nResAlpha : 0; + return sal_uInt8( c ); } } @@ -1672,27 +1675,29 @@ Bitmap OutputDevice::ImplBlendWithAlpha( Bitmap aBmp, aSrcCol = pP->GetColor( nMapY, nMapX ); aDstCol = pB->GetColor( nY, nX ); - const sal_uInt8 nSrcOpaq = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex(); - const sal_uInt8 nDstOpaq = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex(); - aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcOpaq, aDstCol.GetRed() ) ); - aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcOpaq, aDstCol.GetBlue() ) ); - aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcOpaq, aDstCol.GetGreen() ) ); + // vcl stores transparency, not alpha - invert it + const sal_uInt8 nSrcAlpha = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex(); + const sal_uInt8 nDstAlpha = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex(); + + // Perform porter-duff compositing 'over' operation + // + // Co = Cs + Cd*(1-As) + // Ad = As + Ad*(1-As) + const sal_uInt8 nResAlpha = (int)nSrcAlpha + (int)nDstAlpha - (int)nDstAlpha*nSrcAlpha/255; + + aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetRed() ) ); + aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetBlue() ) ); + aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetGreen() ) ); aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] + nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] + nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) ); pW->SetPixel( nY, nX, aIndex ); - // Have to perform the compositing 'algebra' in - // the inverse alpha space (with 255 meaning - // opaque), otherwise, transitivity is not - // achieved. - const sal_uInt8 nSrcAlpha = 255-COLOR_CHANNEL_MERGE( 255, (sal_uInt8)nDstOpaq, nSrcOpaq ); - - aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] + - nVCLGLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] + - nVCLBLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] ) ); + aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] + + nVCLGLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] + + nVCLBLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] ) ); pAlphaW->SetPixel( nY, nX, aIndex ); } } @@ -1717,22 +1722,23 @@ Bitmap OutputDevice::ImplBlendWithAlpha( Bitmap aBmp, aSrcCol = pP->GetColor( nMapY, nMapX ); aDstCol = pB->GetColor( nY, nX ); - const sal_uInt8 nSrcOpaq = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex(); - const sal_uInt8 nDstOpaq = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex(); - aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcOpaq, aDstCol.GetRed() ) ); - aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcOpaq, aDstCol.GetBlue() ) ); - aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcOpaq, aDstCol.GetGreen() ) ); + // vcl stores transparency, not alpha - invert it + const sal_uInt8 nSrcAlpha = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex(); + const sal_uInt8 nDstAlpha = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex(); - pB->SetPixel( nY, nX, aDstCol ); + // Perform porter-duff compositing 'over' operation + // + // Co = Cs + Cd*(1-As) + // Ad = As + Ad*(1-As) + const sal_uInt8 nResAlpha = (int)nSrcAlpha + (int)nDstAlpha - (int)nDstAlpha*nSrcAlpha/255; - // Have to perform the compositing 'algebra' in - // the inverse alpha space (with 255 meaning - // opaque), otherwise, transitivity is not - // achieved. - const sal_uInt8 nSrcAlpha = 255-COLOR_CHANNEL_MERGE( 255, (sal_uInt8)nDstOpaq, nSrcOpaq ); + aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetRed() ) ); + aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetBlue() ) ); + aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetGreen() ) ); - pAlphaW->SetPixel( nY, nX, Color(nSrcAlpha, nSrcAlpha, nSrcAlpha) ); + pB->SetPixel( nY, nX, aDstCol ); + pAlphaW->SetPixel( nY, nX, Color(255L-nResAlpha, 255L-nResAlpha, 255L-nResAlpha) ); } } }
_______________________________________________ Libreoffice-commits mailing list Libreoffice-commits@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits