~ubuntu-branches/ubuntu/raring/cairo/raring

« back to all changes in this revision

Viewing changes to .pc/git_evince_rendering_fix.patch/src/cairo-xlib-surface.c

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2013-01-23 21:19:34 UTC
  • mfrom: (1.3.11) (28.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20130123211934-q9qb538ujcmkliic
Tags: 1.12.10-1ubuntu1
* Merge from Debian, remaining changes:
* debian/patches/server_side_gradients.patch:
  - Don't use server side gradients, most drivers don't handle those and
    are really slow
* debian/control: Add missing libxext-dev dependency to libcairo2-dev.
  Spotted by autopkgtest.
* debian/patches/git_evince_rendering_fix.patch:
  Backport GIT commit to fix a rendering bug in evince
* debian/control, debian/libcairo2.symbols, debian/rules:
  - Disable GL backend due to LP: #725434

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 
2
/* cairo - a vector graphics library with display and print output
 
3
 *
 
4
 * Copyright © 2002 University of Southern California
 
5
 * Copyright © 2005 Red Hat, Inc.
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it either under the terms of the GNU Lesser General Public
 
9
 * License version 2.1 as published by the Free Software Foundation
 
10
 * (the "LGPL") or, at your option, under the terms of the Mozilla
 
11
 * Public License Version 1.1 (the "MPL"). If you do not alter this
 
12
 * notice, a recipient may use your version of this file under either
 
13
 * the MPL or the LGPL.
 
14
 *
 
15
 * You should have received a copy of the LGPL along with this library
 
16
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
 
18
 * You should have received a copy of the MPL along with this library
 
19
 * in the file COPYING-MPL-1.1
 
20
 *
 
21
 * The contents of this file are subject to the Mozilla Public License
 
22
 * Version 1.1 (the "License"); you may not use this file except in
 
23
 * compliance with the License. You may obtain a copy of the License at
 
24
 * http://www.mozilla.org/MPL/
 
25
 *
 
26
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
 
27
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
 
28
 * the specific language governing rights and limitations.
 
29
 *
 
30
 * The Original Code is the cairo graphics library.
 
31
 *
 
32
 * The Initial Developer of the Original Code is University of Southern
 
33
 * California.
 
34
 *
 
35
 * Contributor(s):
 
36
 *      Carl D. Worth <cworth@cworth.org>
 
37
 *      Behdad Esfahbod <behdad@behdad.org>
 
38
 *      Chris Wilson <chris@chris-wilson.co.uk>
 
39
 *      Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
 
40
 */
 
41
 
 
42
/* Heed well the words of Owen Taylor:
 
43
 * "Any patch that works around a render bug, or claims to, without a
 
44
 * specific reference to the bug filed in bugzilla.freedesktop.org will
 
45
 * never pass approval."
 
46
 */
 
47
 
 
48
#include "cairoint.h"
 
49
 
 
50
#if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
 
51
 
 
52
#include "cairo-xlib-private.h"
 
53
#include "cairo-xlib-surface-private.h"
 
54
 
 
55
#include "cairo-compositor-private.h"
 
56
#include "cairo-clip-private.h"
 
57
#include "cairo-damage-private.h"
 
58
#include "cairo-default-context-private.h"
 
59
#include "cairo-error-private.h"
 
60
#include "cairo-image-surface-private.h"
 
61
#include "cairo-list-inline.h"
 
62
#include "cairo-pattern-private.h"
 
63
#include "cairo-region-private.h"
 
64
#include "cairo-scaled-font-private.h"
 
65
#include "cairo-surface-snapshot-private.h"
 
66
#include "cairo-surface-subsurface-private.h"
 
67
 
 
68
#include <X11/Xutil.h> /* for XDestroyImage */
 
69
 
 
70
#include <X11/extensions/XShm.h>
 
71
#include <sys/ipc.h>
 
72
#include <sys/shm.h>
 
73
 
 
74
#define XLIB_COORD_MAX 32767
 
75
 
 
76
#define DEBUG 0
 
77
 
 
78
#if DEBUG
 
79
#define UNSUPPORTED(reason) \
 
80
    fprintf (stderr, \
 
81
             "cairo-xlib: hit unsupported operation %s(), line %d: %s\n", \
 
82
             __FUNCTION__, __LINE__, reason), \
 
83
    CAIRO_INT_STATUS_UNSUPPORTED
 
84
#else
 
85
#define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED
 
86
#endif
 
87
 
 
88
#if DEBUG
 
89
#include <X11/Xlibint.h>
 
90
static void CAIRO_PRINTF_FORMAT (2, 3)
 
91
_x_bread_crumb (Display *dpy,
 
92
                const char *fmt,
 
93
                ...)
 
94
{
 
95
    xReq *req;
 
96
    char buf[2048];
 
97
    unsigned int len, len_dwords;
 
98
    va_list ap;
 
99
 
 
100
    va_start (ap, fmt);
 
101
    len = vsnprintf (buf, sizeof (buf), fmt, ap);
 
102
    va_end (ap);
 
103
 
 
104
    buf[len++] = '\0';
 
105
    while (len & 3)
 
106
        buf[len++] = '\0';
 
107
 
 
108
    LockDisplay (dpy);
 
109
    GetEmptyReq (NoOperation, req);
 
110
 
 
111
    len_dwords = len >> 2;
 
112
    SetReqLen (req, len_dwords, len_dwords);
 
113
    Data (dpy, buf, len);
 
114
 
 
115
    UnlockDisplay (dpy);
 
116
    SyncHandle ();
 
117
}
 
118
#define X_DEBUG(x) _x_bread_crumb x
 
119
#else
 
120
#define X_DEBUG(x)
 
121
#endif
 
122
 
 
123
/**
 
124
 * SECTION:cairo-xlib
 
125
 * @Title: XLib Surfaces
 
126
 * @Short_Description: X Window System rendering using XLib
 
127
 * @See_Also: #cairo_surface_t
 
128
 *
 
129
 * The XLib surface is used to render cairo graphics to X Window System
 
130
 * windows and pixmaps using the XLib library.
 
131
 *
 
132
 * Note that the XLib surface automatically takes advantage of X render extension
 
133
 * if it is available.
 
134
 **/
 
135
 
 
136
/**
 
137
 * CAIRO_HAS_XLIB_SURFACE:
 
138
 *
 
139
 * Defined if the Xlib surface backend is available.
 
140
 * This macro can be used to conditionally compile backend-specific code.
 
141
 *
 
142
 * Since: 1.0
 
143
 **/
 
144
 
 
145
/**
 
146
 * SECTION:cairo-xlib-xrender
 
147
 * @Title: XLib-XRender Backend
 
148
 * @Short_Description: X Window System rendering using XLib and the X Render extension
 
149
 * @See_Also: #cairo_surface_t
 
150
 *
 
151
 * The XLib surface is used to render cairo graphics to X Window System
 
152
 * windows and pixmaps using the XLib and Xrender libraries.
 
153
 *
 
154
 * Note that the XLib surface automatically takes advantage of X Render extension
 
155
 * if it is available.
 
156
 **/
 
157
 
 
158
/**
 
159
 * CAIRO_HAS_XLIB_XRENDER_SURFACE:
 
160
 *
 
161
 * Defined if the XLib/XRender surface functions are available.
 
162
 * This macro can be used to conditionally compile backend-specific code.
 
163
 *
 
164
 * Since: 1.6
 
165
 **/
 
166
 
 
167
/* Xlib doesn't define a typedef, so define one ourselves */
 
168
typedef int (*cairo_xlib_error_func_t) (Display     *display,
 
169
                                        XErrorEvent *event);
 
170
 
 
171
static cairo_surface_t *
 
172
_cairo_xlib_surface_create_internal (cairo_xlib_screen_t        *screen,
 
173
                                     Drawable                   drawable,
 
174
                                     Visual                    *visual,
 
175
                                     XRenderPictFormat         *xrender_format,
 
176
                                     int                        width,
 
177
                                     int                        height,
 
178
                                     int                        depth);
 
179
 
 
180
static cairo_bool_t
 
181
_cairo_surface_is_xlib (cairo_surface_t *surface);
 
182
 
 
183
/*
 
184
 * Instead of taking two round trips for each blending request,
 
185
 * assume that if a particular drawable fails GetImage that it will
 
186
 * fail for a "while"; use temporary pixmaps to avoid the errors
 
187
 */
 
188
 
 
189
#define CAIRO_ASSUME_PIXMAP     20
 
190
 
 
191
static const XTransform identity = { {
 
192
    { 1 << 16, 0x00000, 0x00000 },
 
193
    { 0x00000, 1 << 16, 0x00000 },
 
194
    { 0x00000, 0x00000, 1 << 16 },
 
195
} };
 
196
 
 
197
static Visual *
 
198
_visual_for_xrender_format(Screen *screen,
 
199
                           XRenderPictFormat *xrender_format)
 
200
{
 
201
    int d, v;
 
202
 
 
203
    /* XXX Consider searching through the list of known cairo_visual_t for
 
204
     * the reverse mapping.
 
205
     */
 
206
 
 
207
    for (d = 0; d < screen->ndepths; d++) {
 
208
        Depth *d_info = &screen->depths[d];
 
209
 
 
210
        if (d_info->depth != xrender_format->depth)
 
211
            continue;
 
212
 
 
213
        for (v = 0; v < d_info->nvisuals; v++) {
 
214
            Visual *visual = &d_info->visuals[v];
 
215
 
 
216
            switch (visual->class) {
 
217
            case TrueColor:
 
218
                if (xrender_format->type != PictTypeDirect)
 
219
                    continue;
 
220
                break;
 
221
 
 
222
            case DirectColor:
 
223
                /* Prefer TrueColor to DirectColor.
 
224
                 * (XRenderFindVisualFormat considers both TrueColor and DirectColor
 
225
                 * Visuals to match the same PictFormat.)
 
226
                 */
 
227
                continue;
 
228
 
 
229
            case StaticGray:
 
230
            case GrayScale:
 
231
            case StaticColor:
 
232
            case PseudoColor:
 
233
                if (xrender_format->type != PictTypeIndexed)
 
234
                    continue;
 
235
                break;
 
236
            }
 
237
 
 
238
            if (xrender_format ==
 
239
                XRenderFindVisualFormat (DisplayOfScreen(screen), visual))
 
240
                return visual;
 
241
        }
 
242
    }
 
243
 
 
244
    return NULL;
 
245
}
 
246
 
 
247
static cairo_content_t
 
248
_xrender_format_to_content (XRenderPictFormat *xrender_format)
 
249
{
 
250
    cairo_content_t content;
 
251
 
 
252
    /* This only happens when using a non-Render server. Let's punt
 
253
     * and say there's no alpha here. */
 
254
    if (xrender_format == NULL)
 
255
        return CAIRO_CONTENT_COLOR;
 
256
 
 
257
    content = 0;
 
258
    if (xrender_format->direct.alphaMask)
 
259
            content |= CAIRO_CONTENT_ALPHA;
 
260
    if (xrender_format->direct.redMask |
 
261
        xrender_format->direct.greenMask |
 
262
        xrender_format->direct.blueMask)
 
263
            content |= CAIRO_CONTENT_COLOR;
 
264
 
 
265
    return content;
 
266
}
 
267
 
 
268
static cairo_surface_t *
 
269
_cairo_xlib_surface_create_similar (void               *abstract_src,
 
270
                                    cairo_content_t     content,
 
271
                                    int                 width,
 
272
                                    int                 height)
 
273
{
 
274
    cairo_xlib_surface_t *src = abstract_src;
 
275
    XRenderPictFormat *xrender_format;
 
276
    cairo_xlib_surface_t *surface;
 
277
    cairo_xlib_display_t *display;
 
278
    Pixmap pix;
 
279
 
 
280
    if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
 
281
        return NULL;
 
282
 
 
283
    if (width == 0 || height == 0)
 
284
        return NULL;
 
285
 
 
286
    if (_cairo_xlib_display_acquire (src->base.device, &display))
 
287
        return NULL;
 
288
 
 
289
    /* If we never found an XRenderFormat or if it isn't compatible
 
290
     * with the content being requested, then we fallback to just
 
291
     * constructing a cairo_format_t instead, (which will fairly
 
292
     * arbitrarily pick a visual/depth for the similar surface.
 
293
     */
 
294
    xrender_format = NULL;
 
295
    if (src->xrender_format &&
 
296
        _xrender_format_to_content (src->xrender_format) == content)
 
297
    {
 
298
        xrender_format = src->xrender_format;
 
299
    }
 
300
    if (xrender_format == NULL) {
 
301
        xrender_format =
 
302
            _cairo_xlib_display_get_xrender_format (display,
 
303
                                                    _cairo_format_from_content (content));
 
304
    }
 
305
    if (xrender_format) {
 
306
        Visual *visual;
 
307
 
 
308
        /* We've got a compatible XRenderFormat now, which means the
 
309
         * similar surface will match the existing surface as closely in
 
310
         * visual/depth etc. as possible. */
 
311
        pix = XCreatePixmap (display->display, src->drawable,
 
312
                             width, height, xrender_format->depth);
 
313
 
 
314
        if (xrender_format == src->xrender_format)
 
315
            visual = src->visual;
 
316
        else
 
317
            visual = _visual_for_xrender_format(src->screen->screen,
 
318
                                                xrender_format);
 
319
 
 
320
        surface = (cairo_xlib_surface_t *)
 
321
                  _cairo_xlib_surface_create_internal (src->screen, pix, visual,
 
322
                                                       xrender_format,
 
323
                                                       width, height,
 
324
                                                       xrender_format->depth);
 
325
    }
 
326
    else
 
327
    {
 
328
        Screen *screen = src->screen->screen;
 
329
        int depth;
 
330
 
 
331
        /* No compatible XRenderFormat, see if we can make an ordinary pixmap,
 
332
         * so that we can still accelerate blits with XCopyArea(). */
 
333
        if (content != CAIRO_CONTENT_COLOR) {
 
334
            cairo_device_release (&display->base);
 
335
            return NULL;
 
336
        }
 
337
 
 
338
        depth = DefaultDepthOfScreen (screen);
 
339
 
 
340
        pix = XCreatePixmap (display->display, RootWindowOfScreen (screen),
 
341
                             width <= 0 ? 1 : width, height <= 0 ? 1 : height,
 
342
                             depth);
 
343
 
 
344
        surface = (cairo_xlib_surface_t *)
 
345
                  _cairo_xlib_surface_create_internal (src->screen, pix,
 
346
                                                       DefaultVisualOfScreen (screen),
 
347
                                                       NULL,
 
348
                                                       width, height, depth);
 
349
    }
 
350
 
 
351
    if (likely (surface->base.status == CAIRO_STATUS_SUCCESS))
 
352
        surface->owns_pixmap = TRUE;
 
353
    else
 
354
        XFreePixmap (display->display, pix);
 
355
 
 
356
    cairo_device_release (&display->base);
 
357
 
 
358
    return &surface->base;
 
359
}
 
360
 
 
361
static void
 
362
_cairo_xlib_surface_discard_shm (cairo_xlib_surface_t *surface)
 
363
{
 
364
    if (surface->shm == NULL)
 
365
        return;
 
366
 
 
367
    /* Force the flush for an external surface */
 
368
    if (!surface->owns_pixmap)
 
369
        cairo_surface_flush (surface->shm);
 
370
 
 
371
    cairo_surface_finish (surface->shm);
 
372
    cairo_surface_destroy (surface->shm);
 
373
    surface->shm = NULL;
 
374
 
 
375
    _cairo_damage_destroy (surface->base.damage);
 
376
    surface->base.damage = NULL;
 
377
 
 
378
    surface->fallback = 0;
 
379
}
 
380
 
 
381
static cairo_status_t
 
382
_cairo_xlib_surface_finish (void *abstract_surface)
 
383
{
 
384
    cairo_xlib_surface_t *surface = abstract_surface;
 
385
    cairo_status_t        status;
 
386
    cairo_xlib_display_t *display;
 
387
 
 
388
    X_DEBUG ((display->display, "finish (drawable=%x)", (unsigned int) surface->drawable));
 
389
 
 
390
    cairo_list_del (&surface->link);
 
391
 
 
392
    status = _cairo_xlib_display_acquire (surface->base.device, &display);
 
393
    if (unlikely (status))
 
394
        return status;
 
395
 
 
396
    if (surface->embedded_source.picture)
 
397
        XRenderFreePicture (display->display, surface->embedded_source.picture);
 
398
    if (surface->picture)
 
399
        XRenderFreePicture (display->display, surface->picture);
 
400
 
 
401
    _cairo_xlib_surface_discard_shm (surface);
 
402
 
 
403
    if (surface->owns_pixmap)
 
404
        XFreePixmap (display->display, surface->drawable);
 
405
 
 
406
    cairo_device_release (&display->base);
 
407
 
 
408
    return status;
 
409
}
 
410
 
 
411
cairo_status_t
 
412
_cairo_xlib_surface_get_gc (cairo_xlib_display_t *display,
 
413
                            cairo_xlib_surface_t *surface,
 
414
                            GC                   *gc)
 
415
{
 
416
    *gc = _cairo_xlib_screen_get_gc (display,
 
417
                                     surface->screen,
 
418
                                     surface->depth,
 
419
                                     surface->drawable);
 
420
    if (unlikely (*gc == NULL))
 
421
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
422
 
 
423
    return CAIRO_STATUS_SUCCESS;
 
424
}
 
425
 
 
426
static int
 
427
_noop_error_handler (Display     *display,
 
428
                     XErrorEvent *event)
 
429
{
 
430
    return False;               /* return value is ignored */
 
431
}
 
432
 
 
433
static void
 
434
_swap_ximage_2bytes (XImage *ximage)
 
435
{
 
436
    int i, j;
 
437
    char *line = ximage->data;
 
438
 
 
439
    for (j = ximage->height; j; j--) {
 
440
        uint16_t *p = (uint16_t *) line;
 
441
        for (i = ximage->width; i; i--) {
 
442
            *p = bswap_16 (*p);
 
443
            p++;
 
444
        }
 
445
 
 
446
        line += ximage->bytes_per_line;
 
447
    }
 
448
}
 
449
 
 
450
static void
 
451
_swap_ximage_3bytes (XImage *ximage)
 
452
{
 
453
    int i, j;
 
454
    char *line = ximage->data;
 
455
 
 
456
    for (j = ximage->height; j; j--) {
 
457
        uint8_t *p = (uint8_t *) line;
 
458
        for (i = ximage->width; i; i--) {
 
459
            uint8_t tmp;
 
460
            tmp = p[2];
 
461
            p[2] = p[0];
 
462
            p[0] = tmp;
 
463
            p += 3;
 
464
        }
 
465
 
 
466
        line += ximage->bytes_per_line;
 
467
    }
 
468
}
 
469
 
 
470
static void
 
471
_swap_ximage_4bytes (XImage *ximage)
 
472
{
 
473
    int i, j;
 
474
    char *line = ximage->data;
 
475
 
 
476
    for (j = ximage->height; j; j--) {
 
477
        uint32_t *p = (uint32_t *) line;
 
478
        for (i = ximage->width; i; i--) {
 
479
            *p = bswap_32 (*p);
 
480
            p++;
 
481
        }
 
482
 
 
483
        line += ximage->bytes_per_line;
 
484
    }
 
485
}
 
486
 
 
487
static void
 
488
_swap_ximage_nibbles (XImage *ximage)
 
489
{
 
490
    int i, j;
 
491
    char *line = ximage->data;
 
492
 
 
493
    for (j = ximage->height; j; j--) {
 
494
        uint8_t *p = (uint8_t *) line;
 
495
        for (i = (ximage->width + 1) / 2; i; i--) {
 
496
            *p = ((*p >> 4) & 0xf) | ((*p << 4) & ~0xf);
 
497
            p++;
 
498
        }
 
499
 
 
500
        line += ximage->bytes_per_line;
 
501
    }
 
502
}
 
503
 
 
504
static void
 
505
_swap_ximage_bits (XImage *ximage)
 
506
{
 
507
    int i, j;
 
508
    char *line = ximage->data;
 
509
    int unit = ximage->bitmap_unit;
 
510
    int line_bytes = ((ximage->width + unit - 1) & ~(unit - 1)) / 8;
 
511
 
 
512
    for (j = ximage->height; j; j--) {
 
513
        char *p = line;
 
514
 
 
515
        for (i = line_bytes; i; i--) {
 
516
            char b = *p;
 
517
            b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55);
 
518
            b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33);
 
519
            b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f);
 
520
            *p = b;
 
521
 
 
522
            p++;
 
523
        }
 
524
 
 
525
        line += ximage->bytes_per_line;
 
526
    }
 
527
}
 
528
 
 
529
static void
 
530
_swap_ximage_to_native (XImage *ximage)
 
531
{
 
532
    int unit_bytes = 0;
 
533
    int native_byte_order = _cairo_is_little_endian () ? LSBFirst : MSBFirst;
 
534
 
 
535
    if (ximage->bits_per_pixel == 1 &&
 
536
        ximage->bitmap_bit_order != native_byte_order)
 
537
    {
 
538
        _swap_ximage_bits (ximage);
 
539
        if (ximage->bitmap_bit_order == ximage->byte_order)
 
540
            return;
 
541
    }
 
542
 
 
543
    if (ximage->byte_order == native_byte_order)
 
544
        return;
 
545
 
 
546
    switch (ximage->bits_per_pixel) {
 
547
    case 1:
 
548
        unit_bytes = ximage->bitmap_unit / 8;
 
549
        break;
 
550
    case 4:
 
551
        _swap_ximage_nibbles (ximage);
 
552
        /* fall-through */
 
553
    case 8:
 
554
    case 16:
 
555
    case 20:
 
556
    case 24:
 
557
    case 28:
 
558
    case 30:
 
559
    case 32:
 
560
        unit_bytes = (ximage->bits_per_pixel + 7) / 8;
 
561
        break;
 
562
    default:
 
563
        /* This could be hit on some rare but possible cases. */
 
564
        ASSERT_NOT_REACHED;
 
565
    }
 
566
 
 
567
    switch (unit_bytes) {
 
568
    case 1:
 
569
        break;
 
570
    case 2:
 
571
        _swap_ximage_2bytes (ximage);
 
572
        break;
 
573
    case 3:
 
574
        _swap_ximage_3bytes (ximage);
 
575
        break;
 
576
    case 4:
 
577
        _swap_ximage_4bytes (ximage);
 
578
        break;
 
579
    default:
 
580
        ASSERT_NOT_REACHED;
 
581
    }
 
582
}
 
583
 
 
584
 
 
585
/* Given a mask, (with a single sequence of contiguous 1 bits), return
 
586
 * the number of 1 bits in 'width' and the number of 0 bits to its
 
587
 * right in 'shift'. */
 
588
static void
 
589
_characterize_field (uint32_t mask, int *width, int *shift)
 
590
{
 
591
    *width = _cairo_popcount (mask);
 
592
    /* The final '& 31' is to force a 0 mask to result in 0 shift. */
 
593
    *shift = _cairo_popcount ((mask - 1) & ~mask) & 31;
 
594
}
 
595
 
 
596
/* Convert a field of 'width' bits to 'new_width' bits with correct
 
597
 * rounding. */
 
598
static inline uint32_t
 
599
_resize_field (uint32_t field, int width, int new_width)
 
600
{
 
601
    if (width == 0)
 
602
        return 0;
 
603
 
 
604
    if (width >= new_width) {
 
605
        return field >> (width - new_width);
 
606
    } else {
 
607
        uint32_t result = field << (new_width - width);
 
608
 
 
609
        while (width < new_width) {
 
610
            result |= result >> width;
 
611
            width <<= 1;
 
612
        }
 
613
        return result;
 
614
    }
 
615
}
 
616
 
 
617
static inline uint32_t
 
618
_adjust_field (uint32_t field, int adjustment)
 
619
{
 
620
    return MIN (255, MAX(0, (int)field + adjustment));
 
621
}
 
622
 
 
623
/* Given a shifted field value, (described by 'width' and 'shift),
 
624
 * resize it 8-bits and return that value.
 
625
 *
 
626
 * Note that the original field value must not have any non-field bits
 
627
 * set.
 
628
 */
 
629
static inline uint32_t
 
630
_field_to_8 (uint32_t field, int width, int shift)
 
631
{
 
632
    return _resize_field (field >> shift, width, 8);
 
633
}
 
634
 
 
635
static inline uint32_t
 
636
_field_to_8_undither (uint32_t field, int width, int shift,
 
637
                      int dither_adjustment)
 
638
{
 
639
    return _adjust_field (_field_to_8 (field, width, shift), - dither_adjustment>>width);
 
640
}
 
641
 
 
642
/* Given an 8-bit value, convert it to a field of 'width', shift it up
 
643
 *  to 'shift, and return it. */
 
644
static inline uint32_t
 
645
_field_from_8 (uint32_t field, int width, int shift)
 
646
{
 
647
    return _resize_field (field, 8, width) << shift;
 
648
}
 
649
 
 
650
static inline uint32_t
 
651
_field_from_8_dither (uint32_t field, int width, int shift,
 
652
                      int8_t dither_adjustment)
 
653
{
 
654
    return _field_from_8 (_adjust_field (field, dither_adjustment>>width), width, shift);
 
655
}
 
656
 
 
657
static inline uint32_t
 
658
_pseudocolor_from_rgb888_dither (cairo_xlib_visual_info_t *visual_info,
 
659
                                 uint32_t r, uint32_t g, uint32_t b,
 
660
                                 int8_t dither_adjustment)
 
661
{
 
662
    if (r == g && g == b) {
 
663
        dither_adjustment /= RAMP_SIZE;
 
664
        return visual_info->gray8_to_pseudocolor[_adjust_field (r, dither_adjustment)];
 
665
    } else {
 
666
        dither_adjustment = visual_info->dither8_to_cube[dither_adjustment+128];
 
667
        return visual_info->cube_to_pseudocolor[visual_info->field8_to_cube[_adjust_field (r, dither_adjustment)]]
 
668
                                               [visual_info->field8_to_cube[_adjust_field (g, dither_adjustment)]]
 
669
                                               [visual_info->field8_to_cube[_adjust_field (b, dither_adjustment)]];
 
670
    }
 
671
}
 
672
 
 
673
static inline uint32_t
 
674
_pseudocolor_to_rgb888 (cairo_xlib_visual_info_t *visual_info,
 
675
                        uint32_t pixel)
 
676
{
 
677
    uint32_t r, g, b;
 
678
    pixel &= 0xff;
 
679
    r = visual_info->colors[pixel].r;
 
680
    g = visual_info->colors[pixel].g;
 
681
    b = visual_info->colors[pixel].b;
 
682
    return (r << 16) |
 
683
           (g <<  8) |
 
684
           (b      );
 
685
}
 
686
 
 
687
/* should range from -128 to 127 */
 
688
#define X 16
 
689
static const int8_t dither_pattern[4][4] = {
 
690
    {-8*X, +0*X, -6*X, +2*X},
 
691
    {+4*X, -4*X, +6*X, -2*X},
 
692
    {-5*X, +4*X, -7*X, +1*X},
 
693
    {+7*X, -1*X, +5*X, -3*X}
 
694
};
 
695
#undef X
 
696
 
 
697
static int bits_per_pixel(cairo_xlib_surface_t *surface)
 
698
{
 
699
    if (surface->depth > 16)
 
700
        return 32;
 
701
    else if (surface->depth > 8)
 
702
        return 16;
 
703
    else if (surface->depth > 1)
 
704
        return 8;
 
705
    else
 
706
        return 1;
 
707
}
 
708
 
 
709
pixman_format_code_t
 
710
_pixman_format_for_xlib_surface (cairo_xlib_surface_t *surface)
 
711
{
 
712
    cairo_format_masks_t masks;
 
713
    pixman_format_code_t format;
 
714
 
 
715
    masks.bpp = bits_per_pixel (surface);
 
716
    masks.alpha_mask = surface->a_mask;
 
717
    masks.red_mask = surface->r_mask;
 
718
    masks.green_mask = surface->g_mask;
 
719
    masks.blue_mask = surface->b_mask;
 
720
    if (! _pixman_format_from_masks (&masks, &format))
 
721
        return 0;
 
722
 
 
723
    return format;
 
724
}
 
725
 
 
726
static cairo_surface_t *
 
727
_get_image_surface (cairo_xlib_surface_t    *surface,
 
728
                    const cairo_rectangle_int_t *extents,
 
729
                    int try_shm)
 
730
{
 
731
    cairo_int_status_t status;
 
732
    cairo_image_surface_t *image = NULL;
 
733
    XImage *ximage;
 
734
    pixman_format_code_t pixman_format;
 
735
    cairo_xlib_display_t *display;
 
736
 
 
737
    assert (extents->x >= 0);
 
738
    assert (extents->y >= 0);
 
739
    assert (extents->x + extents->width <= surface->width);
 
740
    assert (extents->y + extents->height <= surface->height);
 
741
 
 
742
    if (surface->base.is_clear ||
 
743
        (surface->base.serial == 0 && surface->owns_pixmap))
 
744
    {
 
745
        pixman_format = _pixman_format_for_xlib_surface (surface);
 
746
        if (pixman_format)
 
747
        {
 
748
            return _cairo_image_surface_create_with_pixman_format (NULL,
 
749
                                                                   pixman_format,
 
750
                                                                   extents->width,
 
751
                                                                   extents->height,
 
752
                                                                   0);
 
753
        }
 
754
    }
 
755
 
 
756
    if (surface->shm) {
 
757
        cairo_image_surface_t *src = (cairo_image_surface_t *) surface->shm;
 
758
        cairo_surface_t *dst;
 
759
        cairo_surface_pattern_t pattern;
 
760
 
 
761
        dst = cairo_image_surface_create (src->format,
 
762
                                          extents->width, extents->height);
 
763
        if (unlikely (dst->status))
 
764
            return dst;
 
765
 
 
766
        _cairo_pattern_init_for_surface (&pattern, &src->base);
 
767
        cairo_matrix_init_translate (&pattern.base.matrix,
 
768
                                     extents->x, extents->y);
 
769
        status = _cairo_surface_paint (dst, CAIRO_OPERATOR_SOURCE, &pattern.base, NULL);
 
770
        _cairo_pattern_fini (&pattern.base);
 
771
        if (unlikely (status)) {
 
772
            cairo_surface_destroy (dst);
 
773
            dst = _cairo_surface_create_in_error (status);
 
774
        }
 
775
 
 
776
        return dst;
 
777
    }
 
778
 
 
779
    status = _cairo_xlib_display_acquire (surface->base.device, &display);
 
780
    if (status)
 
781
        return _cairo_surface_create_in_error (status);
 
782
 
 
783
    pixman_format = _pixman_format_for_xlib_surface (surface);
 
784
    if (try_shm && pixman_format) {
 
785
        image = (cairo_image_surface_t *)
 
786
            _cairo_xlib_surface_create_shm__image (surface, pixman_format,
 
787
                                                   extents->width, extents->height);
 
788
        if (image && image->base.status == CAIRO_STATUS_SUCCESS) {
 
789
            cairo_xlib_error_func_t old_handler;
 
790
            XImage shm_image;
 
791
            Bool success;
 
792
 
 
793
            _cairo_xlib_shm_surface_get_ximage (&image->base, &shm_image);
 
794
 
 
795
            old_handler = XSetErrorHandler (_noop_error_handler);
 
796
            success = XShmGetImage (display->display,
 
797
                                    surface->drawable,
 
798
                                    &shm_image,
 
799
                                    extents->x, extents->y,
 
800
                                    AllPlanes);
 
801
            XSetErrorHandler (old_handler);
 
802
 
 
803
            if (success) {
 
804
                cairo_device_release (&display->base);
 
805
                return &image->base;
 
806
            }
 
807
 
 
808
            cairo_surface_destroy (&image->base);
 
809
        }
 
810
    }
 
811
 
 
812
    if (surface->use_pixmap == 0) {
 
813
        cairo_xlib_error_func_t old_handler;
 
814
 
 
815
        old_handler = XSetErrorHandler (_noop_error_handler);
 
816
 
 
817
        ximage = XGetImage (display->display,
 
818
                            surface->drawable,
 
819
                            extents->x, extents->y,
 
820
                            extents->width, extents->height,
 
821
                            AllPlanes, ZPixmap);
 
822
 
 
823
        XSetErrorHandler (old_handler);
 
824
 
 
825
        /* If we get an error, the surface must have been a window,
 
826
         * so retry with the safe code path.
 
827
         */
 
828
        if (!ximage)
 
829
            surface->use_pixmap = CAIRO_ASSUME_PIXMAP;
 
830
    } else {
 
831
        surface->use_pixmap--;
 
832
        ximage = NULL;
 
833
    }
 
834
 
 
835
    if (ximage == NULL) {
 
836
        /* XGetImage from a window is dangerous because it can
 
837
         * produce errors if the window is unmapped or partially
 
838
         * outside the screen. We could check for errors and
 
839
         * retry, but to keep things simple, we just create a
 
840
         * temporary pixmap
 
841
         */
 
842
        Pixmap pixmap;
 
843
        GC gc;
 
844
 
 
845
        status = _cairo_xlib_surface_get_gc (display, surface, &gc);
 
846
        if (unlikely (status))
 
847
            goto BAIL;
 
848
 
 
849
        pixmap = XCreatePixmap (display->display,
 
850
                                surface->drawable,
 
851
                                extents->width, extents->height,
 
852
                                surface->depth);
 
853
        if (pixmap) {
 
854
            XGCValues gcv;
 
855
 
 
856
            gcv.subwindow_mode = IncludeInferiors;
 
857
            XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
 
858
 
 
859
            XCopyArea (display->display, surface->drawable, pixmap, gc,
 
860
                       extents->x, extents->y,
 
861
                       extents->width, extents->height,
 
862
                       0, 0);
 
863
 
 
864
            gcv.subwindow_mode = ClipByChildren;
 
865
            XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
 
866
 
 
867
            ximage = XGetImage (display->display,
 
868
                                pixmap,
 
869
                                0, 0,
 
870
                                extents->width, extents->height,
 
871
                                AllPlanes, ZPixmap);
 
872
 
 
873
            XFreePixmap (display->display, pixmap);
 
874
        }
 
875
 
 
876
        _cairo_xlib_surface_put_gc (display, surface, gc);
 
877
 
 
878
        if (ximage == NULL) {
 
879
            status =  _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
880
            goto BAIL;
 
881
        }
 
882
    }
 
883
 
 
884
    _swap_ximage_to_native (ximage);
 
885
 
 
886
    /* We can't use pixman to simply write to image if:
 
887
     *   (a) the pixels are not appropriately aligned,
 
888
     *   (b) pixman does not the pixel format, or
 
889
     *   (c) if the image is palettized and we need to convert.
 
890
     */
 
891
    if (pixman_format &&
 
892
        ximage->bitmap_unit == 32 && ximage->bitmap_pad == 32 &&
 
893
        (surface->visual == NULL || surface->visual->class == TrueColor))
 
894
    {
 
895
        image = (cairo_image_surface_t*)
 
896
            _cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data,
 
897
                                                            pixman_format,
 
898
                                                            ximage->width,
 
899
                                                            ximage->height,
 
900
                                                            ximage->bytes_per_line);
 
901
        status = image->base.status;
 
902
        if (unlikely (status))
 
903
            goto BAIL;
 
904
 
 
905
        /* Let the surface take ownership of the data */
 
906
        _cairo_image_surface_assume_ownership_of_data (image);
 
907
        ximage->data = NULL;
 
908
    } else {
 
909
        /* The visual we are dealing with is not supported by the
 
910
         * standard pixman formats. So we must first convert the data
 
911
         * to a supported format. */
 
912
 
 
913
        cairo_format_t format;
 
914
        unsigned char *data;
 
915
        uint32_t *row;
 
916
        uint32_t in_pixel, out_pixel;
 
917
        unsigned int rowstride;
 
918
        uint32_t a_mask=0, r_mask=0, g_mask=0, b_mask=0;
 
919
        int a_width=0, r_width=0, g_width=0, b_width=0;
 
920
        int a_shift=0, r_shift=0, g_shift=0, b_shift=0;
 
921
        int x, y, x0, y0, x_off, y_off;
 
922
        cairo_xlib_visual_info_t *visual_info = NULL;
 
923
 
 
924
        if (surface->visual == NULL || surface->visual->class == TrueColor) {
 
925
            cairo_bool_t has_alpha;
 
926
            cairo_bool_t has_color;
 
927
 
 
928
            has_alpha =  surface->a_mask;
 
929
            has_color = (surface->r_mask ||
 
930
                         surface->g_mask ||
 
931
                         surface->b_mask);
 
932
 
 
933
            if (has_color) {
 
934
                if (has_alpha) {
 
935
                    format = CAIRO_FORMAT_ARGB32;
 
936
                } else {
 
937
                    format = CAIRO_FORMAT_RGB24;
 
938
                }
 
939
            } else {
 
940
                /* XXX: Using CAIRO_FORMAT_A8 here would be more
 
941
                 * efficient, but would require slightly different code in
 
942
                 * the image conversion to put the alpha channel values
 
943
                 * into the right place. */
 
944
                format = CAIRO_FORMAT_ARGB32;
 
945
            }
 
946
 
 
947
            a_mask = surface->a_mask;
 
948
            r_mask = surface->r_mask;
 
949
            g_mask = surface->g_mask;
 
950
            b_mask = surface->b_mask;
 
951
 
 
952
            _characterize_field (a_mask, &a_width, &a_shift);
 
953
            _characterize_field (r_mask, &r_width, &r_shift);
 
954
            _characterize_field (g_mask, &g_width, &g_shift);
 
955
            _characterize_field (b_mask, &b_width, &b_shift);
 
956
 
 
957
        } else {
 
958
            format = CAIRO_FORMAT_RGB24;
 
959
 
 
960
            status = _cairo_xlib_screen_get_visual_info (display,
 
961
                                                         surface->screen,
 
962
                                                         surface->visual,
 
963
                                                         &visual_info);
 
964
            if (unlikely (status))
 
965
                goto BAIL;
 
966
        }
 
967
 
 
968
        image = (cairo_image_surface_t *) cairo_image_surface_create
 
969
            (format, ximage->width, ximage->height);
 
970
        status = image->base.status;
 
971
        if (unlikely (status))
 
972
            goto BAIL;
 
973
 
 
974
        data = cairo_image_surface_get_data (&image->base);
 
975
        rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
 
976
        row = (uint32_t *) data;
 
977
        x0 = extents->x + surface->base.device_transform.x0;
 
978
        y0 = extents->y + surface->base.device_transform.y0;
 
979
        for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
 
980
             y < ximage->height;
 
981
             y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern)) {
 
982
            const int8_t *dither_row = dither_pattern[y_off];
 
983
            for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]);
 
984
                 x < ximage->width;
 
985
                 x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0])) {
 
986
                int dither_adjustment = dither_row[x_off];
 
987
 
 
988
                in_pixel = XGetPixel (ximage, x, y);
 
989
                if (visual_info == NULL) {
 
990
                    out_pixel = (
 
991
                        _field_to_8 (in_pixel & a_mask, a_width, a_shift) << 24 |
 
992
                        _field_to_8_undither (in_pixel & r_mask, r_width, r_shift, dither_adjustment) << 16 |
 
993
                        _field_to_8_undither (in_pixel & g_mask, g_width, g_shift, dither_adjustment) << 8 |
 
994
                        _field_to_8_undither (in_pixel & b_mask, b_width, b_shift, dither_adjustment));
 
995
                } else {
 
996
                    /* Undithering pseudocolor does not look better */
 
997
                    out_pixel = _pseudocolor_to_rgb888 (visual_info, in_pixel);
 
998
                }
 
999
                row[x] = out_pixel;
 
1000
            }
 
1001
            row += rowstride;
 
1002
        }
 
1003
        cairo_surface_mark_dirty (&image->base);
 
1004
    }
 
1005
 
 
1006
 BAIL:
 
1007
    if (ximage)
 
1008
        XDestroyImage (ximage);
 
1009
 
 
1010
    cairo_device_release (&display->base);
 
1011
 
 
1012
    if (unlikely (status)) {
 
1013
        cairo_surface_destroy (&image->base);
 
1014
        return _cairo_surface_create_in_error (status);
 
1015
    }
 
1016
 
 
1017
    return &image->base;
 
1018
}
 
1019
 
 
1020
void
 
1021
_cairo_xlib_surface_set_precision (cairo_xlib_surface_t *surface,
 
1022
                                   cairo_antialias_t     antialias)
 
1023
{
 
1024
    cairo_xlib_display_t        *display = surface->display;
 
1025
    int precision;
 
1026
 
 
1027
    if (display->force_precision != -1)
 
1028
            precision = display->force_precision;
 
1029
    else switch (antialias) {
 
1030
    default:
 
1031
    case CAIRO_ANTIALIAS_DEFAULT:
 
1032
    case CAIRO_ANTIALIAS_GRAY:
 
1033
    case CAIRO_ANTIALIAS_NONE:
 
1034
    case CAIRO_ANTIALIAS_FAST:
 
1035
    case CAIRO_ANTIALIAS_GOOD:
 
1036
        precision = PolyModeImprecise;
 
1037
        break;
 
1038
    case CAIRO_ANTIALIAS_BEST:
 
1039
    case CAIRO_ANTIALIAS_SUBPIXEL:
 
1040
        precision = PolyModePrecise;
 
1041
        break;
 
1042
    }
 
1043
 
 
1044
    if (surface->precision != precision) {
 
1045
        XRenderPictureAttributes pa;
 
1046
 
 
1047
        pa.poly_mode = precision;
 
1048
        XRenderChangePicture (display->display, surface->picture,
 
1049
                              CPPolyMode, &pa);
 
1050
 
 
1051
        surface->precision = precision;
 
1052
    }
 
1053
}
 
1054
 
 
1055
void
 
1056
_cairo_xlib_surface_ensure_picture (cairo_xlib_surface_t    *surface)
 
1057
{
 
1058
    cairo_xlib_display_t *display = surface->display;
 
1059
    XRenderPictureAttributes pa;
 
1060
    int mask = 0;
 
1061
 
 
1062
    if (surface->picture)
 
1063
        return;
 
1064
 
 
1065
    if (display->force_precision != -1)
 
1066
        pa.poly_mode = display->force_precision;
 
1067
    else
 
1068
        pa.poly_mode = PolyModeImprecise;
 
1069
    if (pa.poly_mode)
 
1070
            mask |= CPPolyMode;
 
1071
 
 
1072
    surface->precision = pa.poly_mode;
 
1073
    surface->picture = XRenderCreatePicture (display->display,
 
1074
                                             surface->drawable,
 
1075
                                             surface->xrender_format,
 
1076
                                             mask, &pa);
 
1077
}
 
1078
 
 
1079
cairo_status_t
 
1080
_cairo_xlib_surface_draw_image (cairo_xlib_surface_t   *surface,
 
1081
                                cairo_image_surface_t  *image,
 
1082
                                int                    src_x,
 
1083
                                int                    src_y,
 
1084
                                int                    width,
 
1085
                                int                    height,
 
1086
                                int                    dst_x,
 
1087
                                int                    dst_y)
 
1088
{
 
1089
    cairo_xlib_display_t *display;
 
1090
    XImage ximage;
 
1091
    cairo_format_masks_t image_masks;
 
1092
    int native_byte_order = _cairo_is_little_endian () ? LSBFirst : MSBFirst;
 
1093
    cairo_surface_t *shm_image = NULL;
 
1094
    pixman_image_t *pixman_image = NULL;
 
1095
    cairo_status_t status;
 
1096
    cairo_bool_t own_data = FALSE;
 
1097
    cairo_bool_t is_rgb_image;
 
1098
    GC gc;
 
1099
 
 
1100
    ximage.width = image->width;
 
1101
    ximage.height = image->height;
 
1102
    ximage.format = ZPixmap;
 
1103
    ximage.byte_order = native_byte_order;
 
1104
    ximage.bitmap_unit = 32;    /* always for libpixman */
 
1105
    ximage.bitmap_bit_order = native_byte_order;
 
1106
    ximage.bitmap_pad = 32;     /* always for libpixman */
 
1107
    ximage.depth = surface->depth;
 
1108
    ximage.red_mask = surface->r_mask;
 
1109
    ximage.green_mask = surface->g_mask;
 
1110
    ximage.blue_mask = surface->b_mask;
 
1111
    ximage.xoffset = 0;
 
1112
    ximage.obdata = NULL;
 
1113
 
 
1114
    status = _cairo_xlib_display_acquire (surface->base.device, &display);
 
1115
    if (unlikely (status))
 
1116
        return status;
 
1117
 
 
1118
    is_rgb_image = _pixman_format_to_masks (image->pixman_format, &image_masks);
 
1119
 
 
1120
    if (is_rgb_image &&
 
1121
        (image_masks.alpha_mask == surface->a_mask || surface->a_mask == 0) &&
 
1122
        (image_masks.red_mask   == surface->r_mask || surface->r_mask == 0) &&
 
1123
        (image_masks.green_mask == surface->g_mask || surface->g_mask == 0) &&
 
1124
        (image_masks.blue_mask  == surface->b_mask || surface->b_mask == 0))
 
1125
    {
 
1126
        int ret;
 
1127
 
 
1128
        ximage.bits_per_pixel = image_masks.bpp;
 
1129
        ximage.bytes_per_line = image->stride;
 
1130
        ximage.data = (char *)image->data;
 
1131
        if (image->base.device != surface->base.device) {
 
1132
            /* If PutImage will break the image up into chunks, prefer to
 
1133
             * send it all in one pass with ShmPutImage.  For larger images,
 
1134
             * it is further advantageous to reduce the number of copies,
 
1135
             * albeit at the expense of more SHM bookkeeping.
 
1136
             */
 
1137
            int max_request_size = XExtendedMaxRequestSize (display->display);
 
1138
            if (max_request_size == 0)
 
1139
                max_request_size = XMaxRequestSize (display->display);
 
1140
            if (max_request_size > 8192)
 
1141
                max_request_size = 8192;
 
1142
            if (image->stride * image->height > max_request_size) {
 
1143
                shm_image = _cairo_xlib_surface_create_shm__image (surface,
 
1144
                                                                   image->pixman_format,
 
1145
                                                                   image->width,
 
1146
                                                                   image->height);
 
1147
                if (shm_image && shm_image->status == CAIRO_STATUS_SUCCESS) {
 
1148
                    cairo_image_surface_t *clone = (cairo_image_surface_t *) shm_image;
 
1149
                    if (clone->stride == image->stride) {
 
1150
                        memcpy (clone->data, image->data, clone->stride * clone->height);
 
1151
                    } else {
 
1152
                        pixman_image_composite32 (PIXMAN_OP_SRC,
 
1153
                                                  image->pixman_image, NULL, clone->pixman_image,
 
1154
                                                  0, 0,
 
1155
                                                  0, 0,
 
1156
                                                  0, 0,
 
1157
                                                  image->width, image->height);
 
1158
                    }
 
1159
                    ximage.obdata = _cairo_xlib_shm_surface_get_obdata (shm_image);
 
1160
                    ximage.data = (char *)clone->data;
 
1161
                    ximage.bytes_per_line = clone->stride;
 
1162
                }
 
1163
            }
 
1164
        } else
 
1165
            ximage.obdata = _cairo_xlib_shm_surface_get_obdata (&image->base);
 
1166
 
 
1167
        ret = XInitImage (&ximage);
 
1168
        assert (ret != 0);
 
1169
    }
 
1170
    else if (surface->visual == NULL || surface->visual->class == TrueColor)
 
1171
    {
 
1172
        pixman_format_code_t intermediate_format;
 
1173
        int ret;
 
1174
 
 
1175
        image_masks.alpha_mask = surface->a_mask;
 
1176
        image_masks.red_mask   = surface->r_mask;
 
1177
        image_masks.green_mask = surface->g_mask;
 
1178
        image_masks.blue_mask  = surface->b_mask;
 
1179
        image_masks.bpp        = bits_per_pixel (surface);
 
1180
        ret = _pixman_format_from_masks (&image_masks, &intermediate_format);
 
1181
        assert (ret);
 
1182
 
 
1183
        shm_image = _cairo_xlib_surface_create_shm__image (surface,
 
1184
                                                           intermediate_format,
 
1185
                                                           width, height);
 
1186
        if (shm_image && shm_image->status == CAIRO_STATUS_SUCCESS) {
 
1187
            cairo_image_surface_t *clone = (cairo_image_surface_t *) shm_image;
 
1188
 
 
1189
            pixman_image_composite32 (PIXMAN_OP_SRC,
 
1190
                                      image->pixman_image,
 
1191
                                      NULL,
 
1192
                                      clone->pixman_image,
 
1193
                                      src_x, src_y,
 
1194
                                      0, 0,
 
1195
                                      0, 0,
 
1196
                                      width, height);
 
1197
 
 
1198
            ximage.data = (char *) clone->data;
 
1199
            ximage.obdata = _cairo_xlib_shm_surface_get_obdata (&clone->base);
 
1200
            ximage.bytes_per_line = clone->stride;
 
1201
        } else {
 
1202
            pixman_image = pixman_image_create_bits (intermediate_format,
 
1203
                                                     width, height, NULL, 0);
 
1204
            if (pixman_image == NULL) {
 
1205
                status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1206
                goto BAIL;
 
1207
            }
 
1208
 
 
1209
            pixman_image_composite32 (PIXMAN_OP_SRC,
 
1210
                                      image->pixman_image,
 
1211
                                      NULL,
 
1212
                                      pixman_image,
 
1213
                                      src_x, src_y,
 
1214
                                      0, 0,
 
1215
                                      0, 0,
 
1216
                                      width, height);
 
1217
 
 
1218
            ximage.data = (char *) pixman_image_get_data (pixman_image);
 
1219
            ximage.bytes_per_line = pixman_image_get_stride (pixman_image);
 
1220
        }
 
1221
 
 
1222
        ximage.width = width;
 
1223
        ximage.height = height;
 
1224
        ximage.bits_per_pixel = image_masks.bpp;
 
1225
 
 
1226
        ret = XInitImage (&ximage);
 
1227
        assert (ret != 0);
 
1228
 
 
1229
        src_x = src_y = 0;
 
1230
    }
 
1231
    else
 
1232
    {
 
1233
        unsigned int stride, rowstride;
 
1234
        int x, y, x0, y0, x_off, y_off;
 
1235
        uint32_t in_pixel, out_pixel, *row;
 
1236
        int i_a_width=0, i_r_width=0, i_g_width=0, i_b_width=0;
 
1237
        int i_a_shift=0, i_r_shift=0, i_g_shift=0, i_b_shift=0;
 
1238
        int o_a_width=0, o_r_width=0, o_g_width=0, o_b_width=0;
 
1239
        int o_a_shift=0, o_r_shift=0, o_g_shift=0, o_b_shift=0;
 
1240
        cairo_xlib_visual_info_t *visual_info = NULL;
 
1241
        cairo_bool_t true_color;
 
1242
        int ret;
 
1243
 
 
1244
        ximage.bits_per_pixel = bits_per_pixel(surface);
 
1245
        stride = CAIRO_STRIDE_FOR_WIDTH_BPP (ximage.width,
 
1246
                                             ximage.bits_per_pixel);
 
1247
        ximage.bytes_per_line = stride;
 
1248
        ximage.data = _cairo_malloc_ab (stride, ximage.height);
 
1249
        if (unlikely (ximage.data == NULL)) {
 
1250
            status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1251
            goto BAIL;
 
1252
        }
 
1253
 
 
1254
        own_data = TRUE;
 
1255
 
 
1256
        ret = XInitImage (&ximage);
 
1257
        assert (ret != 0);
 
1258
 
 
1259
        _characterize_field (image_masks.alpha_mask, &i_a_width, &i_a_shift);
 
1260
        _characterize_field (image_masks.red_mask  , &i_r_width, &i_r_shift);
 
1261
        _characterize_field (image_masks.green_mask, &i_g_width, &i_g_shift);
 
1262
        _characterize_field (image_masks.blue_mask , &i_b_width, &i_b_shift);
 
1263
 
 
1264
        true_color = surface->visual == NULL ||
 
1265
                     surface->visual->class == TrueColor;
 
1266
        if (true_color) {
 
1267
            _characterize_field (surface->a_mask, &o_a_width, &o_a_shift);
 
1268
            _characterize_field (surface->r_mask, &o_r_width, &o_r_shift);
 
1269
            _characterize_field (surface->g_mask, &o_g_width, &o_g_shift);
 
1270
            _characterize_field (surface->b_mask, &o_b_width, &o_b_shift);
 
1271
        } else {
 
1272
            status = _cairo_xlib_screen_get_visual_info (display,
 
1273
                                                         surface->screen,
 
1274
                                                         surface->visual,
 
1275
                                                         &visual_info);
 
1276
            if (unlikely (status))
 
1277
                goto BAIL;
 
1278
        }
 
1279
 
 
1280
        rowstride = image->stride >> 2;
 
1281
        row = (uint32_t *) image->data;
 
1282
        x0 = dst_x + surface->base.device_transform.x0;
 
1283
        y0 = dst_y + surface->base.device_transform.y0;
 
1284
        for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
 
1285
             y < ximage.height;
 
1286
             y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern))
 
1287
        {
 
1288
            const int8_t *dither_row = dither_pattern[y_off];
 
1289
 
 
1290
            for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]);
 
1291
                 x < ximage.width;
 
1292
                 x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0]))
 
1293
            {
 
1294
                int dither_adjustment = dither_row[x_off];
 
1295
                int a, r, g, b;
 
1296
 
 
1297
                if (image_masks.bpp == 1)
 
1298
                    in_pixel = !! (((uint8_t*)row)[x/8] & (1 << (x & 7)));
 
1299
                else if (image_masks.bpp <= 8)
 
1300
                    in_pixel = ((uint8_t*)row)[x];
 
1301
                else if (image_masks.bpp <= 16)
 
1302
                    in_pixel = ((uint16_t*)row)[x];
 
1303
                else if (image_masks.bpp <= 24)
 
1304
#ifdef WORDS_BIGENDIAN
 
1305
                    in_pixel = ((uint8_t*)row)[3 * x]     << 16 |
 
1306
                               ((uint8_t*)row)[3 * x + 1] << 8  |
 
1307
                               ((uint8_t*)row)[3 * x + 2];
 
1308
#else
 
1309
                    in_pixel = ((uint8_t*)row)[3 * x]           |
 
1310
                               ((uint8_t*)row)[3 * x + 1] << 8  |
 
1311
                               ((uint8_t*)row)[3 * x + 2] << 16;
 
1312
#endif
 
1313
                else
 
1314
                    in_pixel = row[x];
 
1315
 
 
1316
                /* If the incoming image has no alpha channel, then the input
 
1317
                 * is opaque and the output should have the maximum alpha value.
 
1318
                 * For all other channels, their absence implies 0.
 
1319
                 */
 
1320
                if (image_masks.alpha_mask == 0x0)
 
1321
                    a = 0xff;
 
1322
                else
 
1323
                    a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
 
1324
                r = _field_to_8 (in_pixel & image_masks.red_mask  , i_r_width, i_r_shift);
 
1325
                g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift);
 
1326
                b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift);
 
1327
 
 
1328
                if (true_color) {
 
1329
                    out_pixel = _field_from_8        (a, o_a_width, o_a_shift) |
 
1330
                                _field_from_8_dither (r, o_r_width, o_r_shift, dither_adjustment) |
 
1331
                                _field_from_8_dither (g, o_g_width, o_g_shift, dither_adjustment) |
 
1332
                                _field_from_8_dither (b, o_b_width, o_b_shift, dither_adjustment);
 
1333
                } else {
 
1334
                    out_pixel = _pseudocolor_from_rgb888_dither (visual_info, r, g, b, dither_adjustment);
 
1335
                }
 
1336
 
 
1337
                XPutPixel (&ximage, x, y, out_pixel);
 
1338
            }
 
1339
 
 
1340
            row += rowstride;
 
1341
        }
 
1342
    }
 
1343
 
 
1344
    status = _cairo_xlib_surface_get_gc (display, surface, &gc);
 
1345
    if (unlikely (status))
 
1346
        goto BAIL;
 
1347
 
 
1348
    if (ximage.obdata)
 
1349
        XShmPutImage (display->display, surface->drawable, gc, &ximage,
 
1350
                      src_x, src_y, dst_x, dst_y, width, height,
 
1351
                      shm_image == NULL);
 
1352
    else
 
1353
        XPutImage (display->display, surface->drawable, gc, &ximage,
 
1354
                   src_x, src_y, dst_x, dst_y, width, height);
 
1355
 
 
1356
    _cairo_xlib_surface_put_gc (display, surface, gc);
 
1357
 
 
1358
  BAIL:
 
1359
    cairo_device_release (&display->base);
 
1360
 
 
1361
    if (own_data)
 
1362
        free (ximage.data);
 
1363
    if (shm_image)
 
1364
        cairo_surface_destroy (shm_image);
 
1365
    if (pixman_image)
 
1366
        pixman_image_unref (pixman_image);
 
1367
 
 
1368
    return CAIRO_STATUS_SUCCESS;
 
1369
}
 
1370
 
 
1371
static cairo_surface_t *
 
1372
_cairo_xlib_surface_source(void                    *abstract_surface,
 
1373
                           cairo_rectangle_int_t *extents)
 
1374
{
 
1375
    cairo_xlib_surface_t *surface = abstract_surface;
 
1376
 
 
1377
    if (extents) {
 
1378
        extents->x = extents->y = 0;
 
1379
        extents->width  = surface->width;
 
1380
        extents->height = surface->height;
 
1381
    }
 
1382
 
 
1383
    return &surface->base;
 
1384
}
 
1385
 
 
1386
static cairo_status_t
 
1387
_cairo_xlib_surface_acquire_source_image (void                    *abstract_surface,
 
1388
                                          cairo_image_surface_t  **image_out,
 
1389
                                          void                   **image_extra)
 
1390
{
 
1391
    cairo_xlib_surface_t *surface = abstract_surface;
 
1392
    cairo_rectangle_int_t extents;
 
1393
 
 
1394
    *image_extra = NULL;
 
1395
    *image_out = (cairo_image_surface_t *)
 
1396
        _cairo_xlib_surface_get_shm (abstract_surface, FALSE);
 
1397
    if (*image_out) 
 
1398
            return (*image_out)->base.status;
 
1399
 
 
1400
    extents.x = extents.y = 0;
 
1401
    extents.width = surface->width;
 
1402
    extents.height = surface->height;
 
1403
 
 
1404
    *image_out = (cairo_image_surface_t*)
 
1405
        _get_image_surface (surface, &extents, TRUE);
 
1406
    return (*image_out)->base.status;
 
1407
}
 
1408
 
 
1409
static cairo_surface_t *
 
1410
_cairo_xlib_surface_snapshot (void *abstract_surface)
 
1411
{
 
1412
    cairo_xlib_surface_t *surface = abstract_surface;
 
1413
    cairo_rectangle_int_t extents;
 
1414
 
 
1415
    extents.x = extents.y = 0;
 
1416
    extents.width = surface->width;
 
1417
    extents.height = surface->height;
 
1418
 
 
1419
    return _get_image_surface (surface, &extents, FALSE);
 
1420
}
 
1421
 
 
1422
static void
 
1423
_cairo_xlib_surface_release_source_image (void                   *abstract_surface,
 
1424
                                          cairo_image_surface_t  *image,
 
1425
                                          void                   *image_extra)
 
1426
{
 
1427
    cairo_xlib_surface_t *surface = abstract_surface;
 
1428
 
 
1429
    if (&image->base == surface->shm)
 
1430
        return;
 
1431
 
 
1432
    cairo_surface_destroy (&image->base);
 
1433
}
 
1434
 
 
1435
static cairo_image_surface_t *
 
1436
_cairo_xlib_surface_map_to_image (void                    *abstract_surface,
 
1437
                                  const cairo_rectangle_int_t   *extents)
 
1438
{
 
1439
    cairo_xlib_surface_t *surface = abstract_surface;
 
1440
    cairo_surface_t *image;
 
1441
 
 
1442
    image = _cairo_xlib_surface_get_shm (abstract_surface, FALSE);
 
1443
    if (image) {
 
1444
        assert (surface->base.damage);
 
1445
        surface->fallback++;
 
1446
        return _cairo_image_surface_map_to_image (image, extents);
 
1447
    }
 
1448
 
 
1449
    image = _get_image_surface (abstract_surface, extents, TRUE);
 
1450
    cairo_surface_set_device_offset (image, -extents->x, -extents->y);
 
1451
 
 
1452
    return (cairo_image_surface_t *) image;
 
1453
}
 
1454
 
 
1455
static cairo_int_status_t
 
1456
_cairo_xlib_surface_unmap_image (void *abstract_surface,
 
1457
                                 cairo_image_surface_t *image)
 
1458
{
 
1459
    cairo_xlib_surface_t *surface = abstract_surface;
 
1460
    cairo_int_status_t status;
 
1461
 
 
1462
    if (surface->shm) {
 
1463
        cairo_rectangle_int_t r;
 
1464
 
 
1465
        assert (surface->fallback);
 
1466
        assert (surface->base.damage);
 
1467
 
 
1468
        r.x = image->base.device_transform_inverse.x0;
 
1469
        r.y = image->base.device_transform_inverse.y0;
 
1470
        r.width  = image->width;
 
1471
        r.height = image->height;
 
1472
 
 
1473
        TRACE ((stderr, "%s: adding damage (%d,%d)x(%d,%d)\n",
 
1474
                __FUNCTION__, r.x, r.y, r.width, r.height));
 
1475
        surface->shm->damage =
 
1476
            _cairo_damage_add_rectangle (surface->shm->damage, &r);
 
1477
 
 
1478
        return _cairo_image_surface_unmap_image (surface->shm, image);
 
1479
    }
 
1480
 
 
1481
    status = _cairo_xlib_surface_draw_image (abstract_surface, image,
 
1482
                                             0, 0,
 
1483
                                             image->width, image->height,
 
1484
                                             image->base.device_transform_inverse.x0,
 
1485
                                             image->base.device_transform_inverse.y0);
 
1486
 
 
1487
    cairo_surface_finish (&image->base);
 
1488
    cairo_surface_destroy (&image->base);
 
1489
 
 
1490
    return status;
 
1491
}
 
1492
 
 
1493
static cairo_status_t
 
1494
_cairo_xlib_surface_flush (void *abstract_surface,
 
1495
                           unsigned flags)
 
1496
{
 
1497
    cairo_xlib_surface_t *surface = abstract_surface;
 
1498
    cairo_int_status_t status;
 
1499
 
 
1500
    if (flags)
 
1501
        return CAIRO_STATUS_SUCCESS;
 
1502
 
 
1503
    status = _cairo_xlib_surface_put_shm (surface);
 
1504
    if (unlikely (status))
 
1505
        return status;
 
1506
 
 
1507
    surface->fallback >>= 1;
 
1508
    if (surface->shm && _cairo_xlib_shm_surface_is_idle (surface->shm))
 
1509
        _cairo_xlib_surface_discard_shm (surface);
 
1510
 
 
1511
    return CAIRO_STATUS_SUCCESS;
 
1512
}
 
1513
 
 
1514
static cairo_bool_t
 
1515
_cairo_xlib_surface_get_extents (void                    *abstract_surface,
 
1516
                                 cairo_rectangle_int_t   *rectangle)
 
1517
{
 
1518
    cairo_xlib_surface_t *surface = abstract_surface;
 
1519
 
 
1520
    rectangle->x = 0;
 
1521
    rectangle->y = 0;
 
1522
 
 
1523
    rectangle->width  = surface->width;
 
1524
    rectangle->height = surface->height;
 
1525
 
 
1526
    return TRUE;
 
1527
}
 
1528
 
 
1529
static void
 
1530
_cairo_xlib_surface_get_font_options (void                  *abstract_surface,
 
1531
                                      cairo_font_options_t  *options)
 
1532
{
 
1533
    cairo_xlib_surface_t *surface = abstract_surface;
 
1534
 
 
1535
    *options = *_cairo_xlib_screen_get_font_options (surface->screen);
 
1536
}
 
1537
 
 
1538
static inline cairo_int_status_t
 
1539
get_compositor (cairo_xlib_surface_t **surface,
 
1540
                const cairo_compositor_t **compositor)
 
1541
{
 
1542
    cairo_xlib_surface_t *s = *surface;
 
1543
    cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;;
 
1544
 
 
1545
    if (s->fallback) {
 
1546
        assert (s->base.damage != NULL);
 
1547
        assert (s->shm != NULL);
 
1548
        assert (s->shm->damage != NULL);
 
1549
        if (! _cairo_xlib_shm_surface_is_active (s->shm)) {
 
1550
            *surface = (cairo_xlib_surface_t *) s->shm;
 
1551
            *compositor = ((cairo_image_surface_t *) s->shm)->compositor;
 
1552
            s->fallback++;
 
1553
        } else {
 
1554
            status = _cairo_xlib_surface_put_shm (s);
 
1555
            s->fallback = 0;
 
1556
            *compositor = s->compositor;
 
1557
        }
 
1558
    } else
 
1559
        *compositor = s->compositor;
 
1560
 
 
1561
    return status;
 
1562
}
 
1563
 
 
1564
static cairo_int_status_t
 
1565
_cairo_xlib_surface_paint (void                         *_surface,
 
1566
                           cairo_operator_t              op,
 
1567
                           const cairo_pattern_t        *source,
 
1568
                           const cairo_clip_t           *clip)
 
1569
{
 
1570
    cairo_xlib_surface_t *surface = _surface;
 
1571
    const cairo_compositor_t *compositor;
 
1572
    cairo_int_status_t status;
 
1573
 
 
1574
    status = get_compositor (&surface, &compositor);
 
1575
    if (unlikely (status))
 
1576
        return status;
 
1577
 
 
1578
    return _cairo_compositor_paint (compositor, &surface->base,
 
1579
                                    op, source,
 
1580
                                    clip);
 
1581
}
 
1582
 
 
1583
static cairo_int_status_t
 
1584
_cairo_xlib_surface_mask (void                  *_surface,
 
1585
                          cairo_operator_t       op,
 
1586
                          const cairo_pattern_t *source,
 
1587
                          const cairo_pattern_t *mask,
 
1588
                          const cairo_clip_t    *clip)
 
1589
{
 
1590
    cairo_xlib_surface_t *surface = _surface;
 
1591
    const cairo_compositor_t *compositor;
 
1592
    cairo_int_status_t status;
 
1593
 
 
1594
    status = get_compositor (&surface, &compositor);
 
1595
    if (unlikely (status))
 
1596
        return status;
 
1597
 
 
1598
    return _cairo_compositor_mask (compositor, &surface->base,
 
1599
                                   op, source, mask,
 
1600
                                   clip);
 
1601
}
 
1602
 
 
1603
static cairo_int_status_t
 
1604
_cairo_xlib_surface_stroke (void                        *_surface,
 
1605
                            cairo_operator_t             op,
 
1606
                            const cairo_pattern_t       *source,
 
1607
                            const cairo_path_fixed_t    *path,
 
1608
                            const cairo_stroke_style_t  *style,
 
1609
                            const cairo_matrix_t        *ctm,
 
1610
                            const cairo_matrix_t        *ctm_inverse,
 
1611
                            double                       tolerance,
 
1612
                            cairo_antialias_t            antialias,
 
1613
                            const cairo_clip_t          *clip)
 
1614
{
 
1615
    cairo_xlib_surface_t *surface = _surface;
 
1616
    const cairo_compositor_t *compositor;
 
1617
    cairo_int_status_t status;
 
1618
 
 
1619
    status = get_compositor (&surface, &compositor);
 
1620
    if (unlikely (status))
 
1621
        return status;
 
1622
 
 
1623
    return _cairo_compositor_stroke (compositor, &surface->base,
 
1624
                                     op, source,
 
1625
                                     path, style, ctm, ctm_inverse,
 
1626
                                     tolerance, antialias,
 
1627
                                     clip);
 
1628
}
 
1629
 
 
1630
static cairo_int_status_t
 
1631
_cairo_xlib_surface_fill (void                          *_surface,
 
1632
                          cairo_operator_t               op,
 
1633
                          const cairo_pattern_t         *source,
 
1634
                          const cairo_path_fixed_t      *path,
 
1635
                          cairo_fill_rule_t              fill_rule,
 
1636
                          double                         tolerance,
 
1637
                          cairo_antialias_t              antialias,
 
1638
                          const cairo_clip_t            *clip)
 
1639
{
 
1640
    cairo_xlib_surface_t *surface = _surface;
 
1641
    const cairo_compositor_t *compositor;
 
1642
    cairo_int_status_t status;
 
1643
 
 
1644
    status = get_compositor (&surface, &compositor);
 
1645
    if (unlikely (status))
 
1646
        return status;
 
1647
 
 
1648
    return _cairo_compositor_fill (compositor, &surface->base,
 
1649
                                   op, source,
 
1650
                                   path, fill_rule, tolerance, antialias,
 
1651
                                   clip);
 
1652
}
 
1653
 
 
1654
static cairo_int_status_t
 
1655
_cairo_xlib_surface_glyphs (void                        *_surface,
 
1656
                            cairo_operator_t             op,
 
1657
                            const cairo_pattern_t       *source,
 
1658
                            cairo_glyph_t               *glyphs,
 
1659
                            int                          num_glyphs,
 
1660
                            cairo_scaled_font_t         *scaled_font,
 
1661
                            const cairo_clip_t          *clip)
 
1662
{
 
1663
    cairo_xlib_surface_t *surface = _surface;
 
1664
    const cairo_compositor_t *compositor;
 
1665
    cairo_int_status_t status;
 
1666
 
 
1667
    status = get_compositor (&surface, &compositor);
 
1668
    if (unlikely (status))
 
1669
        return status;
 
1670
 
 
1671
    return _cairo_compositor_glyphs (compositor, &surface->base,
 
1672
                                     op, source,
 
1673
                                     glyphs, num_glyphs, scaled_font,
 
1674
                                     clip);
 
1675
}
 
1676
 
 
1677
static const cairo_surface_backend_t cairo_xlib_surface_backend = {
 
1678
    CAIRO_SURFACE_TYPE_XLIB,
 
1679
    _cairo_xlib_surface_finish,
 
1680
 
 
1681
    _cairo_default_context_create,
 
1682
 
 
1683
    _cairo_xlib_surface_create_similar,
 
1684
    _cairo_xlib_surface_create_similar_shm,
 
1685
    _cairo_xlib_surface_map_to_image,
 
1686
    _cairo_xlib_surface_unmap_image,
 
1687
 
 
1688
    _cairo_xlib_surface_source,
 
1689
    _cairo_xlib_surface_acquire_source_image,
 
1690
    _cairo_xlib_surface_release_source_image,
 
1691
    _cairo_xlib_surface_snapshot,
 
1692
 
 
1693
    NULL, /* copy_page */
 
1694
    NULL, /* show_page */
 
1695
 
 
1696
    _cairo_xlib_surface_get_extents,
 
1697
    _cairo_xlib_surface_get_font_options,
 
1698
 
 
1699
    _cairo_xlib_surface_flush,
 
1700
    NULL, /* mark_dirty_rectangle */
 
1701
 
 
1702
    _cairo_xlib_surface_paint,
 
1703
    _cairo_xlib_surface_mask,
 
1704
    _cairo_xlib_surface_stroke,
 
1705
    _cairo_xlib_surface_fill,
 
1706
    NULL, /* fill-stroke */
 
1707
    _cairo_xlib_surface_glyphs,
 
1708
};
 
1709
 
 
1710
/**
 
1711
 * _cairo_surface_is_xlib:
 
1712
 * @surface: a #cairo_surface_t
 
1713
 *
 
1714
 * Checks if a surface is a #cairo_xlib_surface_t
 
1715
 *
 
1716
 * Return value: True if the surface is an xlib surface
 
1717
 **/
 
1718
static cairo_bool_t
 
1719
_cairo_surface_is_xlib (cairo_surface_t *surface)
 
1720
{
 
1721
    return surface->backend == &cairo_xlib_surface_backend;
 
1722
}
 
1723
 
 
1724
static cairo_surface_t *
 
1725
_cairo_xlib_surface_create_internal (cairo_xlib_screen_t        *screen,
 
1726
                                     Drawable                    drawable,
 
1727
                                     Visual                     *visual,
 
1728
                                     XRenderPictFormat          *xrender_format,
 
1729
                                     int                         width,
 
1730
                                     int                         height,
 
1731
                                     int                         depth)
 
1732
{
 
1733
    cairo_xlib_surface_t *surface;
 
1734
    cairo_xlib_display_t *display;
 
1735
    cairo_status_t status;
 
1736
 
 
1737
    if (depth == 0) {
 
1738
        if (xrender_format) {
 
1739
            depth = xrender_format->depth;
 
1740
 
 
1741
            /* XXX find matching visual for core/dithering fallbacks? */
 
1742
        } else if (visual) {
 
1743
            Screen *scr = screen->screen;
 
1744
 
 
1745
            if (visual == DefaultVisualOfScreen (scr)) {
 
1746
                depth = DefaultDepthOfScreen (scr);
 
1747
            } else  {
 
1748
                int j, k;
 
1749
 
 
1750
                /* This is ugly, but we have to walk over all visuals
 
1751
                 * for the display to find the correct depth.
 
1752
                 */
 
1753
                depth = 0;
 
1754
                for (j = 0; j < scr->ndepths; j++) {
 
1755
                    Depth *d = &scr->depths[j];
 
1756
                    for (k = 0; k < d->nvisuals; k++) {
 
1757
                        if (&d->visuals[k] == visual) {
 
1758
                            depth = d->depth;
 
1759
                            goto found;
 
1760
                        }
 
1761
                    }
 
1762
                }
 
1763
            }
 
1764
        }
 
1765
 
 
1766
        if (depth == 0)
 
1767
            return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
 
1768
 
 
1769
found:
 
1770
        ;
 
1771
    }
 
1772
 
 
1773
    surface = malloc (sizeof (cairo_xlib_surface_t));
 
1774
    if (unlikely (surface == NULL))
 
1775
        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
1776
 
 
1777
    status = _cairo_xlib_display_acquire (screen->device, &display);
 
1778
    if (unlikely (status)) {
 
1779
        free (surface);
 
1780
        return _cairo_surface_create_in_error (_cairo_error (status));
 
1781
    }
 
1782
 
 
1783
    surface->display = display;
 
1784
    if (CAIRO_RENDER_HAS_CREATE_PICTURE (display)) {
 
1785
        if (!xrender_format) {
 
1786
            if (visual) {
 
1787
                xrender_format = XRenderFindVisualFormat (display->display, visual);
 
1788
            } else if (depth == 1) {
 
1789
                xrender_format =
 
1790
                    _cairo_xlib_display_get_xrender_format (display,
 
1791
                                                            CAIRO_FORMAT_A1);
 
1792
            }
 
1793
        }
 
1794
    }
 
1795
 
 
1796
    cairo_device_release (&display->base);
 
1797
 
 
1798
    _cairo_surface_init (&surface->base,
 
1799
                         &cairo_xlib_surface_backend,
 
1800
                         screen->device,
 
1801
                         _xrender_format_to_content (xrender_format));
 
1802
 
 
1803
    surface->screen = screen;
 
1804
    surface->compositor = display->compositor;
 
1805
    surface->shm = NULL;
 
1806
    surface->fallback = 0;
 
1807
 
 
1808
    surface->drawable = drawable;
 
1809
    surface->owns_pixmap = FALSE;
 
1810
    surface->use_pixmap = 0;
 
1811
    surface->width = width;
 
1812
    surface->height = height;
 
1813
 
 
1814
    surface->picture = None;
 
1815
    surface->precision = PolyModePrecise;
 
1816
 
 
1817
    surface->embedded_source.picture = None;
 
1818
 
 
1819
    surface->visual = visual;
 
1820
    surface->xrender_format = xrender_format;
 
1821
    surface->depth = depth;
 
1822
 
 
1823
    /*
 
1824
     * Compute the pixel format masks from either a XrenderFormat or
 
1825
     * else from a visual; failing that we assume the drawable is an
 
1826
     * alpha-only pixmap as it could only have been created that way
 
1827
     * through the cairo_xlib_surface_create_for_bitmap function.
 
1828
     */
 
1829
    if (xrender_format) {
 
1830
        surface->a_mask = (unsigned long)
 
1831
            surface->xrender_format->direct.alphaMask
 
1832
            << surface->xrender_format->direct.alpha;
 
1833
        surface->r_mask = (unsigned long)
 
1834
            surface->xrender_format->direct.redMask
 
1835
            << surface->xrender_format->direct.red;
 
1836
        surface->g_mask = (unsigned long)
 
1837
            surface->xrender_format->direct.greenMask
 
1838
            << surface->xrender_format->direct.green;
 
1839
        surface->b_mask = (unsigned long)
 
1840
            surface->xrender_format->direct.blueMask
 
1841
            << surface->xrender_format->direct.blue;
 
1842
    } else if (visual) {
 
1843
        surface->a_mask = 0;
 
1844
        surface->r_mask = visual->red_mask;
 
1845
        surface->g_mask = visual->green_mask;
 
1846
        surface->b_mask = visual->blue_mask;
 
1847
    } else {
 
1848
        if (depth < 32)
 
1849
            surface->a_mask = (1 << depth) - 1;
 
1850
        else
 
1851
            surface->a_mask = 0xffffffff;
 
1852
        surface->r_mask = 0;
 
1853
        surface->g_mask = 0;
 
1854
        surface->b_mask = 0;
 
1855
    }
 
1856
 
 
1857
    cairo_list_add (&surface->link, &screen->surfaces);
 
1858
 
 
1859
    return &surface->base;
 
1860
}
 
1861
 
 
1862
static Screen *
 
1863
_cairo_xlib_screen_from_visual (Display *dpy, Visual *visual)
 
1864
{
 
1865
    int s, d, v;
 
1866
 
 
1867
    for (s = 0; s < ScreenCount (dpy); s++) {
 
1868
        Screen *screen;
 
1869
 
 
1870
        screen = ScreenOfDisplay (dpy, s);
 
1871
        if (visual == DefaultVisualOfScreen (screen))
 
1872
            return screen;
 
1873
 
 
1874
        for (d = 0; d < screen->ndepths; d++) {
 
1875
            Depth  *depth;
 
1876
 
 
1877
            depth = &screen->depths[d];
 
1878
            for (v = 0; v < depth->nvisuals; v++)
 
1879
                if (visual == &depth->visuals[v])
 
1880
                    return screen;
 
1881
        }
 
1882
    }
 
1883
 
 
1884
    return NULL;
 
1885
}
 
1886
 
 
1887
static cairo_bool_t valid_size (int width, int height)
 
1888
{
 
1889
    /* Note: the minimum surface size allowed in the X protocol is 1x1.
 
1890
     * However, as we historically did not check the minimum size we
 
1891
     * allowed applications to lie and set the correct size later (one hopes).
 
1892
     * To preserve compatability we must allow applications to use
 
1893
     * 0x0 surfaces.
 
1894
     */
 
1895
    return (width  >= 0 && width  <= XLIB_COORD_MAX &&
 
1896
            height >= 0 && height <= XLIB_COORD_MAX);
 
1897
}
 
1898
 
 
1899
/**
 
1900
 * cairo_xlib_surface_create:
 
1901
 * @dpy: an X Display
 
1902
 * @drawable: an X Drawable, (a Pixmap or a Window)
 
1903
 * @visual: the visual to use for drawing to @drawable. The depth
 
1904
 *          of the visual must match the depth of the drawable.
 
1905
 *          Currently, only TrueColor visuals are fully supported.
 
1906
 * @width: the current width of @drawable.
 
1907
 * @height: the current height of @drawable.
 
1908
 *
 
1909
 * Creates an Xlib surface that draws to the given drawable.
 
1910
 * The way that colors are represented in the drawable is specified
 
1911
 * by the provided visual.
 
1912
 *
 
1913
 * Note: If @drawable is a Window, then the function
 
1914
 * cairo_xlib_surface_set_size() must be called whenever the size of the
 
1915
 * window changes.
 
1916
 *
 
1917
 * When @drawable is a Window containing child windows then drawing to
 
1918
 * the created surface will be clipped by those child windows.  When
 
1919
 * the created surface is used as a source, the contents of the
 
1920
 * children will be included.
 
1921
 *
 
1922
 * Return value: the newly created surface
 
1923
 *
 
1924
 * Since: 1.0
 
1925
 **/
 
1926
cairo_surface_t *
 
1927
cairo_xlib_surface_create (Display     *dpy,
 
1928
                           Drawable     drawable,
 
1929
                           Visual      *visual,
 
1930
                           int          width,
 
1931
                           int          height)
 
1932
{
 
1933
    Screen *scr;
 
1934
    cairo_xlib_screen_t *screen;
 
1935
    cairo_status_t status;
 
1936
 
 
1937
    if (! valid_size (width, height)) {
 
1938
        /* you're lying, and you know it! */
 
1939
        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
 
1940
    }
 
1941
 
 
1942
    scr = _cairo_xlib_screen_from_visual (dpy, visual);
 
1943
    if (scr == NULL)
 
1944
        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
 
1945
 
 
1946
    status = _cairo_xlib_screen_get (dpy, scr, &screen);
 
1947
    if (unlikely (status))
 
1948
        return _cairo_surface_create_in_error (status);
 
1949
 
 
1950
    X_DEBUG ((dpy, "create (drawable=%x)", (unsigned int) drawable));
 
1951
 
 
1952
    return _cairo_xlib_surface_create_internal (screen, drawable,
 
1953
                                                visual, NULL,
 
1954
                                                width, height, 0);
 
1955
}
 
1956
 
 
1957
/**
 
1958
 * cairo_xlib_surface_create_for_bitmap:
 
1959
 * @dpy: an X Display
 
1960
 * @bitmap: an X Drawable, (a depth-1 Pixmap)
 
1961
 * @screen: the X Screen associated with @bitmap
 
1962
 * @width: the current width of @bitmap.
 
1963
 * @height: the current height of @bitmap.
 
1964
 *
 
1965
 * Creates an Xlib surface that draws to the given bitmap.
 
1966
 * This will be drawn to as a %CAIRO_FORMAT_A1 object.
 
1967
 *
 
1968
 * Return value: the newly created surface
 
1969
 *
 
1970
 * Since: 1.0
 
1971
 **/
 
1972
cairo_surface_t *
 
1973
cairo_xlib_surface_create_for_bitmap (Display  *dpy,
 
1974
                                      Pixmap    bitmap,
 
1975
                                      Screen   *scr,
 
1976
                                      int       width,
 
1977
                                      int       height)
 
1978
{
 
1979
    cairo_xlib_screen_t *screen;
 
1980
    cairo_status_t status;
 
1981
 
 
1982
    if (! valid_size (width, height))
 
1983
        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
 
1984
 
 
1985
    status = _cairo_xlib_screen_get (dpy, scr, &screen);
 
1986
    if (unlikely (status))
 
1987
        return _cairo_surface_create_in_error (status);
 
1988
 
 
1989
    X_DEBUG ((dpy, "create_for_bitmap (drawable=%x)", (unsigned int) bitmap));
 
1990
 
 
1991
    return _cairo_xlib_surface_create_internal (screen, bitmap,
 
1992
                                                NULL, NULL,
 
1993
                                                width, height, 1);
 
1994
}
 
1995
 
 
1996
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
 
1997
/**
 
1998
 * cairo_xlib_surface_create_with_xrender_format:
 
1999
 * @dpy: an X Display
 
2000
 * @drawable: an X Drawable, (a Pixmap or a Window)
 
2001
 * @screen: the X Screen associated with @drawable
 
2002
 * @format: the picture format to use for drawing to @drawable. The depth
 
2003
 *          of @format must match the depth of the drawable.
 
2004
 * @width: the current width of @drawable.
 
2005
 * @height: the current height of @drawable.
 
2006
 *
 
2007
 * Creates an Xlib surface that draws to the given drawable.
 
2008
 * The way that colors are represented in the drawable is specified
 
2009
 * by the provided picture format.
 
2010
 *
 
2011
 * Note: If @drawable is a Window, then the function
 
2012
 * cairo_xlib_surface_set_size() must be called whenever the size of the
 
2013
 * window changes.
 
2014
 *
 
2015
 * Return value: the newly created surface
 
2016
 *
 
2017
 * Since: 1.0
 
2018
 **/
 
2019
cairo_surface_t *
 
2020
cairo_xlib_surface_create_with_xrender_format (Display              *dpy,
 
2021
                                               Drawable             drawable,
 
2022
                                               Screen               *scr,
 
2023
                                               XRenderPictFormat    *format,
 
2024
                                               int                  width,
 
2025
                                               int                  height)
 
2026
{
 
2027
    cairo_xlib_screen_t *screen;
 
2028
    cairo_status_t status;
 
2029
 
 
2030
    if (! valid_size (width, height))
 
2031
        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
 
2032
 
 
2033
    status = _cairo_xlib_screen_get (dpy, scr, &screen);
 
2034
    if (unlikely (status))
 
2035
        return _cairo_surface_create_in_error (status);
 
2036
 
 
2037
    X_DEBUG ((dpy, "create_with_xrender_format (drawable=%x)", (unsigned int) drawable));
 
2038
 
 
2039
    return _cairo_xlib_surface_create_internal (screen, drawable,
 
2040
                                                _visual_for_xrender_format (scr, format),
 
2041
                                                format, width, height, 0);
 
2042
}
 
2043
 
 
2044
/**
 
2045
 * cairo_xlib_surface_get_xrender_format:
 
2046
 * @surface: an xlib surface
 
2047
 *
 
2048
 * Gets the X Render picture format that @surface uses for rendering with the
 
2049
 * X Render extension. If the surface was created by
 
2050
 * cairo_xlib_surface_create_with_xrender_format() originally, the return
 
2051
 * value is the format passed to that constructor.
 
2052
 *
 
2053
 * Return value: the XRenderPictFormat* associated with @surface,
 
2054
 * or %NULL if the surface is not an xlib surface
 
2055
 * or if the X Render extension is not available.
 
2056
 *
 
2057
 * Since: 1.6
 
2058
 **/
 
2059
XRenderPictFormat *
 
2060
cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
 
2061
{
 
2062
    cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
 
2063
 
 
2064
    /* Throw an error for a non-xlib surface */
 
2065
    if (! _cairo_surface_is_xlib (surface)) {
 
2066
        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
2067
        return NULL;
 
2068
    }
 
2069
 
 
2070
    return xlib_surface->xrender_format;
 
2071
}
 
2072
#endif
 
2073
 
 
2074
/**
 
2075
 * cairo_xlib_surface_set_size:
 
2076
 * @surface: a #cairo_surface_t for the XLib backend
 
2077
 * @width: the new width of the surface
 
2078
 * @height: the new height of the surface
 
2079
 *
 
2080
 * Informs cairo of the new size of the X Drawable underlying the
 
2081
 * surface. For a surface created for a Window (rather than a Pixmap),
 
2082
 * this function must be called each time the size of the window
 
2083
 * changes. (For a subwindow, you are normally resizing the window
 
2084
 * yourself, but for a toplevel window, it is necessary to listen for
 
2085
 * ConfigureNotify events.)
 
2086
 *
 
2087
 * A Pixmap can never change size, so it is never necessary to call
 
2088
 * this function on a surface created for a Pixmap.
 
2089
 *
 
2090
 * Since: 1.0
 
2091
 **/
 
2092
void
 
2093
cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
 
2094
                             int              width,
 
2095
                             int              height)
 
2096
{
 
2097
    cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
 
2098
    cairo_status_t status;
 
2099
 
 
2100
    if (unlikely (abstract_surface->status))
 
2101
        return;
 
2102
    if (unlikely (abstract_surface->finished)) {
 
2103
        _cairo_surface_set_error (abstract_surface,
 
2104
                                  _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 
2105
        return;
 
2106
    }
 
2107
 
 
2108
    if (! _cairo_surface_is_xlib (abstract_surface)) {
 
2109
        _cairo_surface_set_error (abstract_surface,
 
2110
                                  _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
 
2111
        return;
 
2112
    }
 
2113
 
 
2114
    if (surface->width == width && surface->height == height)
 
2115
        return;
 
2116
 
 
2117
    if (! valid_size (width, height)) {
 
2118
        _cairo_surface_set_error (abstract_surface,
 
2119
                                  _cairo_error (CAIRO_STATUS_INVALID_SIZE));
 
2120
        return;
 
2121
    }
 
2122
 
 
2123
    status = _cairo_surface_flush (abstract_surface, 0);
 
2124
    if (unlikely (status)) {
 
2125
        _cairo_surface_set_error (abstract_surface, status);
 
2126
        return;
 
2127
    }
 
2128
 
 
2129
    _cairo_xlib_surface_discard_shm (surface);
 
2130
 
 
2131
    surface->width = width;
 
2132
    surface->height = height;
 
2133
}
 
2134
 
 
2135
/**
 
2136
 * cairo_xlib_surface_set_drawable:
 
2137
 * @surface: a #cairo_surface_t for the XLib backend
 
2138
 * @drawable: the new drawable for the surface
 
2139
 * @width: the width of the new drawable
 
2140
 * @height: the height of the new drawable
 
2141
 *
 
2142
 * Informs cairo of a new X Drawable underlying the
 
2143
 * surface. The drawable must match the display, screen
 
2144
 * and format of the existing drawable or the application
 
2145
 * will get X protocol errors and will probably terminate.
 
2146
 * No checks are done by this function to ensure this
 
2147
 * compatibility.
 
2148
 *
 
2149
 * Since: 1.0
 
2150
 **/
 
2151
void
 
2152
cairo_xlib_surface_set_drawable (cairo_surface_t   *abstract_surface,
 
2153
                                 Drawable           drawable,
 
2154
                                 int                width,
 
2155
                                 int                height)
 
2156
{
 
2157
    cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
 
2158
    cairo_status_t status;
 
2159
 
 
2160
    if (unlikely (abstract_surface->status))
 
2161
        return;
 
2162
    if (unlikely (abstract_surface->finished)) {
 
2163
        status = _cairo_surface_set_error (abstract_surface,
 
2164
                                           _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
 
2165
        return;
 
2166
    }
 
2167
 
 
2168
    if (! _cairo_surface_is_xlib (abstract_surface)) {
 
2169
        status = _cairo_surface_set_error (abstract_surface,
 
2170
                                           _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
 
2171
        return;
 
2172
    }
 
2173
 
 
2174
    if (! valid_size (width, height)) {
 
2175
        status = _cairo_surface_set_error (abstract_surface,
 
2176
                                           _cairo_error (CAIRO_STATUS_INVALID_SIZE));
 
2177
        return;
 
2178
    }
 
2179
 
 
2180
    /* XXX: and what about this case? */
 
2181
    if (surface->owns_pixmap)
 
2182
        return;
 
2183
 
 
2184
    status = _cairo_surface_flush (abstract_surface, 0);
 
2185
    if (unlikely (status)) {
 
2186
        _cairo_surface_set_error (abstract_surface, status);
 
2187
        return;
 
2188
    }
 
2189
 
 
2190
    if (surface->drawable != drawable) {
 
2191
        cairo_xlib_display_t *display;
 
2192
 
 
2193
        status = _cairo_xlib_display_acquire (surface->base.device, &display);
 
2194
        if (unlikely (status))
 
2195
            return;
 
2196
 
 
2197
        X_DEBUG ((display->display, "set_drawable (drawable=%x)", (unsigned int) drawable));
 
2198
 
 
2199
        if (surface->picture != None) {
 
2200
            XRenderFreePicture (display->display, surface->picture);
 
2201
            if (unlikely (status)) {
 
2202
                status = _cairo_surface_set_error (&surface->base, status);
 
2203
                return;
 
2204
            }
 
2205
 
 
2206
            surface->picture = None;
 
2207
        }
 
2208
 
 
2209
        cairo_device_release (&display->base);
 
2210
 
 
2211
        surface->drawable = drawable;
 
2212
    }
 
2213
 
 
2214
    if (surface->width != width || surface->height != height) {
 
2215
        _cairo_xlib_surface_discard_shm (surface);
 
2216
 
 
2217
        surface->width = width;
 
2218
        surface->height = height;
 
2219
    }
 
2220
}
 
2221
 
 
2222
/**
 
2223
 * cairo_xlib_surface_get_display:
 
2224
 * @surface: a #cairo_xlib_surface_t
 
2225
 *
 
2226
 * Get the X Display for the underlying X Drawable.
 
2227
 *
 
2228
 * Return value: the display.
 
2229
 *
 
2230
 * Since: 1.2
 
2231
 **/
 
2232
Display *
 
2233
cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
 
2234
{
 
2235
    if (! _cairo_surface_is_xlib (abstract_surface)) {
 
2236
        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
2237
        return NULL;
 
2238
    }
 
2239
 
 
2240
    return ((cairo_xlib_display_t *) abstract_surface->device)->display;
 
2241
}
 
2242
 
 
2243
/**
 
2244
 * cairo_xlib_surface_get_drawable:
 
2245
 * @surface: a #cairo_xlib_surface_t
 
2246
 *
 
2247
 * Get the underlying X Drawable used for the surface.
 
2248
 *
 
2249
 * Return value: the drawable.
 
2250
 *
 
2251
 * Since: 1.2
 
2252
 **/
 
2253
Drawable
 
2254
cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
 
2255
{
 
2256
    cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
 
2257
 
 
2258
    if (! _cairo_surface_is_xlib (abstract_surface)) {
 
2259
        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
2260
        return 0;
 
2261
    }
 
2262
 
 
2263
    return surface->drawable;
 
2264
}
 
2265
 
 
2266
/**
 
2267
 * cairo_xlib_surface_get_screen:
 
2268
 * @surface: a #cairo_xlib_surface_t
 
2269
 *
 
2270
 * Get the X Screen for the underlying X Drawable.
 
2271
 *
 
2272
 * Return value: the screen.
 
2273
 *
 
2274
 * Since: 1.2
 
2275
 **/
 
2276
Screen *
 
2277
cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
 
2278
{
 
2279
    cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
 
2280
 
 
2281
    if (! _cairo_surface_is_xlib (abstract_surface)) {
 
2282
        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
2283
        return NULL;
 
2284
    }
 
2285
 
 
2286
    return surface->screen->screen;
 
2287
}
 
2288
 
 
2289
/**
 
2290
 * cairo_xlib_surface_get_visual:
 
2291
 * @surface: a #cairo_xlib_surface_t
 
2292
 *
 
2293
 * Gets the X Visual associated with @surface, suitable for use with the
 
2294
 * underlying X Drawable.  If @surface was created by
 
2295
 * cairo_xlib_surface_create(), the return value is the Visual passed to that
 
2296
 * constructor.
 
2297
 *
 
2298
 * Return value: the Visual or %NULL if there is no appropriate Visual for
 
2299
 * @surface.
 
2300
 *
 
2301
 * Since: 1.2
 
2302
 **/
 
2303
Visual *
 
2304
cairo_xlib_surface_get_visual (cairo_surface_t *surface)
 
2305
{
 
2306
    cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
 
2307
 
 
2308
    if (! _cairo_surface_is_xlib (surface)) {
 
2309
        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
2310
        return NULL;
 
2311
    }
 
2312
 
 
2313
    return xlib_surface->visual;
 
2314
}
 
2315
 
 
2316
/**
 
2317
 * cairo_xlib_surface_get_depth:
 
2318
 * @surface: a #cairo_xlib_surface_t
 
2319
 *
 
2320
 * Get the number of bits used to represent each pixel value.
 
2321
 *
 
2322
 * Return value: the depth of the surface in bits.
 
2323
 *
 
2324
 * Since: 1.2
 
2325
 **/
 
2326
int
 
2327
cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
 
2328
{
 
2329
    cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
 
2330
 
 
2331
    if (! _cairo_surface_is_xlib (abstract_surface)) {
 
2332
        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
2333
        return 0;
 
2334
    }
 
2335
 
 
2336
    return surface->depth;
 
2337
}
 
2338
 
 
2339
/**
 
2340
 * cairo_xlib_surface_get_width:
 
2341
 * @surface: a #cairo_xlib_surface_t
 
2342
 *
 
2343
 * Get the width of the X Drawable underlying the surface in pixels.
 
2344
 *
 
2345
 * Return value: the width of the surface in pixels.
 
2346
 *
 
2347
 * Since: 1.2
 
2348
 **/
 
2349
int
 
2350
cairo_xlib_surface_get_width (cairo_surface_t *abstract_surface)
 
2351
{
 
2352
    cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
 
2353
 
 
2354
    if (! _cairo_surface_is_xlib (abstract_surface)) {
 
2355
        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
2356
        return 0;
 
2357
    }
 
2358
 
 
2359
    return surface->width;
 
2360
}
 
2361
 
 
2362
/**
 
2363
 * cairo_xlib_surface_get_height:
 
2364
 * @surface: a #cairo_xlib_surface_t
 
2365
 *
 
2366
 * Get the height of the X Drawable underlying the surface in pixels.
 
2367
 *
 
2368
 * Return value: the height of the surface in pixels.
 
2369
 *
 
2370
 * Since: 1.2
 
2371
 **/
 
2372
int
 
2373
cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
 
2374
{
 
2375
    cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
 
2376
 
 
2377
    if (! _cairo_surface_is_xlib (abstract_surface)) {
 
2378
        _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
2379
        return 0;
 
2380
    }
 
2381
 
 
2382
    return surface->height;
 
2383
}
 
2384
 
 
2385
#endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */