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 <ci@libreoffice.org> Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <tools/diagnose_ex.h>
|
||||
#include <vcl/bitmapex.hxx>
|
||||
#include <vcl/bitmapaccess.hxx>
|
||||
#include <vcl/BitmapTools.hxx>
|
||||
|
||||
#include <canvas/canvastools.hxx>
|
||||
|
||||
@@ -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<sal_Int64>( 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<unsigned long>(aSize.Height()); y++ )
|
||||
{
|
||||
sal_uInt32 *pPix = reinterpret_cast<sal_uInt32 *>(pSrc + nStride * y);
|
||||
for( unsigned long x = 0; x < static_cast<unsigned long>(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<sal_uInt8>(MinMax( (static_cast<sal_uInt32>(nR) * 255) / nAlpha, 0, 255 ));
|
||||
nG = static_cast<sal_uInt8>(MinMax( (static_cast<sal_uInt32>(nG) * 255) / nAlpha, 0, 255 ));
|
||||
nB = static_cast<sal_uInt8>(MinMax( (static_cast<sal_uInt32>(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<sal_Int64>( pBitmapEx );
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
|
@@ -10,10 +10,14 @@
|
||||
#ifndef INCLUDED_VCL_BITMAP_TOOLS_HXX
|
||||
#define INCLUDED_VCL_BITMAP_TOOLS_HXX
|
||||
|
||||
#include <config_cairo_canvas.h>
|
||||
#include <vcl/bitmapex.hxx>
|
||||
#include <vcl/ImageTree.hxx>
|
||||
#include <vcl/salbtype.hxx>
|
||||
#include <tools/stream.hxx>
|
||||
#if ENABLE_CAIRO_CANVAS
|
||||
#include <vcl/cairo.hxx>
|
||||
#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
|
||||
|
@@ -26,6 +26,9 @@
|
||||
#include <vcl/svapp.hxx>
|
||||
#include <vcl/salbtype.hxx>
|
||||
#include <vcl/bitmapaccess.hxx>
|
||||
#if ENABLE_CAIRO_CANVAS
|
||||
#include <cairo.h>
|
||||
#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<unsigned long>(aSize.Height()); y++ )
|
||||
{
|
||||
sal_uInt32 *pPix = reinterpret_cast<sal_uInt32 *>(pSrc + nStride * y);
|
||||
for( unsigned long x = 0; x < static_cast<unsigned long>(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<sal_uInt8>(MinMax( (static_cast<sal_uInt32>(nR) * 255) / nAlpha, 0, 255 ));
|
||||
nG = static_cast<sal_uInt8>(MinMax( (static_cast<sal_uInt32>(nG) * 255) / nAlpha, 0, 255 ));
|
||||
nB = static_cast<sal_uInt8>(MinMax( (static_cast<sal_uInt32>(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: */
|
||||
|
Reference in New Issue
Block a user