Line data Source code
1 : /* Cairo - a vector graphics library with display and print output
2 : *
3 : * Copyright © 2005 Red Hat, Inc.
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it either under the terms of the GNU Lesser General Public
7 : * License version 2.1 as published by the Free Software Foundation
8 : * (the "LGPL") or, at your option, under the terms of the Mozilla
9 : * Public License Version 1.1 (the "MPL"). If you do not alter this
10 : * notice, a recipient may use your version of this file under either
11 : * the MPL or the LGPL.
12 : *
13 : * You should have received a copy of the LGPL along with this library
14 : * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 : * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 : * You should have received a copy of the MPL along with this library
17 : * in the file COPYING-MPL-1.1
18 : *
19 : * The contents of this file are subject to the Mozilla Public License
20 : * Version 1.1 (the "License"); you may not use this file except in
21 : * compliance with the License. You may obtain a copy of the License at
22 : * http://www.mozilla.org/MPL/
23 : *
24 : * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 : * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 : * the specific language governing rights and limitations.
27 : *
28 : * The Original Code is the cairo graphics library.
29 : *
30 : * The Initial Developer of the Original Code is Red Hat, Inc.
31 : *
32 : * Partially on code from xftdpy.c
33 : *
34 : * Copyright © 2000 Keith Packard
35 : *
36 : * Permission to use, copy, modify, distribute, and sell this software and its
37 : * documentation for any purpose is hereby granted without fee, provided that
38 : * the above copyright notice appear in all copies and that both that
39 : * copyright notice and this permission notice appear in supporting
40 : * documentation, and that the name of Keith Packard not be used in
41 : * advertising or publicity pertaining to distribution of the software without
42 : * specific, written prior permission. Keith Packard makes no
43 : * representations about the suitability of this software for any purpose. It
44 : * is provided "as is" without express or implied warranty.
45 : *
46 : * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
47 : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
48 : * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
49 : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
50 : * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
51 : * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
52 : * PERFORMANCE OF THIS SOFTWARE.
53 : */
54 :
55 : #include "cairoint.h"
56 :
57 : #include "cairo-xlib-private.h"
58 : #include "cairo-xlib-xrender-private.h"
59 :
60 : #include "cairo-xlib-surface-private.h"
61 : #include "cairo-error-private.h"
62 :
63 : #include "cairo-fontconfig-private.h"
64 :
65 : static int
66 0 : parse_boolean (const char *v)
67 : {
68 : char c0, c1;
69 :
70 0 : c0 = *v;
71 0 : if (c0 == 't' || c0 == 'T' || c0 == 'y' || c0 == 'Y' || c0 == '1')
72 0 : return 1;
73 0 : if (c0 == 'f' || c0 == 'F' || c0 == 'n' || c0 == 'N' || c0 == '0')
74 0 : return 0;
75 0 : if (c0 == 'o')
76 : {
77 0 : c1 = v[1];
78 0 : if (c1 == 'n' || c1 == 'N')
79 0 : return 1;
80 0 : if (c1 == 'f' || c1 == 'F')
81 0 : return 0;
82 : }
83 :
84 0 : return -1;
85 : }
86 :
87 : static cairo_bool_t
88 0 : get_boolean_default (Display *dpy,
89 : const char *option,
90 : cairo_bool_t *value)
91 : {
92 : char *v;
93 : int i;
94 :
95 0 : v = XGetDefault (dpy, "Xft", option);
96 0 : if (v) {
97 0 : i = parse_boolean (v);
98 0 : if (i >= 0) {
99 0 : *value = i;
100 0 : return TRUE;
101 : }
102 : }
103 :
104 0 : return FALSE;
105 : }
106 :
107 : static cairo_bool_t
108 0 : get_integer_default (Display *dpy,
109 : const char *option,
110 : int *value)
111 : {
112 : char *v, *e;
113 :
114 0 : v = XGetDefault (dpy, "Xft", option);
115 0 : if (v) {
116 : #if CAIRO_HAS_FC_FONT
117 0 : if (FcNameConstant ((FcChar8 *) v, value))
118 0 : return TRUE;
119 : #endif
120 :
121 0 : *value = strtol (v, &e, 0);
122 0 : if (e != v)
123 0 : return TRUE;
124 : }
125 :
126 0 : return FALSE;
127 : }
128 :
129 : static void
130 0 : _cairo_xlib_init_screen_font_options (Display *dpy,
131 : cairo_xlib_screen_t *info)
132 : {
133 : cairo_bool_t xft_hinting;
134 : cairo_bool_t xft_antialias;
135 : int xft_hintstyle;
136 : int xft_rgba;
137 : int xft_lcdfilter;
138 : cairo_antialias_t antialias;
139 : cairo_subpixel_order_t subpixel_order;
140 : cairo_lcd_filter_t lcd_filter;
141 : cairo_hint_style_t hint_style;
142 :
143 0 : if (!get_boolean_default (dpy, "antialias", &xft_antialias))
144 0 : xft_antialias = TRUE;
145 :
146 0 : if (!get_integer_default (dpy, "lcdfilter", &xft_lcdfilter)) {
147 : /* -1 is an non-existant Fontconfig constant used to differentiate
148 : * the case when no lcdfilter property is available.
149 : */
150 0 : xft_lcdfilter = -1;
151 : }
152 :
153 0 : if (!get_boolean_default (dpy, "hinting", &xft_hinting))
154 0 : xft_hinting = TRUE;
155 :
156 0 : if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle))
157 0 : xft_hintstyle = FC_HINT_FULL;
158 :
159 0 : if (!get_integer_default (dpy, "rgba", &xft_rgba))
160 : {
161 0 : cairo_xlib_display_t *display = (cairo_xlib_display_t *) info->device;
162 :
163 0 : xft_rgba = FC_RGBA_UNKNOWN;
164 :
165 : #if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
166 0 : if (display->render_major > 0 || display->render_minor >= 6) {
167 0 : int render_order = XRenderQuerySubpixelOrder (dpy,
168 : XScreenNumberOfScreen (info->screen));
169 :
170 0 : switch (render_order) {
171 : default:
172 : case SubPixelUnknown:
173 0 : xft_rgba = FC_RGBA_UNKNOWN;
174 0 : break;
175 : case SubPixelHorizontalRGB:
176 0 : xft_rgba = FC_RGBA_RGB;
177 0 : break;
178 : case SubPixelHorizontalBGR:
179 0 : xft_rgba = FC_RGBA_BGR;
180 0 : break;
181 : case SubPixelVerticalRGB:
182 0 : xft_rgba = FC_RGBA_VRGB;
183 0 : break;
184 : case SubPixelVerticalBGR:
185 0 : xft_rgba = FC_RGBA_VBGR;
186 0 : break;
187 : case SubPixelNone:
188 0 : xft_rgba = FC_RGBA_NONE;
189 0 : break;
190 : }
191 : }
192 : #endif
193 : }
194 :
195 0 : if (xft_hinting) {
196 0 : switch (xft_hintstyle) {
197 : case FC_HINT_NONE:
198 0 : hint_style = CAIRO_HINT_STYLE_NONE;
199 0 : break;
200 : case FC_HINT_SLIGHT:
201 0 : hint_style = CAIRO_HINT_STYLE_SLIGHT;
202 0 : break;
203 : case FC_HINT_MEDIUM:
204 0 : hint_style = CAIRO_HINT_STYLE_MEDIUM;
205 0 : break;
206 : case FC_HINT_FULL:
207 0 : hint_style = CAIRO_HINT_STYLE_FULL;
208 0 : break;
209 : default:
210 0 : hint_style = CAIRO_HINT_STYLE_DEFAULT;
211 : }
212 : } else {
213 0 : hint_style = CAIRO_HINT_STYLE_NONE;
214 : }
215 :
216 0 : switch (xft_rgba) {
217 : case FC_RGBA_RGB:
218 0 : subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
219 0 : break;
220 : case FC_RGBA_BGR:
221 0 : subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
222 0 : break;
223 : case FC_RGBA_VRGB:
224 0 : subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
225 0 : break;
226 : case FC_RGBA_VBGR:
227 0 : subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
228 0 : break;
229 : case FC_RGBA_UNKNOWN:
230 : case FC_RGBA_NONE:
231 : default:
232 0 : subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
233 : }
234 :
235 0 : switch (xft_lcdfilter) {
236 : case FC_LCD_NONE:
237 0 : lcd_filter = CAIRO_LCD_FILTER_NONE;
238 0 : break;
239 : case FC_LCD_DEFAULT:
240 0 : lcd_filter = CAIRO_LCD_FILTER_FIR5;
241 0 : break;
242 : case FC_LCD_LIGHT:
243 0 : lcd_filter = CAIRO_LCD_FILTER_FIR3;
244 0 : break;
245 : case FC_LCD_LEGACY:
246 0 : lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
247 0 : break;
248 : default:
249 0 : lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
250 0 : break;
251 : }
252 :
253 0 : if (xft_antialias) {
254 0 : if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
255 0 : antialias = CAIRO_ANTIALIAS_GRAY;
256 : else
257 0 : antialias = CAIRO_ANTIALIAS_SUBPIXEL;
258 : } else {
259 0 : antialias = CAIRO_ANTIALIAS_NONE;
260 : }
261 :
262 0 : cairo_font_options_set_hint_style (&info->font_options, hint_style);
263 0 : cairo_font_options_set_antialias (&info->font_options, antialias);
264 0 : cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
265 0 : _cairo_font_options_set_lcd_filter (&info->font_options, lcd_filter);
266 0 : cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
267 0 : }
268 :
269 : void
270 0 : _cairo_xlib_screen_close_display (cairo_xlib_display_t *display,
271 : cairo_xlib_screen_t *info)
272 : {
273 : Display *dpy;
274 : int i;
275 :
276 0 : dpy = display->display;
277 :
278 0 : for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
279 0 : if ((info->gc_depths >> (8*i)) & 0xff)
280 0 : XFreeGC (dpy, info->gc[i]);
281 : }
282 0 : info->gc_depths = 0;
283 0 : }
284 :
285 : void
286 0 : _cairo_xlib_screen_destroy (cairo_xlib_screen_t *info)
287 : {
288 0 : while (! cairo_list_is_empty (&info->visuals)) {
289 0 : _cairo_xlib_visual_info_destroy (cairo_list_first_entry (&info->visuals,
290 : cairo_xlib_visual_info_t,
291 : link));
292 : }
293 :
294 0 : cairo_list_del (&info->link);
295 :
296 0 : free (info);
297 0 : }
298 :
299 : cairo_status_t
300 0 : _cairo_xlib_screen_get (Display *dpy,
301 : Screen *screen,
302 : cairo_xlib_screen_t **out)
303 : {
304 : cairo_xlib_display_t *display;
305 : cairo_device_t *device;
306 : cairo_xlib_screen_t *info;
307 : cairo_status_t status;
308 :
309 0 : device = _cairo_xlib_device_create (dpy);
310 0 : status = device->status;
311 0 : if (unlikely (status))
312 0 : goto CLEANUP_DEVICE;
313 :
314 0 : status = _cairo_xlib_display_acquire (device, &display);
315 0 : if (unlikely (status))
316 0 : goto CLEANUP_DEVICE;
317 :
318 0 : info = _cairo_xlib_display_get_screen (display, screen);
319 0 : if (info != NULL) {
320 0 : *out = info;
321 0 : goto CLEANUP_DISPLAY;
322 : }
323 :
324 0 : info = malloc (sizeof (cairo_xlib_screen_t));
325 0 : if (unlikely (info == NULL)) {
326 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
327 0 : goto CLEANUP_DISPLAY;
328 : }
329 :
330 0 : info->device = device;
331 0 : info->screen = screen;
332 0 : info->has_font_options = FALSE;
333 0 : info->gc_depths = 0;
334 0 : memset (info->gc, 0, sizeof (info->gc));
335 :
336 0 : cairo_list_init (&info->visuals);
337 0 : cairo_list_add (&info->link, &display->screens);
338 :
339 0 : *out = info;
340 :
341 : CLEANUP_DISPLAY:
342 0 : cairo_device_release (&display->base);
343 :
344 : CLEANUP_DEVICE:
345 0 : cairo_device_destroy (device);
346 0 : return status;
347 : }
348 :
349 : GC
350 0 : _cairo_xlib_screen_get_gc (cairo_xlib_display_t *display,
351 : cairo_xlib_screen_t *info,
352 : int depth,
353 : Drawable drawable)
354 : {
355 0 : GC gc = NULL;
356 : int i;
357 :
358 0 : for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
359 0 : if (((info->gc_depths >> (8*i)) & 0xff) == depth) {
360 0 : info->gc_depths &= ~(0xff << (8*i));
361 0 : gc = info->gc[i];
362 0 : break;
363 : }
364 : }
365 :
366 0 : if (gc == NULL) {
367 : XGCValues gcv;
368 :
369 0 : gcv.graphics_exposures = False;
370 0 : gcv.fill_style = FillTiled;
371 0 : gc = XCreateGC (display->display,
372 : drawable,
373 : GCGraphicsExposures | GCFillStyle, &gcv);
374 : }
375 :
376 0 : return gc;
377 : }
378 :
379 : void
380 0 : _cairo_xlib_screen_put_gc (cairo_xlib_display_t *display,
381 : cairo_xlib_screen_t *info,
382 : int depth,
383 : GC gc)
384 : {
385 : int i;
386 :
387 0 : for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
388 0 : if (((info->gc_depths >> (8*i)) & 0xff) == 0)
389 0 : break;
390 : }
391 :
392 0 : if (i == ARRAY_LENGTH (info->gc)) {
393 : cairo_status_t status;
394 :
395 : /* perform random substitution to ensure fair caching over depths */
396 0 : i = rand () % ARRAY_LENGTH (info->gc);
397 0 : status =
398 : _cairo_xlib_display_queue_work (display,
399 : (cairo_xlib_notify_func) XFreeGC,
400 0 : info->gc[i],
401 : NULL);
402 0 : if (unlikely (status)) {
403 : /* leak the server side resource... */
404 0 : XFree ((char *) info->gc[i]);
405 : }
406 : }
407 :
408 0 : info->gc[i] = gc;
409 0 : info->gc_depths &= ~(0xff << (8*i));
410 0 : info->gc_depths |= depth << (8*i);
411 0 : }
412 :
413 : cairo_status_t
414 0 : _cairo_xlib_screen_get_visual_info (cairo_xlib_display_t *display,
415 : cairo_xlib_screen_t *info,
416 : Visual *v,
417 : cairo_xlib_visual_info_t **out)
418 : {
419 : cairo_xlib_visual_info_t *visual;
420 : cairo_status_t status;
421 :
422 0 : cairo_list_foreach_entry (visual,
423 : cairo_xlib_visual_info_t,
424 : &info->visuals,
425 : link)
426 : {
427 0 : if (visual->visualid == v->visualid) {
428 0 : *out = visual;
429 0 : return CAIRO_STATUS_SUCCESS;
430 : }
431 : }
432 :
433 0 : status = _cairo_xlib_visual_info_create (display->display,
434 : XScreenNumberOfScreen (info->screen),
435 : v->visualid,
436 : &visual);
437 0 : if (unlikely (status))
438 0 : return status;
439 :
440 0 : cairo_list_add (&visual->link, &info->visuals);
441 0 : *out = visual;
442 0 : return CAIRO_STATUS_SUCCESS;
443 : }
444 :
445 : cairo_font_options_t *
446 0 : _cairo_xlib_screen_get_font_options (cairo_xlib_screen_t *info)
447 : {
448 0 : if (! info->has_font_options) {
449 0 : _cairo_font_options_init_default (&info->font_options);
450 0 : _cairo_font_options_set_round_glyph_positions (&info->font_options, CAIRO_ROUND_GLYPH_POS_ON);
451 :
452 0 : if (info->screen != NULL) {
453 : cairo_xlib_display_t *display;
454 :
455 0 : if (! _cairo_xlib_display_acquire (info->device, &display)) {
456 0 : _cairo_xlib_init_screen_font_options (display->display,
457 : info);
458 0 : cairo_device_release (&display->base);
459 : }
460 : }
461 :
462 0 : info->has_font_options = TRUE;
463 : }
464 :
465 0 : return &info->font_options;
466 : }
|