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 <tools/prex.h> 32 #include <X11/extensions/Xrender.h> 33 #include <X11/Xlib.h> 34 #include <tools/postx.h> 35 36 #include "cairo_xlib_cairo.hxx" 37 38 #include <vcl/sysdata.hxx> 39 #include <vcl/bitmap.hxx> 40 #include <vcl/virdev.hxx> 41 #include <basegfx/vector/b2isize.hxx> 42 43 namespace cairo 44 { 45 46 #include <cairo-xlib.h> 47 #include <cairo-xlib-xrender.h> 48 49 // TODO(F3): svp headless case! 50 51 bool IsCairoWorking( OutputDevice* pOutDev ) 52 { 53 if( !pOutDev ) 54 return false; 55 56 Display* pDisplay = (Display*)pOutDev->GetSystemGfxData().pDisplay; 57 int nDummy; 58 return XQueryExtension( pDisplay, "RENDER", &nDummy, &nDummy, &nDummy ); 59 } 60 61 X11SysData::X11SysData() : 62 pDisplay(NULL), 63 hDrawable(0), 64 pVisual(NULL), 65 nScreen(0), 66 nDepth(-1), 67 aColormap(-1), 68 pRenderFormat(NULL) 69 {} 70 71 X11SysData::X11SysData( const SystemGraphicsData& pSysDat ) : 72 pDisplay(pSysDat.pDisplay), 73 hDrawable(pSysDat.hDrawable), 74 pVisual(pSysDat.pVisual), 75 nScreen(pSysDat.nScreen), 76 nDepth(pSysDat.nDepth), 77 aColormap(pSysDat.aColormap), 78 pRenderFormat(pSysDat.pRenderFormat) 79 {} 80 81 X11SysData::X11SysData( const SystemEnvData& pSysDat ) : 82 pDisplay(pSysDat.pDisplay), 83 hDrawable(pSysDat.aWindow), 84 pVisual(pSysDat.pVisual), 85 nScreen(pSysDat.nScreen), 86 nDepth(pSysDat.nDepth), 87 aColormap(pSysDat.aColormap), 88 pRenderFormat(NULL) 89 {} 90 91 X11Pixmap::~X11Pixmap() 92 { 93 if( mpDisplay && mhDrawable ) 94 XFreePixmap( (Display*)mpDisplay, mhDrawable ); 95 } 96 97 /** 98 * Surface::Surface: Create Canvas surface with existing data 99 * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) 100 * @param pSurface Cairo surface 101 * 102 * pSysData contains the platform native Drawable reference 103 * This constructor only stores data, it does no processing. 104 * It is used by e.g. Surface::getSimilar() 105 * 106 * Set the mpSurface as pSurface 107 **/ 108 X11Surface::X11Surface( const X11SysData& rSysData, 109 const X11PixmapSharedPtr& rPixmap, 110 const CairoSurfaceSharedPtr& pSurface ) : 111 maSysData(rSysData), 112 mpPixmap(rPixmap), 113 mpSurface(pSurface) 114 {} 115 116 /** 117 * Surface::Surface: Create generic Canvas surface using given Cairo Surface 118 * 119 * @param pSurface Cairo Surface 120 * 121 * This constructor only stores data, it does no processing. 122 * It is used with e.g. cairo_image_surface_create_for_data() 123 * Unlike other constructors, mpSysData is set to NULL 124 * 125 * Set the mpSurface as pSurface 126 **/ 127 X11Surface::X11Surface( const CairoSurfaceSharedPtr& pSurface ) : 128 maSysData(), 129 mpPixmap(), 130 mpSurface(pSurface) 131 {} 132 133 /** 134 * Surface::Surface: Create Canvas surface from Window reference. 135 * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) 136 * @param x horizontal location of the new surface 137 * @param y vertical location of the new surface 138 * @param width width of the new surface 139 * @param height height of the new surface 140 * 141 * pSysData contains the platform native Window reference. 142 * 143 * pSysData is used to create a surface on the Window 144 * 145 * Set the mpSurface to the new surface or NULL 146 **/ 147 X11Surface::X11Surface( const X11SysData& rSysData, int x, int y, int width, int height ) : 148 maSysData(rSysData), 149 mpPixmap(), 150 mpSurface( 151 cairo_xlib_surface_create( (Display*)rSysData.pDisplay, 152 rSysData.hDrawable, 153 (Visual*)rSysData.pVisual, 154 width + x, height + y ), 155 &cairo_surface_destroy) 156 { 157 cairo_surface_set_device_offset(mpSurface.get(), x, y ); 158 } 159 160 /** 161 * Surface::Surface: Create platfrom native Canvas surface from BitmapSystemData 162 * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) 163 * @param pBmpData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx) 164 * @param width width of the new surface 165 * @param height height of the new surface 166 * 167 * The pBmpData provides the imagedata that the created surface should contain. 168 * 169 * Set the mpSurface to the new surface or NULL 170 **/ 171 X11Surface::X11Surface( const X11SysData& rSysData, 172 const BitmapSystemData& rData ) : 173 maSysData( rSysData ), 174 mpPixmap(), 175 mpSurface( 176 cairo_xlib_surface_create( (Display*)rSysData.pDisplay, 177 (Drawable)rData.aPixmap, 178 (Visual*) rSysData.pVisual, 179 rData.mnWidth, rData.mnHeight ), 180 &cairo_surface_destroy) 181 { 182 } 183 184 /** 185 * Surface::getCairo: Create Cairo (drawing object) for the Canvas surface 186 * 187 * @return new Cairo or NULL 188 **/ 189 CairoSharedPtr X11Surface::getCairo() const 190 { 191 return CairoSharedPtr( cairo_create(mpSurface.get()), 192 &cairo_destroy ); 193 } 194 195 /** 196 * Surface::getSimilar: Create new similar Canvas surface 197 * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h) 198 * @param width width of the new surface 199 * @param height height of the new surface 200 * 201 * Creates a new Canvas surface. This normally creates platform native surface, even though 202 * generic function is used. 203 * 204 * Cairo surface from aContent (cairo_content_t) 205 * 206 * @return new surface or NULL 207 **/ 208 SurfaceSharedPtr X11Surface::getSimilar( Content aContent, int width, int height ) const 209 { 210 Pixmap hPixmap; 211 212 if( maSysData.pDisplay && maSysData.hDrawable ) 213 { 214 XRenderPictFormat* pFormat; 215 int nFormat; 216 217 switch (aContent) 218 { 219 case CAIRO_CONTENT_ALPHA: 220 nFormat = PictStandardA8; 221 break; 222 case CAIRO_CONTENT_COLOR: 223 nFormat = PictStandardRGB24; 224 break; 225 case CAIRO_CONTENT_COLOR_ALPHA: 226 default: 227 nFormat = PictStandardARGB32; 228 break; 229 } 230 231 pFormat = XRenderFindStandardFormat( (Display*)maSysData.pDisplay, nFormat ); 232 hPixmap = XCreatePixmap( (Display*)maSysData.pDisplay, maSysData.hDrawable, 233 width > 0 ? width : 1, height > 0 ? height : 1, 234 pFormat->depth ); 235 236 X11SysData aSysData(maSysData); 237 aSysData.pRenderFormat = pFormat; 238 return SurfaceSharedPtr( 239 new X11Surface( aSysData, 240 X11PixmapSharedPtr( 241 new X11Pixmap(hPixmap, maSysData.pDisplay)), 242 CairoSurfaceSharedPtr( 243 cairo_xlib_surface_create_with_xrender_format( 244 (Display*)maSysData.pDisplay, 245 hPixmap, 246 ScreenOfDisplay((Display *)maSysData.pDisplay, maSysData.nScreen), 247 pFormat, width, height ), 248 &cairo_surface_destroy) )); 249 } 250 else 251 return SurfaceSharedPtr( 252 new X11Surface( maSysData, 253 X11PixmapSharedPtr(), 254 CairoSurfaceSharedPtr( 255 cairo_surface_create_similar( mpSurface.get(), aContent, width, height ), 256 &cairo_surface_destroy ))); 257 } 258 259 boost::shared_ptr<VirtualDevice> X11Surface::createVirtualDevice() const 260 { 261 SystemGraphicsData aSystemGraphicsData; 262 263 aSystemGraphicsData.nSize = sizeof(SystemGraphicsData); 264 aSystemGraphicsData.hDrawable = getDrawable(); 265 aSystemGraphicsData.pRenderFormat = getRenderFormat(); 266 267 return boost::shared_ptr<VirtualDevice>( 268 new VirtualDevice( &aSystemGraphicsData, getDepth() )); 269 } 270 271 /** 272 * Surface::Resize: Resizes the Canvas surface. 273 * @param width new width of the surface 274 * @param height new height of the surface 275 * 276 * Only used on X11. 277 * 278 * @return The new surface or NULL 279 **/ 280 void X11Surface::Resize( int width, int height ) 281 { 282 cairo_xlib_surface_set_size( mpSurface.get(), width, height ); 283 } 284 285 void X11Surface::flush() const 286 { 287 XSync( (Display*)maSysData.pDisplay, false ); 288 } 289 290 /** 291 * Surface::getDepth: Get the color depth of the Canvas surface. 292 * 293 * @return color depth 294 **/ 295 int X11Surface::getDepth() const 296 { 297 if( maSysData.pRenderFormat ) 298 return ((XRenderPictFormat*) maSysData.pRenderFormat)->depth; 299 300 return -1; 301 } 302 303 SurfaceSharedPtr createSurface( const CairoSurfaceSharedPtr& rSurface ) 304 { 305 return SurfaceSharedPtr(new X11Surface(rSurface)); 306 } 307 308 static X11SysData getSysData( const Window& rWindow ) 309 { 310 const SystemEnvData* pSysData = GetSysData(&rWindow); 311 312 if( !pSysData ) 313 return X11SysData(); 314 else 315 return X11SysData(*pSysData); 316 } 317 318 static X11SysData getSysData( const VirtualDevice& rVirDev ) 319 { 320 return X11SysData( rVirDev.GetSystemGfxData() ); 321 } 322 323 SurfaceSharedPtr createSurface( const OutputDevice& rRefDevice, 324 int x, int y, int width, int height ) 325 { 326 if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW ) 327 return SurfaceSharedPtr(new X11Surface(getSysData((const Window&)rRefDevice), 328 x,y,width,height)); 329 else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV ) 330 return SurfaceSharedPtr(new X11Surface(getSysData((const VirtualDevice&)rRefDevice), 331 x,y,width,height)); 332 else 333 return SurfaceSharedPtr(); 334 } 335 336 SurfaceSharedPtr createBitmapSurface( const OutputDevice& rRefDevice, 337 const BitmapSystemData& rData, 338 const Size& rSize ) 339 { 340 OSL_TRACE( "requested size: %d x %d available size: %d x %d", 341 rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight ); 342 if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() ) 343 { 344 if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW ) 345 return SurfaceSharedPtr(new X11Surface(getSysData((const Window&)rRefDevice), rData )); 346 else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV ) 347 return SurfaceSharedPtr(new X11Surface(getSysData((const VirtualDevice&)rRefDevice), rData )); 348 } 349 350 return SurfaceSharedPtr(); 351 } 352 } 353