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