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