fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / canvas / source / cairo / cairo_canvasbitmap.cxx
blob496b5cfe794d59eec8ef26a8e106f3af68f88f99
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <tools/diagnose_ex.h>
24 #include "cairo_canvasbitmap.hxx"
26 #include <vcl/bmpacc.hxx>
27 #include <vcl/bitmapex.hxx>
29 #ifdef CAIRO_HAS_XLIB_SURFACE
30 # include "cairo_xlib_cairo.hxx"
31 #elif defined CAIRO_HAS_QUARTZ_SURFACE
32 # include "cairo_quartz_cairo.hxx"
33 #elif defined CAIRO_HAS_WIN32_SURFACE
34 # include "cairo_win32_cairo.hxx"
35 # include <cairo-win32.h>
36 #else
37 # error Native API needed.
38 #endif
40 using namespace ::cairo;
41 using namespace ::com::sun::star;
43 #ifdef CAIRO_HAS_WIN32_SURFACE
44 namespace
46 HBITMAP surface2HBitmap( const SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize )
48 // cant seem to retrieve HBITMAP from cairo. copy content then
49 HDC hScreenDC=GetDC(NULL);
50 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC,
51 rSize.getX(),
52 rSize.getY() );
54 HDC hBmpDC = CreateCompatibleDC( 0 );
55 HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hBmpBitmap );
57 BitBlt( hBmpDC, 0, 0, rSize.getX(), rSize.getX(),
58 cairo_win32_surface_get_dc(rSurface->getCairoSurface().get()),
59 0, 0, SRCCOPY );
61 SelectObject( hBmpDC, hBmpOld );
62 DeleteDC( hBmpDC );
64 return hBmpBitmap;
67 #endif
69 namespace cairocanvas
71 CanvasBitmap::CanvasBitmap( const ::basegfx::B2ISize& rSize,
72 const SurfaceProviderRef& rSurfaceProvider,
73 rendering::XGraphicDevice* pDevice,
74 bool bHasAlpha ) :
75 mpSurfaceProvider( rSurfaceProvider ),
76 mpBufferSurface(),
77 mpBufferCairo(),
78 maSize(rSize),
79 mbHasAlpha(bHasAlpha)
81 ENSURE_OR_THROW( mpSurfaceProvider.is(),
82 "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
84 OSL_TRACE( "bitmap size: %dx%d", rSize.getX(), rSize.getY() );
86 mpBufferSurface = mpSurfaceProvider->createSurface( rSize, bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
87 mpBufferCairo = mpBufferSurface->getCairo();
89 maCanvasHelper.init( rSize, *mpSurfaceProvider, pDevice );
90 maCanvasHelper.setSurface( mpBufferSurface, bHasAlpha );
92 // clear bitmap to 100% transparent
93 maCanvasHelper.clear();
96 void CanvasBitmap::disposeThis()
98 mpSurfaceProvider.clear();
100 mpBufferCairo.reset();
101 mpBufferSurface.reset();
103 // forward to parent
104 CanvasBitmap_Base::disposeThis();
107 SurfaceSharedPtr CanvasBitmap::getSurface()
109 return mpBufferSurface;
112 SurfaceSharedPtr CanvasBitmap::createSurface( const ::basegfx::B2ISize& rSize, Content aContent )
114 return mpSurfaceProvider->createSurface(rSize,aContent);
117 SurfaceSharedPtr CanvasBitmap::createSurface( ::Bitmap& rBitmap )
119 return mpSurfaceProvider->createSurface(rBitmap);
122 SurfaceSharedPtr CanvasBitmap::changeSurface( bool, bool )
124 // non-modifiable surface here
125 return SurfaceSharedPtr();
128 OutputDevice* CanvasBitmap::getOutputDevice()
130 return mpSurfaceProvider->getOutputDevice();
133 bool CanvasBitmap::repaint( const SurfaceSharedPtr& pSurface,
134 const rendering::ViewState& viewState,
135 const rendering::RenderState& renderState )
137 return maCanvasHelper.repaint( pSurface, viewState, renderState );
140 uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException)
142 uno::Any aRV( sal_Int32(0) );
143 // 0 ... get BitmapEx
144 // 1 ... get Pixbuf with bitmap RGB content
145 // 2 ... get Pixbuf with bitmap alpha mask
146 switch( nHandle )
148 case 0:
150 aRV = uno::Any( reinterpret_cast<sal_Int64>( (BitmapEx *) NULL ) );
151 if ( !mbHasAlpha )
152 break;
154 ::Size aSize( maSize.getX(), maSize.getY() );
155 // FIXME: if we could teach VCL/ about cairo handles, life could
156 // be significantly better here perhaps.
157 cairo_surface_t *pPixels;
158 pPixels = cairo_image_surface_create( CAIRO_FORMAT_ARGB32,
159 aSize.Width(), aSize.Height() );
160 cairo_t *pCairo = cairo_create( pPixels );
161 if( !pPixels || !pCairo )
162 break;
164 // suck ourselves from the X server to this buffer so then we can fiddle with
165 // Alpha to turn it into the ultra-lame vcl required format and then push it
166 // all back again later at vast expense [ urgh ]
167 cairo_set_source_surface( pCairo, getSurface()->getCairoSurface().get(), 0, 0 );
168 cairo_set_operator( pCairo, CAIRO_OPERATOR_SOURCE );
169 cairo_paint( pCairo );
171 ::Bitmap aRGB( aSize, 24 );
172 ::AlphaMask aMask( aSize );
174 BitmapWriteAccess *pRGBWrite( aRGB.AcquireWriteAccess() );
175 BitmapWriteAccess *pMaskWrite( aMask.AcquireWriteAccess() );
177 unsigned char *pSrc = cairo_image_surface_get_data( pPixels );
178 unsigned int nStride = cairo_image_surface_get_stride( pPixels );
179 for( unsigned long y = 0; y < (unsigned long) aSize.Height(); y++ )
181 sal_uInt32 *pPix = (sal_uInt32 *)(pSrc + nStride * y);
182 for( unsigned long x = 0; x < (unsigned long) aSize.Width(); x++ )
184 sal_uInt8 nAlpha = (*pPix >> 24);
185 sal_uInt8 nR = (*pPix >> 16) & 0xff;
186 sal_uInt8 nG = (*pPix >> 8) & 0xff;
187 sal_uInt8 nB = *pPix & 0xff;
188 if( nAlpha != 0 && nAlpha != 255 )
190 // fprintf (stderr, "From A(0x%.2x) 0x%.2x 0x%.2x 0x%.2x -> ",
191 // nAlpha, nR, nG, nB );
192 // Cairo uses pre-multiplied alpha - we do not => re-multiply
193 nR = (sal_uInt8) MinMax( ((sal_uInt32)nR * 255) / nAlpha, 0, 255 );
194 nG = (sal_uInt8) MinMax( ((sal_uInt32)nG * 255) / nAlpha, 0, 255 );
195 nB = (sal_uInt8) MinMax( ((sal_uInt32)nB * 255) / nAlpha, 0, 255 );
196 // fprintf (stderr, "0x%.2x 0x%.2x 0x%.2x\n", nR, nG, nB );
198 pRGBWrite->SetPixel( y, x, BitmapColor( nR, nG, nB ) );
199 pMaskWrite->SetPixelIndex( y, x, 255 - nAlpha );
200 pPix++;
203 aMask.ReleaseAccess( pMaskWrite );
204 aRGB.ReleaseAccess( pRGBWrite );
206 ::BitmapEx *pBitmapEx = new ::BitmapEx( aRGB, aMask );
208 cairo_surface_destroy( pPixels );
210 aRV = uno::Any( reinterpret_cast<sal_Int64>( pBitmapEx ) );
211 break;
213 case 1:
215 #ifdef CAIRO_HAS_XLIB_SURFACE
216 X11Surface* pXlibSurface=dynamic_cast<X11Surface*>(mpBufferSurface.get());
217 OSL_ASSERT(pXlibSurface);
218 uno::Sequence< uno::Any > args( 3 );
219 args[0] = uno::Any( false ); // do not call XFreePixmap on it
220 args[1] = uno::Any( pXlibSurface->getPixmap()->mhDrawable );
221 args[2] = uno::Any( sal_Int32( pXlibSurface->getDepth() ) );
223 aRV = uno::Any( args );
224 #elif defined CAIRO_HAS_QUARTZ_SURFACE
225 QuartzSurface* pQuartzSurface = dynamic_cast<QuartzSurface*>(mpBufferSurface.get());
226 OSL_ASSERT(pQuartzSurface);
227 uno::Sequence< uno::Any > args( 1 );
228 args[0] = uno::Any( sal_IntPtr (pQuartzSurface->getCGContext()) );
229 aRV = uno::Any( args );
230 #elif defined CAIRO_HAS_WIN32_SURFACE
231 // TODO(F2): check whether under all circumstances,
232 // the alpha channel is ignored here.
233 uno::Sequence< uno::Any > args( 1 );
234 args[1] = uno::Any( sal_Int64(surface2HBitmap(mpBufferSurface,maSize)) );
236 aRV = uno::Any( args );
237 // caller frees the bitmap
238 #else
239 # error Please define fast prop retrieval for your platform!
240 #endif
241 break;
243 case 2:
245 // Always return nothing - for the RGB surface support.
246 // Alpha code paths go via the above case 0.
247 aRV = uno::Any();
248 break;
252 return aRV;
255 #define IMPLEMENTATION_NAME "CairoCanvas.CanvasBitmap"
256 #define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap"
258 OUString SAL_CALL CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException)
260 return OUString( IMPLEMENTATION_NAME );
263 sal_Bool SAL_CALL CanvasBitmap::supportsService( const OUString& ServiceName ) throw (uno::RuntimeException)
265 return ServiceName == SERVICE_NAME;
268 uno::Sequence< OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException)
270 uno::Sequence< OUString > aRet(1);
271 aRet[0] = SERVICE_NAME;
273 return aRet;
278 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */