diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2018-03-16 14:58:59 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2018-03-16 19:25:48 +0100 |
commit | 5b75a1697250d8b2b6003c37067f39270a5ad828 (patch) | |
tree | 14d1fddc6f14707c64c220ee738e25567037de18 /canvas | |
parent | 92dc87cbac74c1be260534b5e38088c44515a47b (diff) |
move cairo extract bitmap code from canvas to vcl
part of making GetMask/GetAlpha an internal detail of vcl
Change-Id: I45c2e9fdae08d7f444a64e8e04a6f65bb525cbd1
Reviewed-on: https://gerrit.libreoffice.org/51417
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'canvas')
-rw-r--r-- | canvas/source/cairo/cairo_canvashelper.cxx | 288 |
1 files changed, 6 insertions, 282 deletions
diff --git a/canvas/source/cairo/cairo_canvashelper.cxx b/canvas/source/cairo/cairo_canvashelper.cxx index bba59a15c475..2ed3d0472c04 100644 --- a/canvas/source/cairo/cairo_canvashelper.cxx +++ b/canvas/source/cairo/cairo_canvashelper.cxx @@ -48,6 +48,7 @@ #include <tools/diagnose_ex.h> #include <vcl/bitmapex.hxx> #include <vcl/bitmapaccess.hxx> +#include <vcl/BitmapTools.hxx> #include <vcl/canvastools.hxx> #include <vcl/virdev.hxx> @@ -328,71 +329,6 @@ namespace cairocanvas return ::BitmapEx(); } - static sal_uInt8 lcl_GetColor(BitmapColor const& rColor) - { - sal_uInt8 nTemp(0); - if (rColor.IsIndex()) - { - nTemp = rColor.GetIndex(); - } - else - { - nTemp = rColor.GetBlue(); - // greyscale expected here, or what would non-grey colors mean? - assert(rColor.GetRed() == nTemp && rColor.GetGreen() == nTemp); - } - return nTemp; - } - - static bool readAlpha( BitmapReadAccess const * pAlphaReadAcc, long nY, const long nWidth, unsigned char* data, long nOff ) - { - bool bIsAlpha = false; - long nX; - int nAlpha; - Scanline pReadScan; - - nOff += 3; - - switch( pAlphaReadAcc->GetScanlineFormat() ) - { - case ScanlineFormat::N8BitTcMask: - pReadScan = pAlphaReadAcc->GetScanline( nY ); - for( nX = 0; nX < nWidth; nX++ ) - { - nAlpha = data[ nOff ] = 255 - ( *pReadScan++ ); - if( nAlpha != 255 ) - bIsAlpha = true; - nOff += 4; - } - break; - case ScanlineFormat::N8BitPal: - pReadScan = pAlphaReadAcc->GetScanline( nY ); - for( nX = 0; nX < nWidth; nX++ ) - { - BitmapColor const& rColor( - pAlphaReadAcc->GetPaletteColor(*pReadScan)); - pReadScan++; - nAlpha = data[ nOff ] = 255 - lcl_GetColor(rColor); - if( nAlpha != 255 ) - bIsAlpha = true; - nOff += 4; - } - break; - default: - SAL_INFO( "canvas.cairo", "fallback to GetColor for alpha - slow, format: " << static_cast<int>(pAlphaReadAcc->GetScanlineFormat()) ); - for( nX = 0; nX < nWidth; nX++ ) - { - nAlpha = data[ nOff ] = 255 - pAlphaReadAcc->GetColor( nY, nX ).GetIndex(); - if( nAlpha != 255 ) - bIsAlpha = true; - nOff += 4; - } - } - - return bIsAlpha; - } - - /** surfaceFromXBitmap Create a surface from XBitmap * @param xBitmap bitmap image that will be used for the surface * @param rDevice reference to the device into which we want to draw @@ -427,232 +363,20 @@ namespace cairocanvas if( !pSurface ) { - AlphaMask aAlpha = aBmpEx.GetAlpha(); - - ::BitmapReadAccess* pBitmapReadAcc = aBitmap.AcquireReadAccess(); - ::BitmapReadAccess* pAlphaReadAcc = nullptr; - const long nWidth = pBitmapReadAcc->Width(); - const long nHeight = pBitmapReadAcc->Height(); - long nX, nY; - bool bIsAlpha = false; - - if( aBmpEx.IsTransparent() || aBmpEx.IsAlpha() ) - pAlphaReadAcc = aAlpha.AcquireReadAccess(); - - data = static_cast<unsigned char*>(malloc( nWidth*nHeight*4 )); - - long nOff = 0; - ::Color aColor; - unsigned int nAlpha = 255; - - for( nY = 0; nY < nHeight; nY++ ) - { - ::Scanline pReadScan; - - switch( pBitmapReadAcc->GetScanlineFormat() ) - { - case ScanlineFormat::N8BitPal: - pReadScan = pBitmapReadAcc->GetScanline( nY ); - if( pAlphaReadAcc ) - if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) - bIsAlpha = true; - - for( nX = 0; nX < nWidth; nX++ ) - { -#ifdef OSL_BIGENDIAN - if( pAlphaReadAcc ) - nAlpha = data[ nOff++ ]; - else - nAlpha = data[ nOff++ ] = 255; -#else - if( pAlphaReadAcc ) - nAlpha = data[ nOff + 3 ]; - else - nAlpha = data[ nOff + 3 ] = 255; -#endif - aColor = pBitmapReadAcc->GetPaletteColor(*pReadScan++).GetColor(); - -#ifdef OSL_BIGENDIAN - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetRed() ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetGreen() ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetBlue() ) )/255 ); -#else - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetBlue() ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetGreen() ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( aColor.GetRed() ) )/255 ); - nOff++; -#endif - } - break; - case ScanlineFormat::N24BitTcBgr: - pReadScan = pBitmapReadAcc->GetScanline( nY ); - if( pAlphaReadAcc ) - if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) - bIsAlpha = true; - - for( nX = 0; nX < nWidth; nX++ ) - { -#ifdef OSL_BIGENDIAN - if( pAlphaReadAcc ) - nAlpha = data[ nOff ]; - else - nAlpha = data[ nOff ] = 255; - data[ nOff + 3 ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - data[ nOff + 2 ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - data[ nOff + 1 ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - nOff += 4; -#else - if( pAlphaReadAcc ) - nAlpha = data[ nOff + 3 ]; - else - nAlpha = data[ nOff + 3 ] = 255; - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - nOff++; -#endif - } - break; - case ScanlineFormat::N24BitTcRgb: - pReadScan = pBitmapReadAcc->GetScanline( nY ); - if( pAlphaReadAcc ) - if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) - bIsAlpha = true; - - for( nX = 0; nX < nWidth; nX++ ) - { -#ifdef OSL_BIGENDIAN - if( pAlphaReadAcc ) - nAlpha = data[ nOff++ ]; - else - nAlpha = data[ nOff++ ] = 255; - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); -#else - if( pAlphaReadAcc ) - nAlpha = data[ nOff + 3 ]; - else - nAlpha = data[ nOff + 3 ] = 255; - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 2 ] ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 1 ] ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 0 ] ) )/255 ); - pReadScan += 3; - nOff++; -#endif - } - break; - case ScanlineFormat::N32BitTcBgra: - pReadScan = pBitmapReadAcc->GetScanline( nY ); - if( pAlphaReadAcc ) - if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) - bIsAlpha = true; - - for( nX = 0; nX < nWidth; nX++ ) - { -#ifdef OSL_BIGENDIAN - if( pAlphaReadAcc ) - nAlpha = data[ nOff++ ]; - else - nAlpha = data[ nOff++ ] = 255; - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 2 ] ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 1 ] ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 0 ] ) )/255 ); - pReadScan += 4; -#else - if( pAlphaReadAcc ) - nAlpha = data[ nOff + 3 ]; - else - nAlpha = data[ nOff + 3 ] = 255; - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - pReadScan++; - nOff++; -#endif - } - break; - case ScanlineFormat::N32BitTcRgba: - pReadScan = pBitmapReadAcc->GetScanline( nY ); - if( pAlphaReadAcc ) - if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) - bIsAlpha = true; - - for( nX = 0; nX < nWidth; nX++ ) - { -#ifdef OSL_BIGENDIAN - if( pAlphaReadAcc ) - nAlpha = data[ nOff ++ ]; - else - nAlpha = data[ nOff ++ ] = 255; - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( *pReadScan++ ) )/255 ); - pReadScan++; -#else - if( pAlphaReadAcc ) - nAlpha = data[ nOff + 3 ]; - else - nAlpha = data[ nOff + 3 ] = 255; - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 2 ] ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 1 ] ) )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*( pReadScan[ 0 ] ) )/255 ); - pReadScan += 4; - nOff++; -#endif - } - break; - default: - SAL_INFO( "canvas.cairo", "fallback to GetColor - slow, format: " << static_cast<int>(pBitmapReadAcc->GetScanlineFormat()) ); - - if( pAlphaReadAcc ) - if( readAlpha( pAlphaReadAcc, nY, nWidth, data, nOff ) ) - bIsAlpha = true; - - for( nX = 0; nX < nWidth; nX++ ) - { - aColor = pBitmapReadAcc->GetColor( nY, nX ).GetColor(); - - // cairo need premultiplied color values - // TODO(rodo) handle endianness -#ifdef OSL_BIGENDIAN - if( pAlphaReadAcc ) - nAlpha = data[ nOff++ ]; - else - nAlpha = data[ nOff++ ] = 255; - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetRed() )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetGreen() )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetBlue() )/255 ); -#else - if( pAlphaReadAcc ) - nAlpha = data[ nOff + 3 ]; - else - nAlpha = data[ nOff + 3 ] = 255; - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetBlue() )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetGreen() )/255 ); - data[ nOff++ ] = sal::static_int_cast<unsigned char>(( nAlpha*aColor.GetRed() )/255 ); - nOff ++; -#endif - } - } - } - - ::Bitmap::ReleaseAccess( pBitmapReadAcc ); - if( pAlphaReadAcc ) - aAlpha.ReleaseAccess( pAlphaReadAcc ); + vcl::bitmap::CanvasCairoExtractBitmapData(aBmpEx, aBitmap, data, bHasAlpha); + const long nWidth = aBmpEx.GetPrefSize().Width(); + const long nHeight = aBmpEx.GetPrefSize().Height(); SurfaceSharedPtr pImageSurface = rSurfaceProvider->getOutputDevice()->CreateSurface( CairoSurfaceSharedPtr( cairo_image_surface_create_for_data( data, - bIsAlpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, + bHasAlpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, nWidth, nHeight, nWidth*4 ), &cairo_surface_destroy) ); pSurface = pImageSurface; - bHasAlpha = bIsAlpha; - - SAL_INFO( "canvas.cairo","image: " << nWidth << " x " << nHeight << " alpha: " << bIsAlpha << " alphaRead " << std::hex << pAlphaReadAcc); + SAL_INFO( "canvas.cairo","image: " << nWidth << " x " << nHeight << " alpha: " << bHasAlpha); } } |