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