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