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