update dev300-m58
[ooovba.git] / canvas / source / cairo / cairo_canvasbitmap.cxx
blob59fcf7768fd3547889c9d6abdafb250b0613c0fe
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cairo_canvasbitmap.cxx,v $
10 * $Revision: 1.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_canvas.hxx"
34 #include <canvas/debug.hxx>
35 #include <canvas/canvastools.hxx>
36 #include <tools/diagnose_ex.h>
38 #include "cairo_canvasbitmap.hxx"
40 #ifdef CAIRO_HAS_XLIB_SURFACE
41 # include "cairo_xlib_cairo.hxx"
42 #elif defined CAIRO_HAS_QUARTZ_SURFACE
43 # include "cairo_quartz_cairo.hxx"
44 #elif defined CAIRO_HAS_WIN32_SURFACE
45 # include "cairo_win32_cairo.hxx"
46 # include <cairo-win32.h>
47 #else
48 # error Native API needed.
49 #endif
51 using namespace ::cairo;
52 using namespace ::com::sun::star;
54 #ifdef CAIRO_HAS_WIN32_SURFACE
55 namespace
57 HBITMAP surface2HBitmap( const SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize )
59 // cant seem to retrieve HBITMAP from cairo. copy content then
60 HDC hScreenDC=GetDC(NULL);
61 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC,
62 rSize.getX(),
63 rSize.getY() );
65 HDC hBmpDC = CreateCompatibleDC( 0 );
66 HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hBmpBitmap );
68 BitBlt( hBmpDC, 0, 0, rSize.getX(), rSize.getX(),
69 cairo_win32_surface_get_dc(rSurface->getCairoSurface().get()),
70 0, 0, SRCCOPY );
72 SelectObject( hBmpDC, hBmpOld );
73 DeleteDC( hBmpDC );
75 return hBmpBitmap;
78 #endif
80 namespace cairocanvas
82 CanvasBitmap::CanvasBitmap( const ::basegfx::B2ISize& rSize,
83 const SurfaceProviderRef& rSurfaceProvider,
84 rendering::XGraphicDevice* pDevice,
85 bool bHasAlpha ) :
86 mpSurfaceProvider( rSurfaceProvider ),
87 mpBufferSurface(),
88 mpBufferCairo(),
89 maSize(rSize),
90 mbHasAlpha(bHasAlpha)
92 ENSURE_OR_THROW( mpSurfaceProvider.is(),
93 "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
95 OSL_TRACE( "bitmap size: %dx%d", rSize.getX(), rSize.getY() );
97 mpBufferSurface = mpSurfaceProvider->createSurface( rSize, bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
98 mpBufferCairo = mpBufferSurface->getCairo();
100 maCanvasHelper.init( rSize, *mpSurfaceProvider, pDevice );
101 maCanvasHelper.setSurface( mpBufferSurface, bHasAlpha );
103 // clear bitmap to 100% transparent
104 maCanvasHelper.clear();
107 void SAL_CALL CanvasBitmap::disposing()
109 mpSurfaceProvider.clear();
111 mpBufferCairo.reset();
112 mpBufferSurface.reset();
114 // forward to parent
115 CanvasBitmap_Base::disposing();
118 SurfaceSharedPtr CanvasBitmap::getSurface()
120 return mpBufferSurface;
123 SurfaceSharedPtr CanvasBitmap::createSurface( const ::basegfx::B2ISize& rSize, Content aContent )
125 return mpSurfaceProvider->createSurface(rSize,aContent);
128 SurfaceSharedPtr CanvasBitmap::createSurface( ::Bitmap& rBitmap )
130 return mpSurfaceProvider->createSurface(rBitmap);
133 SurfaceSharedPtr CanvasBitmap::changeSurface( bool, bool )
135 // non-modifiable surface here
136 return SurfaceSharedPtr();
139 OutputDevice* CanvasBitmap::getOutputDevice()
141 return mpSurfaceProvider->getOutputDevice();
144 bool CanvasBitmap::repaint( const SurfaceSharedPtr& pSurface,
145 const rendering::ViewState& viewState,
146 const rendering::RenderState& renderState )
148 return maCanvasHelper.repaint( pSurface, viewState, renderState );
151 uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException)
153 uno::Any aRV( sal_Int32(0) );
154 // 0 ... get BitmapEx
155 // 1 ... get Pixbuf with bitmap RGB content
156 // 2 ... get Pixbuf with bitmap alpha mask
157 switch( nHandle )
159 case 0:
161 aRV = uno::Any( reinterpret_cast<sal_Int64>( (BitmapEx*) NULL ) );
162 break;
164 case 1:
166 #ifdef CAIRO_HAS_XLIB_SURFACE
167 X11Surface* pXlibSurface=dynamic_cast<X11Surface*>(mpBufferSurface.get());
168 OSL_ASSERT(pXlibSurface);
169 uno::Sequence< uno::Any > args( 3 );
170 args[0] = uno::Any( false ); // do not call XFreePixmap on it
171 args[1] = uno::Any( pXlibSurface->getPixmap()->mhDrawable );
172 args[2] = uno::Any( sal_Int32( pXlibSurface->getDepth() ) );
174 aRV = uno::Any( args );
175 #elif defined CAIRO_HAS_QUARTZ_SURFACE
176 QuartzSurface* pQuartzSurface = dynamic_cast<QuartzSurface*>(mpBufferSurface.get());
177 OSL_ASSERT(pQuartzSurface);
178 uno::Sequence< uno::Any > args( 1 );
179 args[0] = uno::Any( sal_IntPtr (pQuartzSurface->getCGContext()) );
180 aRV = uno::Any( args );
181 #elif defined CAIRO_HAS_WIN32_SURFACE
182 // TODO(F2): check whether under all circumstances,
183 // the alpha channel is ignored here.
184 uno::Sequence< uno::Any > args( 1 );
185 args[1] = uno::Any( sal_Int64(surface2HBitmap(mpBufferSurface,maSize)) );
187 aRV = uno::Any( args );
188 // caller frees the bitmap
189 #else
190 # error Please define fast prop retrieval for your platform!
191 #endif
192 break;
194 case 2:
196 #ifdef CAIRO_HAS_XLIB_SURFACE
197 uno::Sequence< uno::Any > args( 3 );
198 SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR );
199 CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo();
200 X11Surface* pXlibSurface=dynamic_cast<X11Surface*>(pAlphaSurface.get());
201 OSL_ASSERT(pXlibSurface);
203 // create RGB image (levels of gray) of alpha channel of original picture
204 cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 );
205 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE );
206 cairo_paint( pAlphaCairo.get() );
207 cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 );
208 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR );
209 cairo_paint( pAlphaCairo.get() );
210 pAlphaCairo.reset();
212 X11PixmapSharedPtr pPixmap = pXlibSurface->getPixmap();
213 args[0] = uno::Any( true );
214 args[1] = ::com::sun::star::uno::Any( pPixmap->mhDrawable );
215 args[2] = ::com::sun::star::uno::Any( sal_Int32( pXlibSurface->getDepth () ) );
216 pPixmap->clear(); // caller takes ownership of pixmap
218 // return pixmap and alphachannel pixmap - it will be used in BitmapEx
219 aRV = uno::Any( args );
220 #elif defined CAIRO_HAS_QUARTZ_SURFACE
221 SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR );
222 CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo();
223 QuartzSurface* pQuartzSurface=dynamic_cast<QuartzSurface*>(pAlphaSurface.get());
224 OSL_ASSERT(pQuartzSurface);
226 // create RGB image (levels of gray) of alpha channel of original picture
227 cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 );
228 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE );
229 cairo_paint( pAlphaCairo.get() );
230 cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 );
231 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR );
232 cairo_paint( pAlphaCairo.get() );
233 pAlphaCairo.reset();
235 uno::Sequence< uno::Any > args( 1 );
236 args[0] = uno::Any( sal_IntPtr (pQuartzSurface->getCGContext()) );
237 // return ??? and alphachannel ??? - it will be used in BitmapEx
238 aRV = uno::Any( args );
239 #elif defined CAIRO_HAS_WIN32_SURFACE
240 SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR );
241 CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo();
243 // create RGB image (levels of gray) of alpha channel of original picture
244 cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 );
245 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE );
246 cairo_paint( pAlphaCairo.get() );
247 cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 );
248 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR );
249 cairo_paint( pAlphaCairo.get() );
250 pAlphaCairo.reset();
252 // cant seem to retrieve HBITMAP from cairo. copy content then
253 uno::Sequence< uno::Any > args( 1 );
254 args[1] = uno::Any( sal_Int64(surface2HBitmap(pAlphaSurface,maSize)) );
256 aRV = uno::Any( args );
257 // caller frees the bitmap
258 #else
259 # error Please define fast prop retrieval for your platform!
260 #endif
261 break;
265 return aRV;
268 #define IMPLEMENTATION_NAME "CairoCanvas.CanvasBitmap"
269 #define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap"
271 ::rtl::OUString SAL_CALL CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException)
273 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
276 sal_Bool SAL_CALL CanvasBitmap::supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException)
278 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
281 uno::Sequence< ::rtl::OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException)
283 uno::Sequence< ::rtl::OUString > aRet(1);
284 aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
286 return aRet;