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