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 #elif defined OS2 41 #else 42 # error Native API needed. 43 #endif 44 45 using namespace ::cairo; 46 using namespace ::com::sun::star; 47 48 #ifdef CAIRO_HAS_WIN32_SURFACE 49 namespace 50 { surface2HBitmap(const SurfaceSharedPtr & rSurface,const basegfx::B2ISize & rSize)51 HBITMAP surface2HBitmap( const SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize ) 52 { 53 // can't seem to retrieve HBITMAP from cairo. copy content then 54 HDC hScreenDC=GetDC(NULL); 55 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, 56 rSize.getX(), 57 rSize.getY() ); 58 59 HDC hBmpDC = CreateCompatibleDC( 0 ); 60 HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hBmpBitmap ); 61 62 BitBlt( hBmpDC, 0, 0, rSize.getX(), rSize.getX(), 63 cairo_win32_surface_get_dc(rSurface->getCairoSurface().get()), 64 0, 0, SRCCOPY ); 65 66 SelectObject( hBmpDC, hBmpOld ); 67 DeleteDC( hBmpDC ); 68 69 return hBmpBitmap; 70 } 71 } 72 #endif 73 74 namespace cairocanvas 75 { CanvasBitmap(const::basegfx::B2ISize & rSize,const SurfaceProviderRef & rSurfaceProvider,rendering::XGraphicDevice * pDevice,bool bHasAlpha)76 CanvasBitmap::CanvasBitmap( const ::basegfx::B2ISize& rSize, 77 const SurfaceProviderRef& rSurfaceProvider, 78 rendering::XGraphicDevice* pDevice, 79 bool bHasAlpha ) : 80 mpSurfaceProvider( rSurfaceProvider ), 81 mpBufferSurface(), 82 mpBufferCairo(), 83 maSize(rSize), 84 mbHasAlpha(bHasAlpha) 85 { 86 ENSURE_OR_THROW( mpSurfaceProvider.is(), 87 "CanvasBitmap::CanvasBitmap(): Invalid surface or device" ); 88 89 OSL_TRACE( "bitmap size: %dx%d", rSize.getX(), rSize.getY() ); 90 91 mpBufferSurface = mpSurfaceProvider->createSurface( rSize, bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR ); 92 mpBufferCairo = mpBufferSurface->getCairo(); 93 94 maCanvasHelper.init( rSize, *mpSurfaceProvider, pDevice ); 95 maCanvasHelper.setSurface( mpBufferSurface, bHasAlpha ); 96 97 // clear bitmap to 100% transparent 98 maCanvasHelper.clear(); 99 } 100 disposing()101 void SAL_CALL CanvasBitmap::disposing() 102 { 103 mpSurfaceProvider.clear(); 104 105 mpBufferCairo.reset(); 106 mpBufferSurface.reset(); 107 108 // forward to parent 109 CanvasBitmap_Base::disposing(); 110 } 111 getSurface()112 SurfaceSharedPtr CanvasBitmap::getSurface() 113 { 114 return mpBufferSurface; 115 } 116 createSurface(const::basegfx::B2ISize & rSize,Content aContent)117 SurfaceSharedPtr CanvasBitmap::createSurface( const ::basegfx::B2ISize& rSize, Content aContent ) 118 { 119 return mpSurfaceProvider->createSurface(rSize,aContent); 120 } 121 createSurface(::Bitmap & rBitmap)122 SurfaceSharedPtr CanvasBitmap::createSurface( ::Bitmap& rBitmap ) 123 { 124 return mpSurfaceProvider->createSurface(rBitmap); 125 } 126 changeSurface(bool,bool)127 SurfaceSharedPtr CanvasBitmap::changeSurface( bool, bool ) 128 { 129 // non-modifiable surface here 130 return SurfaceSharedPtr(); 131 } 132 getOutputDevice()133 OutputDevice* CanvasBitmap::getOutputDevice() 134 { 135 return mpSurfaceProvider->getOutputDevice(); 136 } 137 repaint(const SurfaceSharedPtr & pSurface,const rendering::ViewState & viewState,const rendering::RenderState & renderState)138 bool CanvasBitmap::repaint( const SurfaceSharedPtr& pSurface, 139 const rendering::ViewState& viewState, 140 const rendering::RenderState& renderState ) 141 { 142 return maCanvasHelper.repaint( pSurface, viewState, renderState ); 143 } 144 getFastPropertyValue(sal_Int32 nHandle)145 uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException) 146 { 147 uno::Any aRV( sal_Int32(0) ); 148 // 0 ... get BitmapEx 149 // 1 ... get Pixbuf with bitmap RGB content 150 // 2 ... get Pixbuf with bitmap alpha mask 151 switch( nHandle ) 152 { 153 case 0: 154 { 155 aRV = uno::Any( reinterpret_cast<sal_Int64>( (BitmapEx*) NULL ) ); 156 break; 157 } 158 case 1: 159 { 160 #ifdef CAIRO_HAS_XLIB_SURFACE 161 X11Surface* pXlibSurface=dynamic_cast<X11Surface*>(mpBufferSurface.get()); 162 OSL_ASSERT(pXlibSurface); 163 uno::Sequence< uno::Any > args( 3 ); 164 args[0] = uno::Any( false ); // do not call XFreePixmap on it 165 args[1] = uno::Any( pXlibSurface->getPixmap()->mhDrawable ); 166 args[2] = uno::Any( sal_Int32( pXlibSurface->getDepth() ) ); 167 168 aRV = uno::Any( args ); 169 #elif defined CAIRO_HAS_QUARTZ_SURFACE 170 QuartzSurface* pQuartzSurface = dynamic_cast<QuartzSurface*>(mpBufferSurface.get()); 171 OSL_ASSERT(pQuartzSurface); 172 uno::Sequence< uno::Any > args( 1 ); 173 args[0] = uno::Any( sal_IntPtr (pQuartzSurface->getCGContext()) ); 174 aRV = uno::Any( args ); 175 #elif defined CAIRO_HAS_WIN32_SURFACE 176 // TODO(F2): check whether under all circumstances, 177 // the alpha channel is ignored here. 178 uno::Sequence< uno::Any > args( 1 ); 179 args[1] = uno::Any( sal_Int64(surface2HBitmap(mpBufferSurface,maSize)) ); 180 181 aRV = uno::Any( args ); 182 // caller frees the bitmap 183 #elif defined CAIRO_HAS_OS2_SURFACE 184 OSL_TRACE( "CanvasBitmap::getFastPropertyValue case 1"); 185 #else 186 # error Please define fast prop retrieval for your platform! 187 #endif 188 break; 189 } 190 case 2: 191 { 192 #ifdef CAIRO_HAS_XLIB_SURFACE 193 uno::Sequence< uno::Any > args( 3 ); 194 SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR ); 195 CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo(); 196 X11Surface* pXlibSurface=dynamic_cast<X11Surface*>(pAlphaSurface.get()); 197 OSL_ASSERT(pXlibSurface); 198 199 // create RGB image (levels of gray) of alpha channel of original picture 200 cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 ); 201 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE ); 202 cairo_paint( pAlphaCairo.get() ); 203 cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 ); 204 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR ); 205 cairo_paint( pAlphaCairo.get() ); 206 pAlphaCairo.reset(); 207 208 X11PixmapSharedPtr pPixmap = pXlibSurface->getPixmap(); 209 args[0] = uno::Any( true ); 210 args[1] = ::com::sun::star::uno::Any( pPixmap->mhDrawable ); 211 args[2] = ::com::sun::star::uno::Any( sal_Int32( pXlibSurface->getDepth () ) ); 212 pPixmap->clear(); // caller takes ownership of pixmap 213 214 // return pixmap and alphachannel pixmap - it will be used in BitmapEx 215 aRV = uno::Any( args ); 216 #elif defined CAIRO_HAS_QUARTZ_SURFACE 217 SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR ); 218 CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo(); 219 QuartzSurface* pQuartzSurface=dynamic_cast<QuartzSurface*>(pAlphaSurface.get()); 220 OSL_ASSERT(pQuartzSurface); 221 222 // create RGB image (levels of gray) of alpha channel of original picture 223 cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 ); 224 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE ); 225 cairo_paint( pAlphaCairo.get() ); 226 cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 ); 227 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR ); 228 cairo_paint( pAlphaCairo.get() ); 229 pAlphaCairo.reset(); 230 231 uno::Sequence< uno::Any > args( 1 ); 232 args[0] = uno::Any( sal_IntPtr (pQuartzSurface->getCGContext()) ); 233 // return ??? and alphachannel ??? - it will be used in BitmapEx 234 aRV = uno::Any( args ); 235 #elif defined CAIRO_HAS_WIN32_SURFACE 236 SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR ); 237 CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo(); 238 239 // create RGB image (levels of gray) of alpha channel of original picture 240 cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 ); 241 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE ); 242 cairo_paint( pAlphaCairo.get() ); 243 cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 ); 244 cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR ); 245 cairo_paint( pAlphaCairo.get() ); 246 pAlphaCairo.reset(); 247 248 // can't seem to retrieve HBITMAP from cairo. copy content then 249 uno::Sequence< uno::Any > args( 1 ); 250 args[1] = uno::Any( sal_Int64(surface2HBitmap(pAlphaSurface,maSize)) ); 251 252 aRV = uno::Any( args ); 253 // caller frees the bitmap 254 #elif defined CAIRO_HAS_OS2_SURFACE 255 OSL_TRACE( "CanvasBitmap::getFastPropertyValue case 2"); 256 #else 257 # error Please define fast prop retrieval for your platform! 258 #endif 259 break; 260 } 261 } 262 263 return aRV; 264 } 265 266 #define IMPLEMENTATION_NAME "CairoCanvas.CanvasBitmap" 267 #define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap" 268 getImplementationName()269 ::rtl::OUString SAL_CALL CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException) 270 { 271 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) ); 272 } 273 supportsService(const::rtl::OUString & ServiceName)274 sal_Bool SAL_CALL CanvasBitmap::supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException) 275 { 276 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) ); 277 } 278 getSupportedServiceNames()279 uno::Sequence< ::rtl::OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException) 280 { 281 uno::Sequence< ::rtl::OUString > aRet(1); 282 aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) ); 283 284 return aRet; 285 } 286 287 } 288