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