From 32d8a32dcf85e2cee589ee19bc72b4abf73f9681 Mon Sep 17 00:00:00 2001 From: Noel Grandin Date: Wed, 14 Feb 2018 14:27:12 +0200 Subject: move cairo surface code from canvas to BitmapTools part of making Bitmap an implementation detail of vcl/ Change-Id: Ic4b8d114a8091041374a083b3b7ca2fa68757ab1 Reviewed-on: https://gerrit.libreoffice.org/49719 Tested-by: Jenkins Reviewed-by: Noel Grandin --- canvas/source/cairo/cairo_canvasbitmap.cxx | 77 +++--------------------------- include/vcl/BitmapTools.hxx | 8 ++++ vcl/source/bitmap/BitmapTools.cxx | 77 ++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 71 deletions(-) diff --git a/canvas/source/cairo/cairo_canvasbitmap.cxx b/canvas/source/cairo/cairo_canvasbitmap.cxx index 7894e2e978e2..27ce9af37758 100644 --- a/canvas/source/cairo/cairo_canvasbitmap.cxx +++ b/canvas/source/cairo/cairo_canvasbitmap.cxx @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include @@ -118,77 +118,12 @@ namespace cairocanvas if ( !mbHasAlpha ) break; - ::Size aSize( maSize.getX(), maSize.getY() ); - // FIXME: if we could teach VCL/ about cairo handles, life could - // be significantly better here perhaps. - cairo_surface_t *pPixels; - pPixels = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, - aSize.Width(), aSize.Height() ); - cairo_t *pCairo = cairo_create( pPixels ); - if( !pPixels || !pCairo || cairo_status(pCairo) != CAIRO_STATUS_SUCCESS ) - break; + BitmapEx* pBitmapEx = vcl::bitmap::CreateFromCairoSurface( + ::Size( maSize.getX(), maSize.getY() ), + getSurface()->getCairoSurface().get()); + if (pBitmapEx) + aRV <<= reinterpret_cast( pBitmapEx ); - // suck ourselves from the X server to this buffer so then we can fiddle with - // Alpha to turn it into the ultra-lame vcl required format and then push it - // all back again later at vast expense [ urgh ] - cairo_set_source_surface( pCairo, getSurface()->getCairoSurface().get(), 0, 0 ); - cairo_set_operator( pCairo, CAIRO_OPERATOR_SOURCE ); - cairo_paint( pCairo ); - - ::Bitmap aRGB( aSize, 24 ); - ::AlphaMask aMask( aSize ); - - BitmapWriteAccess *pRGBWrite( aRGB.AcquireWriteAccess() ); - if( pRGBWrite ) - { - BitmapWriteAccess *pMaskWrite( aMask.AcquireWriteAccess() ); - if( pMaskWrite ) - { - cairo_surface_flush(pPixels); - unsigned char *pSrc = cairo_image_surface_get_data( pPixels ); - unsigned int nStride = cairo_image_surface_get_stride( pPixels ); - for( unsigned long y = 0; y < static_cast(aSize.Height()); y++ ) - { - sal_uInt32 *pPix = reinterpret_cast(pSrc + nStride * y); - for( unsigned long x = 0; x < static_cast(aSize.Width()); x++ ) - { -#if defined OSL_BIGENDIAN - sal_uInt8 nB = (*pPix >> 24); - sal_uInt8 nG = (*pPix >> 16) & 0xff; - sal_uInt8 nR = (*pPix >> 8) & 0xff; - sal_uInt8 nAlpha = *pPix & 0xff; -#else - sal_uInt8 nAlpha = (*pPix >> 24); - sal_uInt8 nR = (*pPix >> 16) & 0xff; - sal_uInt8 nG = (*pPix >> 8) & 0xff; - sal_uInt8 nB = *pPix & 0xff; -#endif - if( nAlpha != 0 && nAlpha != 255 ) - { - // Cairo uses pre-multiplied alpha - we do not => re-multiply - nR = static_cast(MinMax( (static_cast(nR) * 255) / nAlpha, 0, 255 )); - nG = static_cast(MinMax( (static_cast(nG) * 255) / nAlpha, 0, 255 )); - nB = static_cast(MinMax( (static_cast(nB) * 255) / nAlpha, 0, 255 )); - } - pRGBWrite->SetPixel( y, x, BitmapColor( nR, nG, nB ) ); - pMaskWrite->SetPixelIndex( y, x, 255 - nAlpha ); - pPix++; - } - } - aMask.ReleaseAccess( pMaskWrite ); - } - ::Bitmap::ReleaseAccess( pRGBWrite ); - } - - // ignore potential errors above. will get caller a - // uniformely white bitmap, but not that there would - // be error handling in calling code ... - ::BitmapEx *pBitmapEx = new ::BitmapEx( aRGB, aMask ); - - cairo_destroy( pCairo ); - cairo_surface_destroy( pPixels ); - - aRV <<= reinterpret_cast( pBitmapEx ); break; } case 1: diff --git a/include/vcl/BitmapTools.hxx b/include/vcl/BitmapTools.hxx index f2cf5512dc6f..4caafb3545e4 100644 --- a/include/vcl/BitmapTools.hxx +++ b/include/vcl/BitmapTools.hxx @@ -10,10 +10,14 @@ #ifndef INCLUDED_VCL_BITMAP_TOOLS_HXX #define INCLUDED_VCL_BITMAP_TOOLS_HXX +#include #include #include #include #include +#if ENABLE_CAIRO_CANVAS +#include +#endif namespace vcl { namespace bitmap { @@ -66,6 +70,10 @@ BitmapEx VCL_DLLPUBLIC CreateFromData( sal_uInt8 const *pData, sal_Int32 nWidth, BitmapEx VCL_DLLPUBLIC CreateFromData( RawBitmap && data ); +#if ENABLE_CAIRO_CANVAS +VCL_DLLPUBLIC BitmapEx* CreateFromCairoSurface(Size size, cairo_surface_t* pSurface); +#endif + }} // end vcl::bitmap #endif // INCLUDED_VCL_BITMAP_TOOLS_HXX diff --git a/vcl/source/bitmap/BitmapTools.cxx b/vcl/source/bitmap/BitmapTools.cxx index 87c6b64fb56a..ee0aef4f1f67 100644 --- a/vcl/source/bitmap/BitmapTools.cxx +++ b/vcl/source/bitmap/BitmapTools.cxx @@ -26,6 +26,9 @@ #include #include #include +#if ENABLE_CAIRO_CANVAS +#include +#endif using namespace css; @@ -199,6 +202,80 @@ BitmapEx CreateFromData( RawBitmap&& rawBitmap ) return aBmp; } +#if ENABLE_CAIRO_CANVAS +BitmapEx* CreateFromCairoSurface(Size aSize, cairo_surface_t * pSurface) +{ + // FIXME: if we could teach VCL/ about cairo handles, life could + // be significantly better here perhaps. + cairo_surface_t *pPixels = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, + aSize.Width(), aSize.Height() ); + cairo_t *pCairo = cairo_create( pPixels ); + if( !pPixels || !pCairo || cairo_status(pCairo) != CAIRO_STATUS_SUCCESS ) + return nullptr; + + // suck ourselves from the X server to this buffer so then we can fiddle with + // Alpha to turn it into the ultra-lame vcl required format and then push it + // all back again later at vast expense [ urgh ] + cairo_set_source_surface( pCairo, pSurface, 0, 0 ); + cairo_set_operator( pCairo, CAIRO_OPERATOR_SOURCE ); + cairo_paint( pCairo ); + + ::Bitmap aRGB( aSize, 24 ); + ::AlphaMask aMask( aSize ); + + Bitmap::ScopedWriteAccess pRGBWrite(aRGB); + assert(pRGBWrite); + if (!pRGBWrite) + return nullptr; + + AlphaMask::ScopedWriteAccess pMaskWrite(aMask); + assert(pMaskWrite); + if (!pMaskWrite) + return nullptr; + + cairo_surface_flush(pPixels); + unsigned char *pSrc = cairo_image_surface_get_data( pPixels ); + unsigned int nStride = cairo_image_surface_get_stride( pPixels ); + for( unsigned long y = 0; y < static_cast(aSize.Height()); y++ ) + { + sal_uInt32 *pPix = reinterpret_cast(pSrc + nStride * y); + for( unsigned long x = 0; x < static_cast(aSize.Width()); x++ ) + { +#if defined OSL_BIGENDIAN + sal_uInt8 nB = (*pPix >> 24); + sal_uInt8 nG = (*pPix >> 16) & 0xff; + sal_uInt8 nR = (*pPix >> 8) & 0xff; + sal_uInt8 nAlpha = *pPix & 0xff; +#else + sal_uInt8 nAlpha = (*pPix >> 24); + sal_uInt8 nR = (*pPix >> 16) & 0xff; + sal_uInt8 nG = (*pPix >> 8) & 0xff; + sal_uInt8 nB = *pPix & 0xff; +#endif + if( nAlpha != 0 && nAlpha != 255 ) + { + // Cairo uses pre-multiplied alpha - we do not => re-multiply + nR = static_cast(MinMax( (static_cast(nR) * 255) / nAlpha, 0, 255 )); + nG = static_cast(MinMax( (static_cast(nG) * 255) / nAlpha, 0, 255 )); + nB = static_cast(MinMax( (static_cast(nB) * 255) / nAlpha, 0, 255 )); + } + pRGBWrite->SetPixel( y, x, BitmapColor( nR, nG, nB ) ); + pMaskWrite->SetPixelIndex( y, x, 255 - nAlpha ); + pPix++; + } + } + + // ignore potential errors above. will get caller a + // uniformly white bitmap, but not that there would + // be error handling in calling code ... + ::BitmapEx *pBitmapEx = new ::BitmapEx( aRGB, aMask ); + + cairo_destroy( pCairo ); + cairo_surface_destroy( pPixels ); + return pBitmapEx; +} +#endif + }} // end vcl::bitmap /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit