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 <cppuhelper/supportsservice.hxx>
|
||||||
#include <tools/diagnose_ex.h>
|
#include <tools/diagnose_ex.h>
|
||||||
#include <vcl/bitmapex.hxx>
|
#include <vcl/bitmapex.hxx>
|
||||||
#include <vcl/bitmapaccess.hxx>
|
#include <vcl/BitmapTools.hxx>
|
||||||
|
|
||||||
#include <canvas/canvastools.hxx>
|
#include <canvas/canvastools.hxx>
|
||||||
|
|
||||||
@@ -118,77 +118,12 @@ namespace cairocanvas
|
|||||||
if ( !mbHasAlpha )
|
if ( !mbHasAlpha )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
::Size aSize( maSize.getX(), maSize.getY() );
|
BitmapEx* pBitmapEx = vcl::bitmap::CreateFromCairoSurface(
|
||||||
// FIXME: if we could teach VCL/ about cairo handles, life could
|
::Size( maSize.getX(), maSize.getY() ),
|
||||||
// be significantly better here perhaps.
|
getSurface()->getCairoSurface().get());
|
||||||
cairo_surface_t *pPixels;
|
if (pBitmapEx)
|
||||||
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;
|
|
||||||
|
|
||||||
// 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 );
|
aRV <<= reinterpret_cast<sal_Int64>( pBitmapEx );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
|
@@ -10,10 +10,14 @@
|
|||||||
#ifndef INCLUDED_VCL_BITMAP_TOOLS_HXX
|
#ifndef INCLUDED_VCL_BITMAP_TOOLS_HXX
|
||||||
#define INCLUDED_VCL_BITMAP_TOOLS_HXX
|
#define INCLUDED_VCL_BITMAP_TOOLS_HXX
|
||||||
|
|
||||||
|
#include <config_cairo_canvas.h>
|
||||||
#include <vcl/bitmapex.hxx>
|
#include <vcl/bitmapex.hxx>
|
||||||
#include <vcl/ImageTree.hxx>
|
#include <vcl/ImageTree.hxx>
|
||||||
#include <vcl/salbtype.hxx>
|
#include <vcl/salbtype.hxx>
|
||||||
#include <tools/stream.hxx>
|
#include <tools/stream.hxx>
|
||||||
|
#if ENABLE_CAIRO_CANVAS
|
||||||
|
#include <vcl/cairo.hxx>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace vcl {
|
namespace vcl {
|
||||||
namespace bitmap {
|
namespace bitmap {
|
||||||
@@ -66,6 +70,10 @@ BitmapEx VCL_DLLPUBLIC CreateFromData( sal_uInt8 const *pData, sal_Int32 nWidth,
|
|||||||
|
|
||||||
BitmapEx VCL_DLLPUBLIC CreateFromData( RawBitmap && data );
|
BitmapEx VCL_DLLPUBLIC CreateFromData( RawBitmap && data );
|
||||||
|
|
||||||
|
#if ENABLE_CAIRO_CANVAS
|
||||||
|
VCL_DLLPUBLIC BitmapEx* CreateFromCairoSurface(Size size, cairo_surface_t* pSurface);
|
||||||
|
#endif
|
||||||
|
|
||||||
}} // end vcl::bitmap
|
}} // end vcl::bitmap
|
||||||
|
|
||||||
#endif // INCLUDED_VCL_BITMAP_TOOLS_HXX
|
#endif // INCLUDED_VCL_BITMAP_TOOLS_HXX
|
||||||
|
@@ -26,6 +26,9 @@
|
|||||||
#include <vcl/svapp.hxx>
|
#include <vcl/svapp.hxx>
|
||||||
#include <vcl/salbtype.hxx>
|
#include <vcl/salbtype.hxx>
|
||||||
#include <vcl/bitmapaccess.hxx>
|
#include <vcl/bitmapaccess.hxx>
|
||||||
|
#if ENABLE_CAIRO_CANVAS
|
||||||
|
#include <cairo.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace css;
|
using namespace css;
|
||||||
|
|
||||||
@@ -199,6 +202,80 @@ BitmapEx CreateFromData( RawBitmap&& rawBitmap )
|
|||||||
return aBmp;
|
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
|
}} // end vcl::bitmap
|
||||||
|
|
||||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||||
|
Reference in New Issue
Block a user