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_cairo.hxx"
28 : #include "cairo_xlib_cairo.hxx"
29 :
30 : #include <vcl/sysdata.hxx>
31 : #include <vcl/bitmap.hxx>
32 : #include <vcl/virdev.hxx>
33 : #include <vcl/window.hxx>
34 : #include <basegfx/vector/b2isize.hxx>
35 :
36 : namespace
37 : {
38 2 : Pixmap limitXCreatePixmap(Display *display, Drawable d, unsigned int width, unsigned int height, unsigned int depth)
39 : {
40 : // The X protocol request CreatePixmap puts an upper bound
41 : // of 16 bit to the size. And in practice some drivers
42 : // fall over with values close to the max.
43 :
44 : // see, e.g. moz#424333, fdo#48961, rhbz#1086714
45 : // we've a duplicate of this in vcl :-(
46 2 : if (width > SAL_MAX_INT16-10 || height > SAL_MAX_INT16-10)
47 : {
48 : SAL_WARN("canvas", "overlarge pixmap: " << width << " x " << height);
49 0 : return None;
50 : }
51 2 : return XCreatePixmap(display, d, width, height, depth);
52 : }
53 : }
54 :
55 : namespace cairo
56 : {
57 :
58 : #include <cairo-xlib.h>
59 : #include <cairo-xlib-xrender.h>
60 :
61 2 : X11SysData::X11SysData() :
62 : pDisplay(NULL),
63 : hDrawable(0),
64 : pVisual(NULL),
65 : nScreen(0),
66 : nDepth(-1),
67 : aColormap(-1),
68 2 : pRenderFormat(NULL)
69 2 : {}
70 :
71 0 : 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 0 : pRenderFormat(pSysDat.pXRenderFormat)
79 0 : {}
80 :
81 2 : 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 2 : pRenderFormat(NULL)
89 2 : {}
90 :
91 2 : X11Pixmap::~X11Pixmap()
92 : {
93 2 : if( mpDisplay && mhDrawable )
94 2 : XFreePixmap( static_cast<Display*>(mpDisplay), mhDrawable );
95 2 : }
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 2 : X11Surface::X11Surface( const X11SysData& rSysData,
109 : const X11PixmapSharedPtr& rPixmap,
110 : const CairoSurfaceSharedPtr& pSurface ) :
111 : maSysData(rSysData),
112 : mpPixmap(rPixmap),
113 2 : mpSurface(pSurface)
114 2 : {}
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 2 : X11Surface::X11Surface( const CairoSurfaceSharedPtr& pSurface ) :
128 : maSysData(),
129 : mpPixmap(),
130 2 : mpSurface(pSurface)
131 2 : {}
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 2 : 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( static_cast<Display*>(rSysData.pDisplay),
152 : rSysData.hDrawable,
153 : static_cast<Visual*>(rSysData.pVisual),
154 : width + x, height + y ),
155 2 : &cairo_surface_destroy)
156 : {
157 2 : cairo_surface_set_device_offset(mpSurface.get(), x, y );
158 2 : }
159 :
160 : /**
161 : * Surface::Surface: Create platform 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 0 : X11Surface::X11Surface( const X11SysData& rSysData,
172 : const BitmapSystemData& rData ) :
173 : maSysData( rSysData ),
174 : mpPixmap(),
175 : mpSurface(
176 : cairo_xlib_surface_create( static_cast<Display*>(rSysData.pDisplay),
177 : reinterpret_cast<Drawable>(rData.aPixmap),
178 : static_cast<Visual*>(rSysData.pVisual),
179 : rData.mnWidth, rData.mnHeight ),
180 0 : &cairo_surface_destroy)
181 : {
182 0 : }
183 :
184 : /**
185 : * Surface::getCairo: Create Cairo (drawing object) for the Canvas surface
186 : *
187 : * @return new Cairo or NULL
188 : **/
189 6 : CairoSharedPtr X11Surface::getCairo() const
190 : {
191 : return CairoSharedPtr( cairo_create(mpSurface.get()),
192 6 : &cairo_destroy );
193 : }
194 :
195 : /**
196 : * Surface::getSimilar: Create new similar Canvas surface
197 : * @param cairo_content_type 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 cairo_content_type (cairo_content_t)
205 : *
206 : * @return new surface or NULL
207 : **/
208 2 : SurfaceSharedPtr X11Surface::getSimilar(int cairo_content_type, int width, int height ) const
209 : {
210 : Pixmap hPixmap;
211 :
212 2 : if( maSysData.pDisplay && maSysData.hDrawable )
213 : {
214 : XRenderPictFormat* pFormat;
215 : int nFormat;
216 :
217 2 : switch (cairo_content_type)
218 : {
219 : case CAIRO_CONTENT_ALPHA:
220 0 : nFormat = PictStandardA8;
221 0 : break;
222 : case CAIRO_CONTENT_COLOR:
223 0 : nFormat = PictStandardRGB24;
224 0 : break;
225 : case CAIRO_CONTENT_COLOR_ALPHA:
226 : default:
227 2 : nFormat = PictStandardARGB32;
228 2 : break;
229 : }
230 :
231 2 : pFormat = XRenderFindStandardFormat( static_cast<Display*>(maSysData.pDisplay), nFormat );
232 : hPixmap = limitXCreatePixmap( static_cast<Display*>(maSysData.pDisplay), maSysData.hDrawable,
233 : width > 0 ? width : 1, height > 0 ? height : 1,
234 2 : pFormat->depth );
235 :
236 2 : X11SysData aSysData(maSysData);
237 2 : aSysData.pRenderFormat = pFormat;
238 : return SurfaceSharedPtr(
239 : new X11Surface( aSysData,
240 : X11PixmapSharedPtr(
241 2 : new X11Pixmap(hPixmap, maSysData.pDisplay)),
242 : CairoSurfaceSharedPtr(
243 : cairo_xlib_surface_create_with_xrender_format(
244 : static_cast<Display*>(maSysData.pDisplay),
245 : hPixmap,
246 : ScreenOfDisplay(static_cast<Display *>(maSysData.pDisplay), maSysData.nScreen),
247 : pFormat, width, height ),
248 4 : &cairo_surface_destroy) ));
249 : }
250 : else
251 : return SurfaceSharedPtr(
252 : new X11Surface( maSysData,
253 : X11PixmapSharedPtr(),
254 : CairoSurfaceSharedPtr(
255 : cairo_surface_create_similar( mpSurface.get(),
256 : static_cast<cairo_content_t>(cairo_content_type), width, height ),
257 0 : &cairo_surface_destroy )));
258 : }
259 :
260 0 : VclPtr<VirtualDevice> X11Surface::createVirtualDevice() const
261 : {
262 0 : SystemGraphicsData aSystemGraphicsData;
263 :
264 0 : aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
265 0 : aSystemGraphicsData.hDrawable = getDrawable();
266 0 : aSystemGraphicsData.pXRenderFormat = getRenderFormat();
267 :
268 0 : int width = cairo_xlib_surface_get_width(mpSurface.get());
269 0 : int height = cairo_xlib_surface_get_height(mpSurface.get());
270 :
271 : return VclPtr<VirtualDevice>(
272 : VclPtr<VirtualDevice>::Create(&aSystemGraphicsData,
273 : Size(width, height),
274 0 : std::max(getDepth(), 0)));
275 : }
276 :
277 : /**
278 : * Surface::Resize: Resizes the Canvas surface.
279 : * @param width new width of the surface
280 : * @param height new height of the surface
281 : *
282 : * Only used on X11.
283 : *
284 : * @return The new surface or NULL
285 : **/
286 0 : bool X11Surface::Resize(int width, int height)
287 : {
288 0 : cairo_xlib_surface_set_size(mpSurface.get(), width, height);
289 0 : return true;
290 : }
291 :
292 0 : void X11Surface::flush() const
293 : {
294 0 : XSync( static_cast<Display*>(maSysData.pDisplay), false );
295 0 : }
296 :
297 : /**
298 : * Surface::getDepth: Get the color depth of the Canvas surface.
299 : *
300 : * @return color depth
301 : **/
302 0 : int X11Surface::getDepth() const
303 : {
304 0 : if( maSysData.pRenderFormat )
305 0 : return static_cast<XRenderPictFormat*>(maSysData.pRenderFormat)->depth;
306 :
307 0 : return -1;
308 : }
309 : }
310 :
311 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|