1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <canvas/debug.hxx>
21 #include <canvas/canvastools.hxx>
22 #include <cppuhelper/supportsservice.hxx>
23 #include <tools/diagnose_ex.h>
25 #include "cairo_canvasbitmap.hxx"
27 #include <vcl/bmpacc.hxx>
28 #include <vcl/bitmapex.hxx>
30 using namespace ::cairo
;
31 using namespace ::com::sun::star
;
35 CanvasBitmap::CanvasBitmap( const ::basegfx::B2ISize
& rSize
,
36 const SurfaceProviderRef
& rSurfaceProvider
,
37 rendering::XGraphicDevice
* pDevice
,
39 mpSurfaceProvider( rSurfaceProvider
),
45 ENSURE_OR_THROW( mpSurfaceProvider
.is(),
46 "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
50 "bitmap size: " << rSize
.getX() << "x" << rSize
.getY());
52 mpBufferSurface
= mpSurfaceProvider
->createSurface( rSize
, bHasAlpha
? CAIRO_CONTENT_COLOR_ALPHA
: CAIRO_CONTENT_COLOR
);
53 mpBufferCairo
= mpBufferSurface
->getCairo();
55 maCanvasHelper
.init( rSize
, *mpSurfaceProvider
, pDevice
);
56 maCanvasHelper
.setSurface( mpBufferSurface
, bHasAlpha
);
58 // clear bitmap to 100% transparent
59 maCanvasHelper
.clear();
62 void CanvasBitmap::disposeThis()
64 mpSurfaceProvider
.clear();
66 mpBufferCairo
.reset();
67 mpBufferSurface
.reset();
70 CanvasBitmap_Base::disposeThis();
73 SurfaceSharedPtr
CanvasBitmap::getSurface()
75 return mpBufferSurface
;
78 SurfaceSharedPtr
CanvasBitmap::createSurface( const ::basegfx::B2ISize
& rSize
, int aContent
)
80 return mpSurfaceProvider
->createSurface(rSize
,aContent
);
83 SurfaceSharedPtr
CanvasBitmap::createSurface( ::Bitmap
& rBitmap
)
85 return mpSurfaceProvider
->createSurface(rBitmap
);
88 SurfaceSharedPtr
CanvasBitmap::changeSurface( bool, bool )
90 // non-modifiable surface here
91 return SurfaceSharedPtr();
94 OutputDevice
* CanvasBitmap::getOutputDevice()
96 return mpSurfaceProvider
->getOutputDevice();
99 bool CanvasBitmap::repaint( const SurfaceSharedPtr
& pSurface
,
100 const rendering::ViewState
& viewState
,
101 const rendering::RenderState
& renderState
)
103 return maCanvasHelper
.repaint( pSurface
, viewState
, renderState
);
106 uno::Any SAL_CALL
CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle
) throw (uno::RuntimeException
, std::exception
)
108 uno::Any
aRV( sal_Int32(0) );
109 // 0 ... get BitmapEx
110 // 1 ... get Pixbuf with bitmap RGB content
111 // 2 ... get Pixbuf with bitmap alpha mask
116 aRV
= uno::Any( reinterpret_cast<sal_Int64
>( (BitmapEx
*) NULL
) );
120 ::Size
aSize( maSize
.getX(), maSize
.getY() );
121 // FIXME: if we could teach VCL/ about cairo handles, life could
122 // be significantly better here perhaps.
123 cairo_surface_t
*pPixels
;
124 pPixels
= cairo_image_surface_create( CAIRO_FORMAT_ARGB32
,
125 aSize
.Width(), aSize
.Height() );
126 cairo_t
*pCairo
= cairo_create( pPixels
);
127 if( !pPixels
|| !pCairo
|| cairo_status(pCairo
) != CAIRO_STATUS_SUCCESS
)
130 // suck ourselves from the X server to this buffer so then we can fiddle with
131 // Alpha to turn it into the ultra-lame vcl required format and then push it
132 // all back again later at vast expense [ urgh ]
133 cairo_set_source_surface( pCairo
, getSurface()->getCairoSurface().get(), 0, 0 );
134 cairo_set_operator( pCairo
, CAIRO_OPERATOR_SOURCE
);
135 cairo_paint( pCairo
);
137 ::Bitmap
aRGB( aSize
, 24 );
138 ::AlphaMask
aMask( aSize
);
140 BitmapWriteAccess
*pRGBWrite( aRGB
.AcquireWriteAccess() );
143 BitmapWriteAccess
*pMaskWrite( aMask
.AcquireWriteAccess() );
146 cairo_surface_flush(pPixels
);
147 unsigned char *pSrc
= cairo_image_surface_get_data( pPixels
);
148 unsigned int nStride
= cairo_image_surface_get_stride( pPixels
);
149 for( unsigned long y
= 0; y
< (unsigned long) aSize
.Height(); y
++ )
151 sal_uInt32
*pPix
= reinterpret_cast<sal_uInt32
*>(pSrc
+ nStride
* y
);
152 for( unsigned long x
= 0; x
< (unsigned long) aSize
.Width(); x
++ )
154 sal_uInt8 nAlpha
= (*pPix
>> 24);
155 sal_uInt8 nR
= (*pPix
>> 16) & 0xff;
156 sal_uInt8 nG
= (*pPix
>> 8) & 0xff;
157 sal_uInt8 nB
= *pPix
& 0xff;
158 if( nAlpha
!= 0 && nAlpha
!= 255 )
160 // Cairo uses pre-multiplied alpha - we do not => re-multiply
161 nR
= (sal_uInt8
) MinMax( ((sal_uInt32
)nR
* 255) / nAlpha
, 0, 255 );
162 nG
= (sal_uInt8
) MinMax( ((sal_uInt32
)nG
* 255) / nAlpha
, 0, 255 );
163 nB
= (sal_uInt8
) MinMax( ((sal_uInt32
)nB
* 255) / nAlpha
, 0, 255 );
165 pRGBWrite
->SetPixel( y
, x
, BitmapColor( nR
, nG
, nB
) );
166 pMaskWrite
->SetPixelIndex( y
, x
, 255 - nAlpha
);
170 aMask
.ReleaseAccess( pMaskWrite
);
172 ::Bitmap::ReleaseAccess( pRGBWrite
);
175 // ignore potential errors above. will get caller a
176 // uniformely white bitmap, but not that there would
177 // be error handling in calling code ...
178 ::BitmapEx
*pBitmapEx
= new ::BitmapEx( aRGB
, aMask
);
180 cairo_destroy( pCairo
);
181 cairo_surface_destroy( pPixels
);
183 aRV
= uno::Any( reinterpret_cast<sal_Int64
>( pBitmapEx
) );
188 aRV
= getOutputDevice()->GetNativeSurfaceHandle(mpBufferSurface
, maSize
);
193 // Always return nothing - for the RGB surface support.
194 // Alpha code paths go via the above case 0.
203 OUString SAL_CALL
CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException
, std::exception
)
205 return OUString( "CairoCanvas.CanvasBitmap" );
208 sal_Bool SAL_CALL
CanvasBitmap::supportsService( const OUString
& ServiceName
) throw (uno::RuntimeException
, std::exception
)
210 return cppu::supportsService( this, ServiceName
);
213 uno::Sequence
< OUString
> SAL_CALL
CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException
, std::exception
)
215 uno::Sequence
< OUString
> aRet(1);
216 aRet
[0] = "com.sun.star.rendering.CanvasBitmap";
223 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */