diff options
author | Rüdiger Timm <rt@openoffice.org> | 2003-11-24 16:32:37 +0000 |
---|---|---|
committer | Rüdiger Timm <rt@openoffice.org> | 2003-11-24 16:32:37 +0000 |
commit | b940416849e5fc0b4b91a1df278936ad3c3dcf86 (patch) | |
tree | 074e96c45ac80d82a0dcbea026b3341e344c6d68 /vcl/source/gdi | |
parent | abc73d32a2f73764a6f20ff826cee8b1a709cdf8 (diff) |
INTEGRATION: CWS aw003 (1.13.58); FILE MERGED
2003/09/02 16:48:12 thb 1.13.58.8: #110958# Handling background vdevs special, if destination is alpha vdev -> then, background vdev must be alpha, too
2003/08/19 16:57:58 aw 1.13.58.7: #111096#
2003/08/15 08:51:24 thb 1.13.58.6: #110958# Setting the alpha bit depth, when doing transitive alpha blitting
2003/08/14 11:55:56 thb 1.13.58.5: #110958# Alpha is now transitive for virdev-virdev copies; now correctly forwarding line/fill color switchings to alpha vdev
2003/08/07 08:07:39 thb 1.13.58.4: #110958# Had to intercept some more map mode changes (this time direct mbMap manipulations), and inverted the alpha compositing calculations to actually match Porter/Duff
2003/07/28 18:03:55 thb 1.13.58.3: #110958# Removed several set* inlines, to intercept them for alpha vdev painting
2003/07/28 16:32:17 thb 1.13.58.2: #110958# Changed constructor
2003/07/28 13:59:59 thb 1.13.58.1: #110958# Added alpha channel for virtual device painting. That means, alpha information is retained during painting to a vdev
Diffstat (limited to 'vcl/source/gdi')
-rw-r--r-- | vcl/source/gdi/outdev2.cxx | 363 |
1 files changed, 282 insertions, 81 deletions
diff --git a/vcl/source/gdi/outdev2.cxx b/vcl/source/gdi/outdev2.cxx index b2807cd7a86f..7383d4e13241 100644 --- a/vcl/source/gdi/outdev2.cxx +++ b/vcl/source/gdi/outdev2.cxx @@ -2,9 +2,9 @@ * * $RCSfile: outdev2.cxx,v $ * - * $Revision: 1.14 $ + * $Revision: 1.15 $ * - * last change: $Author: kz $ $Date: 2003-11-18 14:33:45 $ + * last change: $Author: rt $ $Date: 2003-11-24 17:32:37 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -401,6 +401,9 @@ void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize, mpGraphics->CopyBits( &aPosAry, NULL, this, NULL ); } } + + if( mpAlphaVDev ) + mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize ); } // ------------------------------------------------------------------ @@ -442,7 +445,34 @@ void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize, aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() ); aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() ); - ImplDrawOutDevDirect( &rOutDev, &aPosAry ); + if( mpAlphaVDev ) + { + ImplDrawOutDevDirect( &rOutDev, &aPosAry ); + + if( rOutDev.mpAlphaVDev ) + { + // copy source alpha channel to our alpha channel + mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize, *rOutDev.mpAlphaVDev ); + } + else + { + // make destination rectangle opaque - source has no alpha + mpAlphaVDev->DrawRect( Rectangle(rDestPt, rDestSize) ); + } + } + else + { + if( rOutDev.mpAlphaVDev ) + { + // alpha-blend source over destination + DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) ); + } + else + { + // no alpha at all, neither in source nor destination device + ImplDrawOutDevDirect( &rOutDev, &aPosAry ); + } + } } // ------------------------------------------------------------------ @@ -518,6 +548,9 @@ void OutputDevice::CopyArea( const Point& rDestPt, } SetRasterOp( eOldRop ); + + if( mpAlphaVDev ) + mpAlphaVDev->CopyArea( rDestPt, rSrcPt, rSrcSize, nFlags ); } // ------------------------------------------------------------------ @@ -605,6 +638,9 @@ void OutputDevice::DrawBitmap( const Point& rDestPt, const Bitmap& rBitmap ) const Size aSizePix( rBitmap.GetSizePixel() ); ImplDrawBitmap( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, META_BMP_ACTION ); + + if( mpAlphaVDev ) + mpAlphaVDev->DrawRect( Rectangle(rDestPt, PixelToLogic( aSizePix )) ); } // ------------------------------------------------------------------ @@ -617,6 +653,9 @@ void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, cons return; ImplDrawBitmap( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, META_BMPSCALE_ACTION ); + + if( mpAlphaVDev ) + mpAlphaVDev->DrawRect( Rectangle(rDestPt, rDestSize) ); } // ------------------------------------------------------------------ @@ -631,6 +670,9 @@ void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, return; ImplDrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, META_BMPSCALEPART_ACTION ); + + if( mpAlphaVDev ) + mpAlphaVDev->DrawRect( Rectangle(rDestPt, rDestSize) ); } // ----------------------------------------------------------------------------- @@ -907,10 +949,23 @@ void OutputDevice::ImplDrawBitmapEx( const Point& rDestPt, const Size& rDestSize const ImpBitmap* pMaskBmp = aBmpEx.ImplGetMaskImpBitmap(); if ( pMaskBmp ) + { mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap(), *pMaskBmp->ImplGetSalBitmap(), this ); + + // #110958# Paint mask to alpha channel. Luckily, the + // black and white representation of the mask maps to + // the alpha channel + if( mpAlphaVDev ) + mpAlphaVDev->DrawBitmap( rDestPt, rDestSize, rBitmapEx.GetMask() ); + } else + { mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap(), this ); + if( mpAlphaVDev ) + mpAlphaVDev->DrawRect( Rectangle(rDestPt, rDestSize) ); + } + #else if( nMirrFlags ) @@ -939,6 +994,10 @@ void OutputDevice::DrawMask( const Point& rDestPt, const Size aSizePix( rBitmap.GetSizePixel() ); ImplDrawMask( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, rMaskColor, META_MASK_ACTION ); + + // TODO: Use mask here + if( mpAlphaVDev ) + mpAlphaVDev->DrawRect( Rectangle(rDestPt, PixelToLogic( aSizePix )) ); } // ------------------------------------------------------------------ @@ -952,6 +1011,10 @@ void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize, return; ImplDrawMask( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, rMaskColor, META_MASKSCALE_ACTION ); + + // TODO: Use mask here + if( mpAlphaVDev ) + mpAlphaVDev->DrawRect( Rectangle(rDestPt, rDestSize) ); } // ------------------------------------------------------------------ @@ -966,6 +1029,10 @@ void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize, return; ImplDrawMask( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor, META_MASKSCALEPART_ACTION ); + + // TODO: Use mask here + if( mpAlphaVDev ) + mpAlphaVDev->DrawRect( Rectangle(rDestPt, rDestSize) ); } // ------------------------------------------------------------------ @@ -1183,6 +1250,31 @@ Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const // ------------------------------------------------------------------ +BitmapEx OutputDevice::GetBitmapEx( const Point& rSrcPt, const Size& rSize ) const +{ + DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); + + // #110958# Extract alpha value from VDev, if any + if( mpAlphaVDev ) + { + Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( rSrcPt, rSize ) ); + +#ifdef DEBUG_ONLYALPHA + return BitmapEx( aAlphaBitmap ); +#else + // ensure 8 bit alpha + if( aAlphaBitmap.GetBitCount() > 8 ) + aAlphaBitmap.Convert( BMP_CONVERSION_8BIT_GREYS ); + + return BitmapEx(GetBitmap( rSrcPt, rSize ), AlphaMask( aAlphaBitmap ) ); +#endif + } + else + return GetBitmap( rSrcPt, rSize ); +} + +// ------------------------------------------------------------------ + void OutputDevice::ImplGetFrameBitmap( const Point& rDestPt, const Size& rSize, Bitmap& rBitmap ) const { @@ -1318,6 +1410,9 @@ void OutputDevice::DrawPixel( const Point& rPt ) pGraphics->DrawPixel( ImplLogicToDevicePixel( rPt ) ); } #endif + + if( mpAlphaVDev ) + mpAlphaVDev->DrawPixel( rPt ); } // ----------------------------------------------------------------------- @@ -1389,6 +1484,9 @@ void OutputDevice::DrawPixel( const Point& rPt, const Color& rColor ) if ( pGraphics ) pGraphics->DrawPixel( ImplLogicToDevicePixel( rPt ), aColor ); #endif + + if( mpAlphaVDev ) + mpAlphaVDev->DrawPixel( rPt ); } // ----------------------------------------------------------------------- @@ -1439,6 +1537,9 @@ void OutputDevice::DrawPixel( const Polygon& rPts, const Color* pColors ) #endif } } + + if( mpAlphaVDev ) + mpAlphaVDev->DrawPixel( rPts, pColors ); } // ----------------------------------------------------------------------- @@ -1456,6 +1557,9 @@ void OutputDevice::DrawPixel( const Polygon& rPts, const Color& rColor ) DrawPixel( rPts, pColArray ); delete[] pColArray; } + + if( mpAlphaVDev ) + mpAlphaVDev->DrawPixel( rPts, rColor ); } // ------------------------------------------------------------------------ @@ -1492,6 +1596,8 @@ void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha, if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() ) { + VirtualDevice* pOldVDev = mpAlphaVDev; + Rectangle aBmpRect( aPt, rBmp.GetSizePixel() ); if( !aBmpRect.Intersection( Rectangle( rSrcPtPixel, rSrcSizePixel ) ).IsEmpty() ) @@ -1507,6 +1613,11 @@ void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha, // access) aDstRect.SetSize( aBmp.GetSizePixel() ); + // #110958# Disable alpha VDev, we're doing the necessary + // stuff explicitely furher below + if( mpAlphaVDev ) + mpAlphaVDev = NULL; + BitmapColor aDstCol; const long nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight(); const long nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight(); @@ -1540,12 +1651,17 @@ void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha, pMapY[ nY ] = nMirrOffY - pMapY[ nY ]; } + BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess(); + BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess(); + + DBG_ASSERT( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL || + pA->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK, + "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" ); + if( GetBitCount() <= 8 ) { Bitmap aDither( aBmp.GetSizePixel(), 8 ); BitmapColor aIndex( 0 ); - BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess(); - BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess(); BitmapReadAccess* pB = aBmp.AcquireReadAccess(); BitmapWriteAccess* pW = aDither.AcquireWriteAccess(); @@ -1571,127 +1687,212 @@ void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha, } } - ( (Bitmap&) rBmp ).ReleaseAccess( pP ); - ( (AlphaMask&) rAlpha ).ReleaseAccess( pA ); aBmp.ReleaseAccess( pB ); aDither.ReleaseAccess( pW ); DrawBitmap( aDstRect.TopLeft(), aDither ); } else { - BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess(); - BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess(); BitmapWriteAccess* pB = aBmp.AcquireWriteAccess(); if( pP && pA && pB ) { - if( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) + switch( pP->GetScanlineFormat() ) { - switch( pP->GetScanlineFormat() ) + case( BMP_FORMAT_8BIT_PAL ): { - case( BMP_FORMAT_8BIT_PAL ): + for( nY = 0; nY < nDstHeight; nY++ ) { - for( nY = 0; nY < nDstHeight; nY++ ) + const long nMapY = pMapY[ nY ]; + Scanline pPScan = pP->GetScanline( nMapY ); + Scanline pAScan = pA->GetScanline( nMapY ); + + for( nX = 0; nX < nDstWidth; nX++ ) { - const long nMapY = pMapY[ nY ]; - Scanline pPScan = pP->GetScanline( nMapY ); - Scanline pAScan = pA->GetScanline( nMapY ); - - for( nX = 0; nX < nDstWidth; nX++ ) - { - const long nMapX = pMapX[ nX ]; - aDstCol = pB->GetPixel( nY, nX ); - pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ), - pAScan[ nMapX ] ) ); - } + const long nMapX = pMapX[ nX ]; + aDstCol = pB->GetPixel( nY, nX ); + pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ), + pAScan[ nMapX ] ) ); } } - break; + } + break; - case( BMP_FORMAT_24BIT_TC_BGR ): + case( BMP_FORMAT_24BIT_TC_BGR ): + { + for( nY = 0; nY < nDstHeight; nY++ ) { - for( nY = 0; nY < nDstHeight; nY++ ) + const long nMapY = pMapY[ nY ]; + Scanline pPScan = pP->GetScanline( nMapY ); + Scanline pAScan = pA->GetScanline( nMapY ); + + for( nX = 0; nX < nDstWidth; nX++ ) { - const long nMapY = pMapY[ nY ]; - Scanline pPScan = pP->GetScanline( nMapY ); - Scanline pAScan = pA->GetScanline( nMapY ); - - for( nX = 0; nX < nDstWidth; nX++ ) - { - const long nMapX = pMapX[ nX ]; - Scanline pTmp = pPScan + nMapX * 3; - - aDstCol = pB->GetPixel( nY, nX ); - pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ], - pAScan[ nMapX ] ) ); - } + const long nMapX = pMapX[ nX ]; + Scanline pTmp = pPScan + nMapX * 3; + + aDstCol = pB->GetPixel( nY, nX ); + pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ], + pAScan[ nMapX ] ) ); } } - break; + } + break; - case( BMP_FORMAT_24BIT_TC_RGB ): + case( BMP_FORMAT_24BIT_TC_RGB ): + { + for( nY = 0; nY < nDstHeight; nY++ ) { - for( nY = 0; nY < nDstHeight; nY++ ) + const long nMapY = pMapY[ nY ]; + Scanline pPScan = pP->GetScanline( nMapY ); + Scanline pAScan = pA->GetScanline( nMapY ); + + for( nX = 0; nX < nDstWidth; nX++ ) { - const long nMapY = pMapY[ nY ]; - Scanline pPScan = pP->GetScanline( nMapY ); - Scanline pAScan = pA->GetScanline( nMapY ); - - for( nX = 0; nX < nDstWidth; nX++ ) - { - const long nMapX = pMapX[ nX ]; - Scanline pTmp = pPScan + nMapX * 3; - - aDstCol = pB->GetPixel( nY, nX ); - pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ], - pAScan[ nMapX ] ) ); - } + const long nMapX = pMapX[ nX ]; + Scanline pTmp = pPScan + nMapX * 3; + + aDstCol = pB->GetPixel( nY, nX ); + pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ], + pAScan[ nMapX ] ) ); } } - break; + } + break; - default: + default: + { + for( nY = 0; nY < nDstHeight; nY++ ) { - for( nY = 0; nY < nDstHeight; nY++ ) + const long nMapY = pMapY[ nY ]; + Scanline pAScan = pA->GetScanline( nMapY ); + + for( nX = 0; nX < nDstWidth; nX++ ) { - const long nMapY = pMapY[ nY ]; - Scanline pAScan = pA->GetScanline( nMapY ); - - for( nX = 0; nX < nDstWidth; nX++ ) - { - const long nMapX = pMapX[ nX ]; - aDstCol = pB->GetPixel( nY, nX ); - pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ), - pAScan[ nMapX ] ) ); - } + const long nMapX = pMapX[ nX ]; + aDstCol = pB->GetPixel( nY, nX ); + pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ), + pAScan[ nMapX ] ) ); } } - break; } + break; } - else + } + + aBmp.ReleaseAccess( pB ); + DrawBitmap( aDstRect.TopLeft(), aBmp ); + } + + // #110958# Enable alpha VDev again + mpAlphaVDev = pOldVDev; + + // #110958# Perform merging of bitmap and VDev alpha channel + if( mpAlphaVDev ) + { + BOOL bOldMapMode( IsMapModeEnabled() ); + mpAlphaVDev->EnableMapMode(FALSE); + Point aEmptyPoint; + Bitmap aBitmap( mpAlphaVDev->GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) ); + BitmapWriteAccess* pW = aBitmap.AcquireWriteAccess(); + BYTE nAlpha; + + if( pW && pA ) + { + if( mpAlphaVDev->GetBitCount() < 8 ) { - for( nY = 0; nY < nDstHeight; nY++ ) + // Less than 8 bit for backbuffer - try dithering of alpha channel + BitmapColor aIndex( 0 ); + + for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ ) { const long nMapY = pMapY[ nY ]; + const long nModY = ( nOutY & 0x0FL ) << 4L; + Scanline pAScan = pA->GetScanline( nMapY ); - for( nX = 0; nX < nDstWidth; nX++ ) + for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ ) { - const long nMapX = pMapX[ nX ]; - aDstCol = pB->GetPixel( nY, nX ); - pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ), - (BYTE) pA->GetPixel( nMapY, nMapX ) ) ); + const long nMapX = pMapX[ nX ]; + const ULONG nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ]; + + nAlpha = pAScan[ nMapX ]; + + // Have to perform the compositing + // 'algebra' in the inverse alpha + // space (with 255 meaning opaque), + // otherwise, transitivity is not + // achieved. + nAlpha = 255-COLOR_CHANNEL_MERGE( 255, (BYTE) 255-pW->GetColor( nY, nX ), 255-nAlpha ); + + aIndex.SetIndex( (BYTE) ( nVCLRLut[ ( nVCLLut[ nAlpha ] + nD ) >> 16UL ] + + nVCLGLut[ ( nVCLLut[ nAlpha ] + nD ) >> 16UL ] + + nVCLBLut[ ( nVCLLut[ nAlpha ] + nD ) >> 16UL ] ) ); + pW->SetPixel( nY, nX, aIndex ); + } + } + } + else + { + if( pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL || + pW->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK ) + { + // optimized handling for 8 bit alpha - 8 bit backbuffer + for( nY = 0; nY < nDstHeight; nY++ ) + { + const long nMapY = pMapY[ nY ]; + Scanline pWScan = pW->GetScanline( nY ); + Scanline pAScan = pA->GetScanline( nMapY ); + + for( nX = 0; nX < nDstWidth; nX++ ) + { + const long nMapX = pMapX[ nX ]; + + nAlpha = pAScan[ nMapX ]; + + // Have to perform the compositing + // 'algebra' in the inverse alpha + // space (with 255 meaning opaque), + // otherwise, transitivity is not + // achieved. + pWScan[ nX ] = 255 - COLOR_CHANNEL_MERGE( 255, 255-pWScan[ nX ], 255-nAlpha ); + } + } + } + else + { + // optimized handling for 8 bit alpha - >8 bit backbuffer + for( nY = 0; nY < nDstHeight; nY++ ) + { + const long nMapY = pMapY[ nY ]; + Scanline pAScan = pA->GetScanline( nMapY ); + + for( nX = 0; nX < nDstWidth; nX++ ) + { + const long nMapX = pMapX[ nX ]; + nAlpha = pAScan[ nMapX ]; + + // Have to perform the compositing + // 'algebra' in the inverse alpha + // space (with 255 meaning opaque), + // otherwise, transitivity is not + // achieved. + nAlpha = 255 - COLOR_CHANNEL_MERGE( 255, 255-pW->GetColor( nY, nX ).GetBlue(), 255-nAlpha ); + + pW->SetPixel( nY, nX, Color(nAlpha, nAlpha, nAlpha) ); + } } } } } - ( (Bitmap&) rBmp ).ReleaseAccess( pP ); - ( (AlphaMask&) rAlpha ).ReleaseAccess( pA ); - aBmp.ReleaseAccess( pB ); - DrawBitmap( aDstRect.TopLeft(), aBmp ); + aBitmap.ReleaseAccess( pW ); + mpAlphaVDev->DrawBitmap( aDstRect.TopLeft(), aBitmap ); + mpAlphaVDev->EnableMapMode( bOldMapMode ); } + ( (Bitmap&) rBmp ).ReleaseAccess( pP ); + ( (AlphaMask&) rAlpha ).ReleaseAccess( pA ); + delete[] pMapX; delete[] pMapY; mbMap = bOldMap; |