~ubuntu-branches/ubuntu/hardy/libgdiplus/hardy

« back to all changes in this revision

Viewing changes to cairo/src/cairo-xlib-screen.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2007-12-18 13:08:10 UTC
  • mfrom: (1.1.15 upstream)
  • Revision ID: james.westby@ubuntu.com-20071218130810-hlmitxfddf6h511j
Tags: 1.2.6-1ubuntu1
* Sync with Debian:
  - debian/control:
    + Add lpia and sparc to the architectures. We support them.
    + Change Maintainer to Ubuntu Mono Team.

Show diffs side-by-side

added added

removed removed

Lines of Context:
58
58
 
59
59
#include <fontconfig/fontconfig.h>
60
60
 
61
 
#include <X11/Xlibint.h>        /* For XESetCloseDisplay */
62
61
#include <X11/extensions/Xrender.h>
63
62
 
64
63
static int
133
132
#endif
134
133
 
135
134
static void
136
 
_cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
 
135
_cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *info)
137
136
{
138
137
    cairo_bool_t xft_hinting;
139
138
    cairo_bool_t xft_antialias;
143
142
    cairo_subpixel_order_t subpixel_order;
144
143
    cairo_hint_style_t hint_style;
145
144
 
146
 
    if (!get_boolean_default (info->display, "antialias", &xft_antialias))
 
145
    if (!get_boolean_default (dpy, "antialias", &xft_antialias))
147
146
        xft_antialias = TRUE;
148
147
 
149
 
    if (!get_boolean_default (info->display, "hinting", &xft_hinting))
 
148
    if (!get_boolean_default (dpy, "hinting", &xft_hinting))
150
149
        xft_hinting = TRUE;
151
150
 
152
 
    if (!get_integer_default (info->display, "hintstyle", &xft_hintstyle))
 
151
    if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle))
153
152
        xft_hintstyle = FC_HINT_FULL;
154
153
 
155
 
    if (!get_integer_default (info->display, "rgba", &xft_rgba))
 
154
    if (!get_integer_default (dpy, "rgba", &xft_rgba))
156
155
    {
157
156
        xft_rgba = FC_RGBA_UNKNOWN;
158
157
 
159
158
#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
160
159
        if (info->has_render)
161
160
        {
162
 
            int render_order = XRenderQuerySubpixelOrder (info->display,
 
161
            int render_order = XRenderQuerySubpixelOrder (dpy,
163
162
                                                          XScreenNumberOfScreen (info->screen));
164
163
 
165
164
            switch (render_order)
243
242
    cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
244
243
}
245
244
 
246
 
static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL;
247
 
 
248
 
/* NOTE: This function must be called with _cairo_xlib_screen_mutex held. */
249
 
static void
250
 
_cairo_xlib_call_close_display_hooks (cairo_xlib_screen_info_t *info)
251
 
{
252
 
    /* call all registered shutdown routines */
253
 
    while (info->close_display_hooks != NULL) {
254
 
        cairo_xlib_hook_t *hooks = info->close_display_hooks;
255
 
        info->close_display_hooks = NULL;
256
 
 
257
 
        /* drop the list mutex whilst calling the hooks */
258
 
        CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
259
 
        do {
260
 
            cairo_xlib_hook_t *hook = hooks;
261
 
            hooks = hook->next;
262
 
 
263
 
            hook->func (info->display, hook->data);
264
 
 
265
 
            free (hook);
266
 
        } while (hooks != NULL);
267
 
        CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
268
 
    }
269
 
}
270
 
 
271
 
static void
272
 
_cairo_xlib_screen_info_reference_lock_held (cairo_xlib_screen_info_t *info)
273
 
{
 
245
cairo_xlib_screen_info_t *
 
246
_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
 
247
{
 
248
    if (info == NULL)
 
249
        return NULL;
 
250
 
274
251
    assert (info->ref_count > 0);
275
252
    info->ref_count++;
276
 
}
277
 
 
278
 
cairo_xlib_screen_info_t *
279
 
_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
280
 
{
 
253
 
 
254
    return info;
 
255
}
 
256
 
 
257
void
 
258
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info)
 
259
{
 
260
    int i;
 
261
 
 
262
    for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
 
263
        if (info->gc[i] != NULL) {
 
264
            XFreeGC (info->display->display, info->gc[i]);
 
265
            info->gc[i] = NULL;
 
266
        }
 
267
    }
 
268
}
 
269
 
 
270
void
 
271
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
 
272
{
 
273
    cairo_xlib_screen_info_t **prev;
 
274
    cairo_xlib_screen_info_t *list;
 
275
 
281
276
    if (info == NULL)
282
 
        return NULL;
283
 
 
284
 
    /* use our global mutex until we get a real atomic inc */
285
 
    CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
286
 
 
287
 
    _cairo_xlib_screen_info_reference_lock_held (info);
288
 
 
289
 
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
290
 
 
291
 
    return info;
292
 
}
293
 
 
294
 
static void
295
 
_cairo_xlib_screen_info_destroy_lock_held (cairo_xlib_screen_info_t *info)
296
 
{
 
277
        return;
 
278
 
297
279
    assert (info->ref_count > 0);
298
280
    if (--info->ref_count)
299
281
        return;
300
282
 
301
 
    _cairo_xlib_call_close_display_hooks (info);
 
283
    CAIRO_MUTEX_LOCK (info->display->mutex);
 
284
    for (prev = &info->display->screens; (list = *prev); prev = &list->next) {
 
285
        if (list == info) {
 
286
            *prev = info->next;
 
287
            break;
 
288
        }
 
289
    }
 
290
    CAIRO_MUTEX_UNLOCK (info->display->mutex);
 
291
 
 
292
    _cairo_xlib_screen_info_close_display (info);
 
293
 
 
294
    _cairo_xlib_display_destroy (info->display);
 
295
 
302
296
    free (info);
303
297
}
304
298
 
305
 
void
306
 
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
307
 
{
308
 
    if (info == NULL)
309
 
        return;
310
 
 
311
 
    CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
312
 
 
313
 
    _cairo_xlib_screen_info_destroy_lock_held (info);
314
 
 
315
 
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
316
 
}
317
 
 
318
 
static int
319
 
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
320
 
{
321
 
    cairo_xlib_screen_info_t *info, **prev, *next;
322
 
 
323
 
    /*
324
 
     * Unhook from the global list
325
 
     */
326
 
    CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
327
 
 
328
 
    prev = &_cairo_xlib_screen_list;
329
 
    for (info = _cairo_xlib_screen_list; info; info = next) {
330
 
        next = info->next;
331
 
        if (info->display == dpy) {
332
 
            /* trigger the hooks explicitly as we know the display is closing */
333
 
            _cairo_xlib_call_close_display_hooks (info);
334
 
            _cairo_xlib_screen_info_destroy_lock_held (info);
335
 
            *prev = next;
336
 
        } else {
337
 
            prev = &info->next;
338
 
        }
339
 
    }
340
 
    *prev = NULL;
341
 
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
342
 
 
343
 
    /* Return value in accordance with requirements of
344
 
     * XESetCloseDisplay */
345
 
    return 0;
346
 
}
347
 
 
348
 
static void
349
 
_cairo_xlib_screen_info_reset (void)
350
 
{
351
 
    /*
352
 
     * Delete everything in the list.
353
 
     */
354
 
    CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
355
 
 
356
 
    while (_cairo_xlib_screen_list != NULL) {
357
 
        cairo_xlib_screen_info_t *info = _cairo_xlib_screen_list;
358
 
        _cairo_xlib_screen_list = info->next;
359
 
        _cairo_xlib_screen_info_destroy_lock_held (info);
360
 
    }
361
 
 
362
 
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
363
 
 
364
 
}
365
 
 
366
 
static cairo_xlib_screen_info_t *
367
 
_cairo_xlib_screen_info_get_lock_held (Display *dpy, Screen *screen)
368
 
{
369
 
    cairo_xlib_screen_info_t *info;
370
 
    cairo_xlib_screen_info_t **prev;
371
 
    int event_base, error_base;
372
 
    XExtCodes *codes;
373
 
    cairo_bool_t seen_display = FALSE;
374
 
 
375
 
    for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next)
376
 
    {
377
 
        if (info->display == dpy) {
378
 
            seen_display = TRUE;
379
 
            if (info->screen == screen) {
380
 
                /*
381
 
                 * MRU the list
382
 
                 */
383
 
                if (prev != &_cairo_xlib_screen_list) {
384
 
                    *prev = info->next;
385
 
                    info->next = _cairo_xlib_screen_list;
386
 
                    _cairo_xlib_screen_list = info;
387
 
                }
388
 
                break;
389
 
            }
390
 
        }
391
 
    }
392
 
 
393
 
    if (info)
394
 
        return info;
395
 
 
396
 
    info = malloc (sizeof (cairo_xlib_screen_info_t));
397
 
    if (!info)
398
 
        return NULL;
399
 
 
400
 
    if (!seen_display) {
401
 
        codes = XAddExtension (dpy);
402
 
        if (!codes) {
403
 
            free (info);
404
 
            return NULL;
405
 
        }
406
 
 
407
 
        XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
408
 
    }
409
 
 
410
 
    info->ref_count = 1;
411
 
    info->display = dpy;
412
 
    info->screen = screen;
413
 
    info->close_display_hooks = NULL;
414
 
    info->has_render = FALSE;
415
 
    _cairo_font_options_init_default (&info->font_options);
416
 
 
417
 
    if (screen) {
418
 
        info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
419
 
                            (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
420
 
        _cairo_xlib_init_screen_font_options (info);
421
 
    }
422
 
 
423
 
    info->next = _cairo_xlib_screen_list;
424
 
    _cairo_xlib_screen_list = info;
425
 
 
426
 
    return info;
427
 
}
428
299
cairo_xlib_screen_info_t *
429
300
_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
430
301
{
431
 
    cairo_xlib_screen_info_t *info;
432
 
 
433
 
    /* There is an apparent deadlock between this mutex and the
434
 
     * mutex for the display, but it's actually safe. For the
435
 
     * app to call XCloseDisplay() while any other thread is
436
 
     * inside this function would be an error in the logic
437
 
     * app, and the CloseDisplay hook is the only other place we
438
 
     * acquire this mutex.
439
 
     */
440
 
    CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
441
 
 
442
 
    info = _cairo_xlib_screen_info_get_lock_held (dpy, screen);
443
 
    if (info != NULL)
444
 
        _cairo_xlib_screen_info_reference_lock_held (info);
445
 
 
446
 
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
447
 
 
448
 
    return info;
449
 
}
450
 
 
451
 
cairo_bool_t
452
 
_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, void *key)
453
 
{
454
 
    cairo_xlib_screen_info_t *info;
455
 
    cairo_xlib_hook_t *hook;
456
 
    cairo_xlib_hook_t **prev;
457
 
    cairo_bool_t success = FALSE;
458
 
 
459
 
    CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
460
 
 
461
 
    info = _cairo_xlib_screen_info_get_lock_held (dpy,  NULL);
462
 
    if (!info)
463
 
        goto unlock;
464
 
 
465
 
    for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
466
 
    {
467
 
        if (hook->key == key) {
 
302
    cairo_xlib_display_t *display;
 
303
    cairo_xlib_screen_info_t *info = NULL, **prev;
 
304
 
 
305
    display = _cairo_xlib_display_get (dpy);
 
306
    if (display == NULL)
 
307
        return NULL;
 
308
 
 
309
    CAIRO_MUTEX_LOCK (display->mutex);
 
310
    if (display->closed) {
 
311
        CAIRO_MUTEX_UNLOCK (display->mutex);
 
312
        goto DONE;
 
313
    }
 
314
 
 
315
    for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) {
 
316
        if (info->screen == screen) {
468
317
            /*
469
318
             * MRU the list
470
319
             */
471
 
            if (prev != &info->close_display_hooks) {
472
 
                *prev = hook->next;
473
 
                hook->next = info->close_display_hooks;
474
 
                info->close_display_hooks = hook;
475
 
            }
476
 
            break;
477
 
        }
478
 
    }
479
 
 
480
 
    if (!hook) {
481
 
        hook = malloc (sizeof (cairo_xlib_hook_t));
482
 
        if (!hook)
483
 
            goto unlock;
484
 
        hook->func = func;
485
 
        hook->data = data;
486
 
        hook->key = key;
487
 
        hook->next = info->close_display_hooks;
488
 
        info->close_display_hooks = hook;
489
 
    }
490
 
 
491
 
    success = TRUE;
492
 
 unlock:
493
 
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
494
 
    return success;
495
 
}
496
 
 
497
 
void
498
 
_cairo_xlib_remove_close_display_hook (Display *dpy, void *key)
499
 
{
500
 
    cairo_xlib_screen_info_t *info;
501
 
    cairo_xlib_hook_t *hook;
502
 
    cairo_xlib_hook_t **prev;
503
 
 
504
 
    CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
505
 
 
506
 
    info = _cairo_xlib_screen_info_get_lock_held (dpy, NULL);
507
 
    if (!info)
508
 
        goto unlock;
509
 
 
510
 
    for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
511
 
    {
512
 
        if (hook->key == key) {
513
 
            *prev = hook->next;
514
 
            free (hook);
515
 
            break;
516
 
        }
517
 
    }
518
 
 
519
 
unlock:
520
 
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
521
 
}
522
 
 
523
 
void
524
 
_cairo_xlib_screen_reset_static_data (void)
525
 
{
526
 
    _cairo_xlib_screen_info_reset ();
 
320
            if (prev != &display->screens) {
 
321
                *prev = info->next;
 
322
                info->next = display->screens;
 
323
                display->screens = info;
 
324
            }
 
325
            break;
 
326
        }
 
327
    }
 
328
    CAIRO_MUTEX_UNLOCK (display->mutex);
 
329
 
 
330
    if (info != NULL) {
 
331
        info = _cairo_xlib_screen_info_reference (info);
 
332
    } else {
 
333
        info = malloc (sizeof (cairo_xlib_screen_info_t));
 
334
        if (info != NULL) {
 
335
            info->ref_count = 2; /* Add one for display cache */
 
336
            info->display = _cairo_xlib_display_reference (display);
 
337
            info->screen = screen;
 
338
            info->has_render = FALSE;
 
339
            _cairo_font_options_init_default (&info->font_options);
 
340
            memset (info->gc, 0, sizeof (info->gc));
 
341
            info->gc_needs_clip_reset = 0;
 
342
 
 
343
            if (screen) {
 
344
                int event_base, error_base;
 
345
                info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
 
346
                        (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
 
347
                _cairo_xlib_init_screen_font_options (dpy, info);
 
348
            }
 
349
 
 
350
            CAIRO_MUTEX_LOCK (display->mutex);
 
351
            info->next = display->screens;
 
352
            display->screens = info;
 
353
            CAIRO_MUTEX_UNLOCK (display->mutex);
 
354
        }
 
355
    }
 
356
 
 
357
DONE:
 
358
    _cairo_xlib_display_destroy (display);
 
359
 
 
360
    return info;
 
361
}
 
362
 
 
363
static int
 
364
depth_to_index (int depth)
 
365
{
 
366
    switch(depth){
 
367
        case 1:  return 1;
 
368
        case 8:  return 2;
 
369
        case 12: return 3;
 
370
        case 15: return 4;
 
371
        case 16: return 5;
 
372
        case 24: return 6;
 
373
        case 30: return 7;
 
374
        case 32: return 8;
 
375
    }
 
376
    return 0;
 
377
}
 
378
 
 
379
GC
 
380
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
 
381
{
 
382
    GC gc;
 
383
 
 
384
    depth = depth_to_index (depth);
 
385
 
 
386
    gc = info->gc[depth];
 
387
    info->gc[depth] = NULL;
 
388
 
 
389
    if (info->gc_needs_clip_reset & (1 << depth)) {
 
390
        XSetClipMask(info->display->display, gc, None);
 
391
        info->gc_needs_clip_reset &= ~(1 << depth);
 
392
    }
 
393
 
 
394
    return gc;
 
395
}
 
396
 
 
397
cairo_status_t
 
398
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip)
 
399
{
 
400
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
401
 
 
402
    depth = depth_to_index (depth);
 
403
 
 
404
    if (info->gc[depth] != NULL) {
 
405
        status = _cairo_xlib_display_queue_work (info->display,
 
406
                                               (cairo_xlib_notify_func) XFreeGC,
 
407
                                               info->gc[depth],
 
408
                                               NULL);
 
409
    }
 
410
 
 
411
    info->gc[depth] = gc;
 
412
    if (reset_clip)
 
413
        info->gc_needs_clip_reset |= 1 << depth;
 
414
    else
 
415
        info->gc_needs_clip_reset &= ~(1 << depth);
 
416
 
 
417
    return status;
527
418
}