~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-source.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
#include "cairoint.h"
 
42
 
 
43
#if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
 
44
 
 
45
#include "cairo-xlib-private.h"
 
46
#include "cairo-xlib-surface-private.h"
 
47
 
 
48
#include "cairo-error-private.h"
 
49
#include "cairo-image-surface-inline.h"
 
50
#include "cairo-paginated-private.h"
 
51
#include "cairo-pattern-inline.h"
 
52
#include "cairo-recording-surface-private.h"
 
53
#include "cairo-surface-backend-private.h"
 
54
#include "cairo-surface-offset-private.h"
 
55
#include "cairo-surface-observer-private.h"
 
56
#include "cairo-surface-snapshot-inline.h"
 
57
#include "cairo-surface-subsurface-inline.h"
 
58
 
 
59
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
 
60
 
 
61
static cairo_xlib_surface_t *
 
62
unwrap_source (const cairo_surface_pattern_t *pattern)
 
63
{
 
64
    cairo_rectangle_int_t limits;
 
65
    return (cairo_xlib_surface_t *)_cairo_pattern_get_source (pattern, &limits);
 
66
}
 
67
 
 
68
static cairo_status_t
 
69
_cairo_xlib_source_finish (void *abstract_surface)
 
70
{
 
71
    cairo_xlib_source_t *source = abstract_surface;
 
72
 
 
73
    XRenderFreePicture (source->dpy, source->picture);
 
74
    if (source->pixmap)
 
75
            XFreePixmap (source->dpy, source->pixmap);
 
76
    return CAIRO_STATUS_SUCCESS;
 
77
}
 
78
 
 
79
static const cairo_surface_backend_t cairo_xlib_source_backend = {
 
80
    CAIRO_SURFACE_TYPE_XLIB,
 
81
    _cairo_xlib_source_finish,
 
82
    NULL, /* read-only wrapper */
 
83
};
 
84
 
 
85
static cairo_status_t
 
86
_cairo_xlib_proxy_finish (void *abstract_surface)
 
87
{
 
88
    cairo_xlib_proxy_t *proxy = abstract_surface;
 
89
 
 
90
    XRenderFreePicture (proxy->source.dpy, proxy->source.picture);
 
91
    if (proxy->source.pixmap)
 
92
            XFreePixmap (proxy->source.dpy, proxy->source.pixmap);
 
93
    _cairo_xlib_shm_surface_mark_active (proxy->owner);
 
94
    cairo_surface_destroy (proxy->owner);
 
95
    return CAIRO_STATUS_SUCCESS;
 
96
}
 
97
 
 
98
static const cairo_surface_backend_t cairo_xlib_proxy_backend = {
 
99
    CAIRO_SURFACE_TYPE_XLIB,
 
100
    _cairo_xlib_proxy_finish,
 
101
    NULL, /* read-only wrapper */
 
102
};
 
103
 
 
104
static cairo_surface_t *
 
105
source (cairo_xlib_surface_t *dst, Picture picture, Pixmap pixmap)
 
106
{
 
107
    cairo_xlib_source_t *source;
 
108
 
 
109
    if (picture == None)
 
110
        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
111
 
 
112
    source = malloc (sizeof (*source));
 
113
    if (unlikely (source == NULL)) {
 
114
        XRenderFreePicture (dst->display->display, picture);
 
115
        if (pixmap)
 
116
                XFreePixmap (dst->display->display, pixmap);
 
117
        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
118
    }
 
119
 
 
120
    _cairo_surface_init (&source->base,
 
121
                         &cairo_xlib_source_backend,
 
122
                         NULL, /* device */
 
123
                         CAIRO_CONTENT_COLOR_ALPHA);
 
124
 
 
125
    /* The source exists only within an operation */
 
126
    source->picture = picture;
 
127
    source->pixmap = pixmap;
 
128
    source->dpy = dst->display->display;
 
129
 
 
130
    return &source->base;
 
131
}
 
132
 
 
133
static uint32_t
 
134
hars_petruska_f54_1_random (void)
 
135
{
 
136
#define rol(x,k) ((x << k) | (x >> (32-k)))
 
137
    static uint32_t x;
 
138
    return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
 
139
#undef rol
 
140
}
 
141
 
 
142
static const XTransform identity = {
 
143
    {
 
144
        { 1 << 16, 0x00000, 0x00000 },
 
145
        { 0x00000, 1 << 16, 0x00000 },
 
146
        { 0x00000, 0x00000, 1 << 16 },
 
147
    }
 
148
};
 
149
 
 
150
static cairo_bool_t
 
151
picture_set_matrix (cairo_xlib_display_t *display,
 
152
                    Picture picture,
 
153
                    const cairo_matrix_t *matrix,
 
154
                    cairo_filter_t        filter,
 
155
                    double                xc,
 
156
                    double                yc,
 
157
                    int                  *x_offset,
 
158
                    int                  *y_offset)
 
159
{
 
160
    XTransform xtransform;
 
161
    pixman_transform_t *pixman_transform;
 
162
    cairo_int_status_t status;
 
163
 
 
164
    /* Casting between pixman_transform_t and XTransform is safe because
 
165
     * they happen to be the exact same type.
 
166
     */
 
167
    pixman_transform = (pixman_transform_t *) &xtransform;
 
168
    status = _cairo_matrix_to_pixman_matrix_offset (matrix, filter, xc, yc,
 
169
                                                    pixman_transform,
 
170
                                                    x_offset, y_offset);
 
171
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
 
172
        return TRUE;
 
173
    if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
 
174
        return FALSE;
 
175
 
 
176
    if (memcmp (&xtransform, &identity, sizeof (XTransform)) == 0)
 
177
        return TRUE;
 
178
 
 
179
    /* a late check in case we perturb the matrix too far */
 
180
    if (! CAIRO_RENDER_HAS_PICTURE_TRANSFORM (display))
 
181
        return FALSE;
 
182
 
 
183
    XRenderSetPictureTransform (display->display, picture, &xtransform);
 
184
    return TRUE;
 
185
}
 
186
 
 
187
static cairo_status_t
 
188
picture_set_filter (Display *dpy,
 
189
                    Picture picture,
 
190
                    cairo_filter_t filter)
 
191
{
 
192
    const char *render_filter;
 
193
 
 
194
    switch (filter) {
 
195
    case CAIRO_FILTER_FAST:
 
196
        render_filter = FilterFast;
 
197
        break;
 
198
    case CAIRO_FILTER_GOOD:
 
199
        render_filter = FilterGood;
 
200
        break;
 
201
    case CAIRO_FILTER_BEST:
 
202
        render_filter = FilterBest;
 
203
        break;
 
204
    case CAIRO_FILTER_NEAREST:
 
205
        render_filter = FilterNearest;
 
206
        break;
 
207
    case CAIRO_FILTER_BILINEAR:
 
208
        render_filter = FilterBilinear;
 
209
        break;
 
210
    case CAIRO_FILTER_GAUSSIAN:
 
211
        /* XXX: The GAUSSIAN value has no implementation in cairo
 
212
         * whatsoever, so it was really a mistake to have it in the
 
213
         * API. We could fix this by officially deprecating it, or
 
214
         * else inventing semantics and providing an actual
 
215
         * implementation for it. */
 
216
    default:
 
217
        render_filter = FilterBest;
 
218
        break;
 
219
    }
 
220
 
 
221
    XRenderSetPictureFilter (dpy, picture, (char *) render_filter, NULL, 0);
 
222
    return CAIRO_STATUS_SUCCESS;
 
223
}
 
224
 
 
225
static int
 
226
extend_to_repeat (cairo_extend_t extend)
 
227
{
 
228
    switch (extend) {
 
229
    default:
 
230
        ASSERT_NOT_REACHED;
 
231
    case CAIRO_EXTEND_NONE:
 
232
        return RepeatNone;
 
233
    case CAIRO_EXTEND_REPEAT:
 
234
        return RepeatNormal;
 
235
    case CAIRO_EXTEND_REFLECT:
 
236
        return RepeatReflect;
 
237
    case CAIRO_EXTEND_PAD:
 
238
        return RepeatPad;
 
239
    }
 
240
}
 
241
 
 
242
static cairo_bool_t
 
243
picture_set_properties (cairo_xlib_display_t *display,
 
244
                        Picture picture,
 
245
                        const cairo_pattern_t *pattern,
 
246
                        const cairo_matrix_t *matrix,
 
247
                        const cairo_rectangle_int_t *extents,
 
248
                        int *x_off, int *y_off)
 
249
{
 
250
    XRenderPictureAttributes pa;
 
251
    int mask = 0;
 
252
 
 
253
    if (! picture_set_matrix (display, picture, matrix, pattern->filter,
 
254
                              extents->x + extents->width / 2,
 
255
                              extents->y + extents->height / 2,
 
256
                              x_off, y_off))
 
257
        return FALSE;
 
258
 
 
259
    picture_set_filter (display->display, picture, pattern->filter);
 
260
 
 
261
    if (pattern->has_component_alpha) {
 
262
        pa.component_alpha = 1;
 
263
        mask |= CPComponentAlpha;
 
264
    }
 
265
 
 
266
    if (pattern->extend != CAIRO_EXTEND_NONE) {
 
267
        pa.repeat = extend_to_repeat (pattern->extend);
 
268
        mask |= CPRepeat;
 
269
    }
 
270
 
 
271
    if (mask)
 
272
        XRenderChangePicture (display->display, picture, mask, &pa);
 
273
 
 
274
    return TRUE;
 
275
}
 
276
 
 
277
static cairo_surface_t *
 
278
render_pattern (cairo_xlib_surface_t *dst,
 
279
                const cairo_pattern_t *pattern,
 
280
                cairo_bool_t is_mask,
 
281
                const cairo_rectangle_int_t *extents,
 
282
                int *src_x, int *src_y)
 
283
{
 
284
    Display *dpy = dst->display->display;
 
285
    cairo_xlib_surface_t *src;
 
286
    cairo_image_surface_t *image;
 
287
    cairo_status_t status;
 
288
    cairo_rectangle_int_t map_extents;
 
289
 
 
290
    src = (cairo_xlib_surface_t *)
 
291
        _cairo_surface_create_similar_scratch (&dst->base,
 
292
                                               is_mask ? CAIRO_CONTENT_ALPHA : CAIRO_CONTENT_COLOR_ALPHA,
 
293
                                               extents->width,
 
294
                                               extents->height);
 
295
    if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
 
296
        cairo_surface_destroy (&src->base);
 
297
        return None;
 
298
    }
 
299
 
 
300
    map_extents = *extents;
 
301
    map_extents.x = map_extents.y = 0;
 
302
 
 
303
    image = _cairo_surface_map_to_image (&src->base, &map_extents);
 
304
    status = _cairo_surface_offset_paint (&image->base, extents->x, extents->y,
 
305
                                          CAIRO_OPERATOR_SOURCE, pattern,
 
306
                                          NULL);
 
307
    status = _cairo_surface_unmap_image (&src->base, image);
 
308
    if (unlikely (status)) {
 
309
        cairo_surface_destroy (&src->base);
 
310
        return _cairo_surface_create_in_error (status);
 
311
    }
 
312
 
 
313
    status = _cairo_xlib_surface_put_shm (src);
 
314
    if (unlikely (status)) {
 
315
        cairo_surface_destroy (&src->base);
 
316
        return _cairo_surface_create_in_error (status);
 
317
    }
 
318
 
 
319
    src->picture = XRenderCreatePicture (dpy,
 
320
                                         src->drawable, src->xrender_format,
 
321
                                         0, NULL);
 
322
 
 
323
    *src_x = -extents->x;
 
324
    *src_y = -extents->y;
 
325
    return &src->base;
 
326
}
 
327
 
 
328
static cairo_surface_t *
 
329
gradient_source (cairo_xlib_surface_t *dst,
 
330
                 const cairo_gradient_pattern_t *gradient,
 
331
                 cairo_bool_t is_mask,
 
332
                 const cairo_rectangle_int_t *extents,
 
333
                 int *src_x, int *src_y)
 
334
{
 
335
    cairo_xlib_display_t *display = dst->display;
 
336
    cairo_matrix_t matrix = gradient->base.matrix;
 
337
    char buf[CAIRO_STACK_BUFFER_SIZE];
 
338
    cairo_circle_double_t extremes[2];
 
339
    XFixed *stops;
 
340
    XRenderColor *colors;
 
341
    Picture picture;
 
342
    unsigned int i, n_stops;
 
343
 
 
344
    /* The RENDER specification says that the inner circle has
 
345
     * to be completely contained inside the outer one. */
 
346
    if (gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL &&
 
347
        ! _cairo_radial_pattern_focus_is_inside ((cairo_radial_pattern_t *) gradient))
 
348
        return render_pattern (dst, &gradient->base, is_mask, extents, src_x, src_y);
 
349
 
 
350
    assert (gradient->n_stops > 0);
 
351
    n_stops = MAX (gradient->n_stops, 2);
 
352
 
 
353
    if (n_stops < sizeof (buf) / (sizeof (XFixed) + sizeof (XRenderColor)))
 
354
    {
 
355
        stops = (XFixed *) buf;
 
356
    }
 
357
    else
 
358
    {
 
359
        stops =
 
360
            _cairo_malloc_ab (n_stops,
 
361
                              sizeof (XFixed) + sizeof (XRenderColor));
 
362
        if (unlikely (stops == NULL))
 
363
            return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
364
    }
 
365
 
 
366
    colors = (XRenderColor *) (stops + n_stops);
 
367
    for (i = 0; i < gradient->n_stops; i++) {
 
368
        stops[i] =
 
369
            _cairo_fixed_16_16_from_double (gradient->stops[i].offset);
 
370
 
 
371
        colors[i].red   = gradient->stops[i].color.red_short;
 
372
        colors[i].green = gradient->stops[i].color.green_short;
 
373
        colors[i].blue  = gradient->stops[i].color.blue_short;
 
374
        colors[i].alpha = gradient->stops[i].color.alpha_short;
 
375
    }
 
376
 
 
377
    /* RENDER does not support gradients with less than 2
 
378
     * stops. If a gradient has only a single stop, duplicate
 
379
     * it to make RENDER happy. */
 
380
    if (gradient->n_stops == 1) {
 
381
        stops[1] =
 
382
            _cairo_fixed_16_16_from_double (gradient->stops[0].offset);
 
383
 
 
384
        colors[1].red   = gradient->stops[0].color.red_short;
 
385
        colors[1].green = gradient->stops[0].color.green_short;
 
386
        colors[1].blue  = gradient->stops[0].color.blue_short;
 
387
        colors[1].alpha = gradient->stops[0].color.alpha_short;
 
388
    }
 
389
 
 
390
#if 0
 
391
    /* For some weird reason the X server is sometimes getting
 
392
     * CreateGradient requests with bad length. So far I've only seen
 
393
     * XRenderCreateLinearGradient request with 4 stops sometime end up
 
394
     * with length field matching 0 stops at the server side. I've
 
395
     * looked at the libXrender code and I can't see anything that
 
396
     * could cause this behavior. However, for some reason having a
 
397
     * XSync call here seems to avoid the issue so I'll keep it here
 
398
     * until it's solved.
 
399
     */
 
400
    XSync (display->display, False);
 
401
#endif
 
402
 
 
403
    _cairo_gradient_pattern_fit_to_range (gradient, PIXMAN_MAX_INT >> 1, &matrix, extremes);
 
404
 
 
405
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
 
406
        XLinearGradient grad;
 
407
 
 
408
        grad.p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
 
409
        grad.p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
 
410
        grad.p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
 
411
        grad.p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
 
412
 
 
413
        picture = XRenderCreateLinearGradient (display->display, &grad,
 
414
                                               stops, colors,
 
415
                                               n_stops);
 
416
    } else {
 
417
        XRadialGradient grad;
 
418
 
 
419
        grad.inner.x      = _cairo_fixed_16_16_from_double (extremes[0].center.x);
 
420
        grad.inner.y      = _cairo_fixed_16_16_from_double (extremes[0].center.y);
 
421
        grad.inner.radius = _cairo_fixed_16_16_from_double (extremes[0].radius);
 
422
        grad.outer.x      = _cairo_fixed_16_16_from_double (extremes[1].center.x);
 
423
        grad.outer.y      = _cairo_fixed_16_16_from_double (extremes[1].center.y);
 
424
        grad.outer.radius = _cairo_fixed_16_16_from_double (extremes[1].radius);
 
425
 
 
426
        picture = XRenderCreateRadialGradient (display->display, &grad,
 
427
                                               stops, colors,
 
428
                                               n_stops);
 
429
    }
 
430
 
 
431
    if (stops != (XFixed *) buf)
 
432
        free (stops);
 
433
 
 
434
    *src_x = *src_y = 0;
 
435
    if (! picture_set_properties (display, picture,
 
436
                                  &gradient->base, &gradient->base.matrix,
 
437
                                  extents,
 
438
                                  src_x, src_y)) {
 
439
        XRenderFreePicture (display->display, picture);
 
440
        return render_pattern (dst, &gradient->base, is_mask, extents, src_x, src_y);
 
441
    }
 
442
 
 
443
    return source (dst, picture, None);
 
444
}
 
445
 
 
446
static cairo_surface_t *
 
447
color_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
 
448
{
 
449
    Display *dpy = dst->display->display;
 
450
    XRenderColor xcolor;
 
451
    Picture picture;
 
452
    Pixmap pixmap = None;
 
453
 
 
454
    xcolor.red   = color->red_short;
 
455
    xcolor.green = color->green_short;
 
456
    xcolor.blue  = color->blue_short;
 
457
    xcolor.alpha = color->alpha_short;
 
458
 
 
459
    if (CAIRO_RENDER_HAS_GRADIENTS(dst->display)) {
 
460
        picture = XRenderCreateSolidFill (dpy, &xcolor);
 
461
    } else {
 
462
        XRenderPictureAttributes pa;
 
463
        int mask = 0;
 
464
 
 
465
        pa.repeat = RepeatNormal;
 
466
        mask |= CPRepeat;
 
467
 
 
468
        pixmap = XCreatePixmap (dpy, dst->drawable, 1, 1, 32);
 
469
        picture = XRenderCreatePicture (dpy, pixmap,
 
470
                                        _cairo_xlib_display_get_xrender_format (dst->display, CAIRO_FORMAT_ARGB32),
 
471
                                        mask, &pa);
 
472
 
 
473
        if (CAIRO_RENDER_HAS_FILL_RECTANGLES(dst->display)) {
 
474
            XRectangle r = { 0, 0, 1, 1};
 
475
            XRenderFillRectangles (dpy, PictOpSrc, picture, &xcolor, &r, 1);
 
476
        } else {
 
477
            XGCValues gcv;
 
478
            GC gc;
 
479
 
 
480
            gc = _cairo_xlib_screen_get_gc (dst->display, dst->screen,
 
481
                                            32, pixmap);
 
482
            if (unlikely (gc == NULL)) {
 
483
                XFreePixmap (dpy, pixmap);
 
484
                return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
485
            }
 
486
 
 
487
            gcv.foreground = 0;
 
488
            gcv.foreground |= color->alpha_short >> 8 << 24;
 
489
            gcv.foreground |= color->red_short   >> 8 << 16;
 
490
            gcv.foreground |= color->green_short >> 8 << 8;
 
491
            gcv.foreground |= color->blue_short  >> 8 << 0;
 
492
            gcv.fill_style = FillSolid;
 
493
 
 
494
            XChangeGC (dpy, gc, GCFillStyle | GCForeground, &gcv);
 
495
            XFillRectangle (dpy, pixmap, gc, 0, 0, 1, 1);
 
496
 
 
497
            _cairo_xlib_screen_put_gc (dst->display, dst->screen, 32, gc);
 
498
        }
 
499
    }
 
500
 
 
501
    return source (dst, picture, pixmap);
 
502
}
 
503
 
 
504
static cairo_surface_t *
 
505
alpha_source (cairo_xlib_surface_t *dst, uint8_t alpha)
 
506
{
 
507
    cairo_xlib_display_t *display = dst->display;
 
508
 
 
509
    if (display->alpha[alpha] == NULL) {
 
510
        cairo_color_t color;
 
511
 
 
512
        color.red_short = color.green_short = color.blue_short = 0;
 
513
        color.alpha_short = alpha << 8 | alpha;
 
514
 
 
515
        display->alpha[alpha] = color_source (dst, &color);
 
516
    }
 
517
 
 
518
    return cairo_surface_reference (display->alpha[alpha]);
 
519
}
 
520
 
 
521
static cairo_surface_t *
 
522
white_source (cairo_xlib_surface_t *dst)
 
523
{
 
524
    cairo_xlib_display_t *display = dst->display;
 
525
 
 
526
    if (display->white == NULL)
 
527
        display->white = color_source (dst, CAIRO_COLOR_WHITE);
 
528
 
 
529
    return cairo_surface_reference (display->white);
 
530
}
 
531
 
 
532
static cairo_surface_t *
 
533
opaque_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
 
534
{
 
535
    cairo_xlib_display_t *display = dst->display;
 
536
    uint32_t pixel =
 
537
        0xff000000 |
 
538
        color->red_short   >> 8 << 16 |
 
539
        color->green_short >> 8 << 8 |
 
540
        color->blue_short  >> 8 << 0;
 
541
    int i;
 
542
 
 
543
    if (display->last_solid_cache[0].color == pixel)
 
544
        return cairo_surface_reference (display->solid[display->last_solid_cache[0].index]);
 
545
 
 
546
    for (i = 0; i < 16; i++) {
 
547
        if (display->solid_cache[i] == pixel)
 
548
            goto done;
 
549
    }
 
550
 
 
551
    i = hars_petruska_f54_1_random () % 16;
 
552
    cairo_surface_destroy (display->solid[i]);
 
553
 
 
554
    display->solid[i] = color_source (dst, color);
 
555
    display->solid_cache[i] = pixel;
 
556
 
 
557
done:
 
558
    display->last_solid_cache[0].color = pixel;
 
559
    display->last_solid_cache[0].index = i;
 
560
    return cairo_surface_reference (display->solid[i]);
 
561
}
 
562
 
 
563
static cairo_surface_t *
 
564
transparent_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
 
565
{
 
566
    cairo_xlib_display_t *display = dst->display;
 
567
    uint32_t pixel =
 
568
        color->alpha_short >> 8 << 24 |
 
569
        color->red_short   >> 8 << 16 |
 
570
        color->green_short >> 8 << 8 |
 
571
        color->blue_short  >> 8 << 0;
 
572
    int i;
 
573
 
 
574
    if (display->last_solid_cache[1].color == pixel) {
 
575
    assert (display->solid[display->last_solid_cache[1].index]);
 
576
        return cairo_surface_reference (display->solid[display->last_solid_cache[1].index]);
 
577
    }
 
578
 
 
579
    for (i = 16; i < 32; i++) {
 
580
        if (display->solid_cache[i] == pixel)
 
581
            goto done;
 
582
    }
 
583
 
 
584
    i = 16 + (hars_petruska_f54_1_random () % 16);
 
585
    cairo_surface_destroy (display->solid[i]);
 
586
 
 
587
    display->solid[i] = color_source (dst, color);
 
588
    display->solid_cache[i] = pixel;
 
589
 
 
590
done:
 
591
    display->last_solid_cache[1].color = pixel;
 
592
    display->last_solid_cache[1].index = i;
 
593
    assert (display->solid[i]);
 
594
    return cairo_surface_reference (display->solid[i]);
 
595
}
 
596
 
 
597
static cairo_surface_t *
 
598
solid_source (cairo_xlib_surface_t *dst,
 
599
              const cairo_color_t *color)
 
600
{
 
601
    if ((color->red_short | color->green_short | color->blue_short) <= 0xff)
 
602
        return alpha_source (dst, color->alpha_short >> 8);
 
603
 
 
604
    if (CAIRO_ALPHA_SHORT_IS_OPAQUE (color->alpha_short)) {
 
605
        if (color->red_short >= 0xff00 && color->green_short >= 0xff00 && color->blue_short >= 0xff00)
 
606
            return white_source (dst);
 
607
 
 
608
        return opaque_source (dst, color);
 
609
    } else
 
610
        return transparent_source (dst, color);
 
611
}
 
612
 
 
613
static cairo_xlib_source_t *init_source (cairo_xlib_surface_t *dst,
 
614
                                         cairo_xlib_surface_t *src)
 
615
{
 
616
    Display *dpy = dst->display->display;
 
617
    cairo_xlib_source_t *source = &src->embedded_source;
 
618
 
 
619
    /* As these are frequent and meant to be fast, we track pictures for
 
620
     * native surface and minimise update requests.
 
621
     */
 
622
    if (source->picture == None) {
 
623
        XRenderPictureAttributes pa;
 
624
 
 
625
        _cairo_surface_init (&source->base,
 
626
                             &cairo_xlib_source_backend,
 
627
                             NULL, /* device */
 
628
                             CAIRO_CONTENT_COLOR_ALPHA);
 
629
 
 
630
        pa.subwindow_mode = IncludeInferiors;
 
631
        source->picture = XRenderCreatePicture (dpy,
 
632
                                                src->drawable,
 
633
                                                src->xrender_format,
 
634
                                                CPSubwindowMode, &pa);
 
635
 
 
636
        source->has_component_alpha = 0;
 
637
        source->has_matrix = 0;
 
638
        source->filter = CAIRO_FILTER_NEAREST;
 
639
        source->extend = CAIRO_EXTEND_NONE;
 
640
    }
 
641
 
 
642
    return (cairo_xlib_source_t *) cairo_surface_reference (&source->base);
 
643
}
 
644
 
 
645
static cairo_surface_t *
 
646
embedded_source (cairo_xlib_surface_t *dst,
 
647
                 const cairo_surface_pattern_t *pattern,
 
648
                 const cairo_rectangle_int_t *extents,
 
649
                 int *src_x, int *src_y,
 
650
                 cairo_xlib_source_t *source)
 
651
{
 
652
    Display *dpy = dst->display->display;
 
653
    cairo_int_status_t status;
 
654
    XTransform xtransform;
 
655
    XRenderPictureAttributes pa;
 
656
    unsigned mask = 0;
 
657
 
 
658
    status = _cairo_matrix_to_pixman_matrix_offset (&pattern->base.matrix,
 
659
                                                    pattern->base.filter,
 
660
                                                    extents->x + extents->width / 2,
 
661
                                                    extents->y + extents->height / 2,
 
662
                                                    (pixman_transform_t *)&xtransform,
 
663
                                                    src_x, src_y);
 
664
 
 
665
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
 
666
        if (source->has_matrix) {
 
667
            source->has_matrix = 0;
 
668
            memcpy (&xtransform, &identity, sizeof (identity));
 
669
            status = CAIRO_INT_STATUS_SUCCESS;
 
670
        }
 
671
    } else
 
672
        source->has_matrix = 1;
 
673
    if (status == CAIRO_INT_STATUS_SUCCESS)
 
674
        XRenderSetPictureTransform (dpy, source->picture, &xtransform);
 
675
 
 
676
    if (source->filter != pattern->base.filter) {
 
677
        picture_set_filter (dpy, source->picture, pattern->base.filter);
 
678
        source->filter = pattern->base.filter;
 
679
    }
 
680
 
 
681
    if (source->has_component_alpha != pattern->base.has_component_alpha) {
 
682
        pa.component_alpha = pattern->base.has_component_alpha;
 
683
        mask |= CPComponentAlpha;
 
684
        source->has_component_alpha = pattern->base.has_component_alpha;
 
685
    }
 
686
 
 
687
    if (source->extend != pattern->base.extend) {
 
688
        pa.repeat = extend_to_repeat (pattern->base.extend);
 
689
        mask |= CPRepeat;
 
690
        source->extend = pattern->base.extend;
 
691
    }
 
692
 
 
693
    if (mask)
 
694
        XRenderChangePicture (dpy, source->picture, mask, &pa);
 
695
 
 
696
    return &source->base;
 
697
}
 
698
 
 
699
static cairo_surface_t *
 
700
subsurface_source (cairo_xlib_surface_t *dst,
 
701
                   const cairo_surface_pattern_t *pattern,
 
702
                   cairo_bool_t is_mask,
 
703
                   const cairo_rectangle_int_t *extents,
 
704
                   const cairo_rectangle_int_t *sample,
 
705
                   int *src_x, int *src_y)
 
706
{
 
707
    cairo_surface_subsurface_t *sub;
 
708
    cairo_xlib_surface_t *src;
 
709
    cairo_xlib_source_t *source;
 
710
    Display *dpy = dst->display->display;
 
711
    cairo_int_status_t status;
 
712
    cairo_surface_pattern_t local_pattern;
 
713
    XTransform xtransform;
 
714
    XRenderPictureAttributes pa;
 
715
    unsigned mask = 0;
 
716
 
 
717
    sub = (cairo_surface_subsurface_t *) pattern->surface;
 
718
 
 
719
    if (sample->x >= 0 && sample->y >= 0 &&
 
720
        sample->x + sample->width  <= sub->extents.width &&
 
721
        sample->y + sample->height <= sub->extents.height)
 
722
    {
 
723
        src = (cairo_xlib_surface_t *) sub->target;
 
724
        status = _cairo_surface_flush (&src->base, 0);
 
725
        if (unlikely (status))
 
726
            return _cairo_surface_create_in_error (status);
 
727
 
 
728
        if (pattern->base.filter == CAIRO_FILTER_NEAREST &&
 
729
            _cairo_matrix_is_translation (&pattern->base.matrix))
 
730
        {
 
731
            *src_x += pattern->base.matrix.x0 + sub->extents.x;
 
732
            *src_y += pattern->base.matrix.y0 + sub->extents.y;
 
733
 
 
734
            _cairo_xlib_surface_ensure_picture (src);
 
735
            return cairo_surface_reference (&src->base);
 
736
        }
 
737
        else
 
738
        {
 
739
            cairo_surface_pattern_t local_pattern = *pattern;
 
740
            local_pattern.base.matrix.x0 += sub->extents.x;
 
741
            local_pattern.base.matrix.y0 += sub->extents.y;
 
742
            local_pattern.base.extend = CAIRO_EXTEND_NONE;
 
743
            return embedded_source (dst, &local_pattern, extents,
 
744
                                    src_x, src_y, init_source (dst, src));
 
745
        }
 
746
    }
 
747
 
 
748
    if (sub->snapshot && sub->snapshot->type == CAIRO_SURFACE_TYPE_XLIB) {
 
749
        src = (cairo_xlib_surface_t *) cairo_surface_reference (sub->snapshot);
 
750
        source = &src->embedded_source;
 
751
    } else {
 
752
        src = (cairo_xlib_surface_t *)
 
753
            _cairo_surface_create_similar_scratch (&dst->base,
 
754
                                                   sub->base.content,
 
755
                                                   sub->extents.width,
 
756
                                                   sub->extents.height);
 
757
        if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
 
758
            cairo_surface_destroy (&src->base);
 
759
            return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
 
760
        }
 
761
 
 
762
        _cairo_pattern_init_for_surface (&local_pattern, sub->target);
 
763
        cairo_matrix_init_translate (&local_pattern.base.matrix,
 
764
                                     sub->extents.x, sub->extents.y);
 
765
        local_pattern.base.filter = CAIRO_FILTER_NEAREST;
 
766
        status = _cairo_surface_paint (&src->base,
 
767
                                       CAIRO_OPERATOR_SOURCE,
 
768
                                       &local_pattern.base,
 
769
                                       NULL);
 
770
        _cairo_pattern_fini (&local_pattern.base);
 
771
 
 
772
        if (unlikely (status)) {
 
773
            cairo_surface_destroy (&src->base);
 
774
            return _cairo_surface_create_in_error (status);
 
775
        }
 
776
 
 
777
        _cairo_xlib_surface_ensure_picture (src);
 
778
        _cairo_surface_subsurface_set_snapshot (&sub->base, &src->base);
 
779
 
 
780
        source = &src->embedded_source;
 
781
        source->has_component_alpha = 0;
 
782
        source->has_matrix = 0;
 
783
        source->filter = CAIRO_FILTER_NEAREST;
 
784
        source->extend = CAIRO_EXTEND_NONE;
 
785
    }
 
786
 
 
787
    status = _cairo_matrix_to_pixman_matrix_offset (&pattern->base.matrix,
 
788
                                                    pattern->base.filter,
 
789
                                                    extents->x + extents->width / 2,
 
790
                                                    extents->y + extents->height / 2,
 
791
                                                    (pixman_transform_t *)&xtransform,
 
792
                                                    src_x, src_y);
 
793
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
 
794
        if (source->has_matrix) {
 
795
            source->has_matrix = 0;
 
796
            memcpy (&xtransform, &identity, sizeof (identity));
 
797
            status = CAIRO_INT_STATUS_SUCCESS;
 
798
        }
 
799
    } else
 
800
        source->has_matrix = 1;
 
801
    if (status == CAIRO_INT_STATUS_SUCCESS)
 
802
        XRenderSetPictureTransform (dpy, src->picture, &xtransform);
 
803
 
 
804
    if (source->filter != pattern->base.filter) {
 
805
        picture_set_filter (dpy, src->picture, pattern->base.filter);
 
806
        source->filter = pattern->base.filter;
 
807
    }
 
808
 
 
809
    if (source->has_component_alpha != pattern->base.has_component_alpha) {
 
810
        pa.component_alpha = pattern->base.has_component_alpha;
 
811
        mask |= CPComponentAlpha;
 
812
        source->has_component_alpha = pattern->base.has_component_alpha;
 
813
    }
 
814
 
 
815
    if (source->extend != pattern->base.extend) {
 
816
        pa.repeat = extend_to_repeat (pattern->base.extend);
 
817
        mask |= CPRepeat;
 
818
        source->extend = pattern->base.extend;
 
819
    }
 
820
 
 
821
    if (mask)
 
822
        XRenderChangePicture (dpy, src->picture, mask, &pa);
 
823
 
 
824
    return &src->base;
 
825
}
 
826
 
 
827
static cairo_surface_t *
 
828
native_source (cairo_xlib_surface_t *dst,
 
829
               const cairo_surface_pattern_t *pattern,
 
830
               cairo_bool_t is_mask,
 
831
               const cairo_rectangle_int_t *extents,
 
832
               const cairo_rectangle_int_t *sample,
 
833
               int *src_x, int *src_y)
 
834
{
 
835
    cairo_xlib_surface_t *src;
 
836
    cairo_int_status_t status;
 
837
 
 
838
    if (_cairo_surface_is_subsurface (pattern->surface))
 
839
        return subsurface_source (dst, pattern, is_mask,
 
840
                                  extents, sample,
 
841
                                  src_x, src_y);
 
842
 
 
843
    src = unwrap_source (pattern);
 
844
    status = _cairo_surface_flush (&src->base, 0);
 
845
    if (unlikely (status))
 
846
        return _cairo_surface_create_in_error (status);
 
847
 
 
848
    if (pattern->base.filter == CAIRO_FILTER_NEAREST &&
 
849
        sample->x >= 0 && sample->y >= 0 &&
 
850
        sample->x + sample->width  <= src->width &&
 
851
        sample->y + sample->height <= src->height &&
 
852
        _cairo_matrix_is_translation (&pattern->base.matrix))
 
853
    {
 
854
        *src_x += pattern->base.matrix.x0;
 
855
        *src_y += pattern->base.matrix.y0;
 
856
        _cairo_xlib_surface_ensure_picture (src);
 
857
        return cairo_surface_reference (&src->base);
 
858
    }
 
859
 
 
860
    return embedded_source (dst, pattern, extents, src_x, src_y,
 
861
                            init_source (dst, src));
 
862
}
 
863
 
 
864
static cairo_surface_t *
 
865
recording_pattern_get_surface (const cairo_pattern_t *pattern)
 
866
{
 
867
    cairo_surface_t *surface;
 
868
 
 
869
    surface = ((const cairo_surface_pattern_t *) pattern)->surface;
 
870
    if (_cairo_surface_is_paginated (surface))
 
871
        surface = _cairo_paginated_surface_get_recording (surface);
 
872
    if (_cairo_surface_is_snapshot (surface))
 
873
        surface = _cairo_surface_snapshot_get_target (surface);
 
874
    return surface;
 
875
}
 
876
 
 
877
static cairo_surface_t *
 
878
record_source (cairo_xlib_surface_t *dst,
 
879
               const cairo_surface_pattern_t *pattern,
 
880
               cairo_bool_t is_mask,
 
881
               const cairo_rectangle_int_t *extents,
 
882
               const cairo_rectangle_int_t *sample,
 
883
               int *src_x, int *src_y)
 
884
{
 
885
    cairo_xlib_surface_t *src;
 
886
    cairo_matrix_t matrix, m;
 
887
    cairo_status_t status;
 
888
    cairo_rectangle_int_t upload, limit;
 
889
 
 
890
    upload = *sample;
 
891
    if (_cairo_surface_get_extents (pattern->surface, &limit) &&
 
892
        ! _cairo_rectangle_intersect (&upload, &limit))
 
893
    {
 
894
        if (pattern->base.extend == CAIRO_EXTEND_NONE)
 
895
            return alpha_source (dst, 0);
 
896
 
 
897
        upload = limit;
 
898
    }
 
899
 
 
900
    src = (cairo_xlib_surface_t *)
 
901
        _cairo_surface_create_similar_scratch (&dst->base,
 
902
                                               pattern->surface->content,
 
903
                                               upload.width,
 
904
                                               upload.height);
 
905
    if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
 
906
        cairo_surface_destroy (&src->base);
 
907
        return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
 
908
    }
 
909
 
 
910
    cairo_matrix_init_translate (&matrix, upload.x, upload.y);
 
911
    status = _cairo_recording_surface_replay_with_clip (recording_pattern_get_surface (&pattern->base),
 
912
                                                        &matrix, &src->base,
 
913
                                                        NULL);
 
914
    if (unlikely (status)) {
 
915
        cairo_surface_destroy (&src->base);
 
916
        return _cairo_surface_create_in_error (status);
 
917
    }
 
918
 
 
919
    matrix = pattern->base.matrix;
 
920
    if (upload.x | upload.y) {
 
921
        cairo_matrix_init_translate (&m, -upload.x, -upload.y);
 
922
        cairo_matrix_multiply (&matrix, &matrix, &m);
 
923
    }
 
924
 
 
925
    _cairo_xlib_surface_ensure_picture (src);
 
926
    if (! picture_set_properties (src->display, src->picture,
 
927
                                  &pattern->base, &matrix, extents,
 
928
                                  src_x, src_y))
 
929
    {
 
930
        cairo_surface_destroy (&src->base);
 
931
        return render_pattern (dst, &pattern->base, is_mask,
 
932
                               extents, src_x, src_y);
 
933
    }
 
934
 
 
935
    return &src->base;
 
936
}
 
937
 
 
938
static cairo_surface_t *
 
939
surface_source (cairo_xlib_surface_t *dst,
 
940
                const cairo_surface_pattern_t *pattern,
 
941
                cairo_bool_t is_mask,
 
942
                const cairo_rectangle_int_t *extents,
 
943
                const cairo_rectangle_int_t *sample,
 
944
                int *src_x, int *src_y)
 
945
{
 
946
    cairo_surface_t *src;
 
947
    cairo_xlib_surface_t *xsrc;
 
948
    cairo_surface_pattern_t local_pattern;
 
949
    cairo_status_t status;
 
950
    cairo_rectangle_int_t upload, limit;
 
951
 
 
952
    src = pattern->surface;
 
953
    if (src->type == CAIRO_SURFACE_TYPE_IMAGE &&
 
954
        src->device == dst->base.device &&
 
955
        _cairo_xlib_shm_surface_get_pixmap (src)) {
 
956
        cairo_xlib_proxy_t *proxy;
 
957
 
 
958
        cairo_surface_reference (src);
 
959
 
 
960
        proxy = malloc (sizeof(*proxy));
 
961
        if (unlikely (proxy == NULL)) {
 
962
            cairo_surface_destroy (src);
 
963
            return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
 
964
        }
 
965
 
 
966
        _cairo_surface_init (&proxy->source.base,
 
967
                             &cairo_xlib_proxy_backend,
 
968
                             dst->base.device,
 
969
                             CAIRO_CONTENT_COLOR_ALPHA);
 
970
 
 
971
        proxy->source.dpy = dst->display->display;
 
972
        proxy->source.picture = XRenderCreatePicture (proxy->source.dpy,
 
973
                                                      _cairo_xlib_shm_surface_get_pixmap (src),
 
974
                                                      _cairo_xlib_shm_surface_get_xrender_format (src),
 
975
                                                      0, NULL);
 
976
        proxy->source.pixmap = None;
 
977
 
 
978
        proxy->source.has_component_alpha = 0;
 
979
        proxy->source.has_matrix = 0;
 
980
        proxy->source.filter = CAIRO_FILTER_NEAREST;
 
981
        proxy->source.extend = CAIRO_EXTEND_NONE;
 
982
        proxy->owner = src;
 
983
 
 
984
        return embedded_source (dst, pattern, extents, src_x, src_y,
 
985
                                &proxy->source);
 
986
    }
 
987
 
 
988
    upload = *sample;
 
989
    if (_cairo_surface_get_extents (pattern->surface, &limit)) {
 
990
        if (pattern->base.extend == CAIRO_EXTEND_NONE) {
 
991
            if (! _cairo_rectangle_intersect (&upload, &limit))
 
992
                return alpha_source (dst, 0);
 
993
        } else {
 
994
            if (upload.x < limit.x ||
 
995
                upload.x + upload.width > limit.x + limit.width ||
 
996
                upload.y < limit.y ||
 
997
                upload.y + upload.height > limit.y + limit.height)
 
998
            {
 
999
                upload = limit;
 
1000
            }
 
1001
        }
 
1002
    }
 
1003
 
 
1004
    xsrc = (cairo_xlib_surface_t *)
 
1005
            _cairo_surface_create_similar_scratch (&dst->base,
 
1006
                                                   src->content,
 
1007
                                                   upload.width,
 
1008
                                                   upload.height);
 
1009
    if (xsrc->base.type != CAIRO_SURFACE_TYPE_XLIB) {
 
1010
        cairo_surface_destroy (src);
 
1011
        cairo_surface_destroy (&xsrc->base);
 
1012
        return None;
 
1013
    }
 
1014
 
 
1015
    if (_cairo_surface_is_image (src)) {
 
1016
        status = _cairo_xlib_surface_draw_image (xsrc, (cairo_image_surface_t *)src,
 
1017
                                                 upload.x, upload.y,
 
1018
                                                 upload.width, upload.height,
 
1019
                                                 0, 0);
 
1020
    } else {
 
1021
        cairo_image_surface_t *image;
 
1022
        cairo_rectangle_int_t map_extents = { 0,0, upload.width,upload.height };
 
1023
 
 
1024
        image = _cairo_surface_map_to_image (&xsrc->base, &map_extents);
 
1025
 
 
1026
        _cairo_pattern_init_for_surface (&local_pattern, pattern->surface);
 
1027
        cairo_matrix_init_translate (&local_pattern.base.matrix,
 
1028
                                     upload.x, upload.y);
 
1029
 
 
1030
        status = _cairo_surface_paint (&image->base,
 
1031
                                       CAIRO_OPERATOR_SOURCE,
 
1032
                                       &local_pattern.base,
 
1033
                                       NULL);
 
1034
        _cairo_pattern_fini (&local_pattern.base);
 
1035
 
 
1036
        status = _cairo_surface_unmap_image (&xsrc->base, image);
 
1037
        if (unlikely (status)) {
 
1038
            cairo_surface_destroy (src);
 
1039
            return _cairo_surface_create_in_error (status);
 
1040
        }
 
1041
    }
 
1042
 
 
1043
    _cairo_pattern_init_static_copy (&local_pattern.base, &pattern->base);
 
1044
    if (upload.x | upload.y) {
 
1045
        cairo_matrix_t m;
 
1046
        cairo_matrix_init_translate (&m, -upload.x, -upload.y);
 
1047
        cairo_matrix_multiply (&local_pattern.base.matrix,
 
1048
                               &local_pattern.base.matrix,
 
1049
                               &m);
 
1050
    }
 
1051
 
 
1052
    *src_x = *src_y = 0;
 
1053
    _cairo_xlib_surface_ensure_picture (xsrc);
 
1054
    if (! picture_set_properties (xsrc->display,
 
1055
                                  xsrc->picture,
 
1056
                                  &local_pattern.base,
 
1057
                                  &local_pattern.base.matrix,
 
1058
                                  extents,
 
1059
                                  src_x, src_y))
 
1060
    {
 
1061
        cairo_surface_destroy (&xsrc->base);
 
1062
        return render_pattern (dst, &pattern->base,
 
1063
                               is_mask, extents,
 
1064
                               src_x, src_y);
 
1065
    }
 
1066
 
 
1067
    return &xsrc->base;
 
1068
}
 
1069
 
 
1070
static cairo_bool_t
 
1071
pattern_is_supported (cairo_xlib_display_t *display,
 
1072
                      const cairo_pattern_t *pattern)
 
1073
{
 
1074
    if (pattern->type == CAIRO_PATTERN_TYPE_MESH)
 
1075
        return FALSE;
 
1076
 
 
1077
    if (display->buggy_pad_reflect) {
 
1078
        if (pattern->extend == CAIRO_EXTEND_REPEAT || pattern->extend == CAIRO_EXTEND_PAD)
 
1079
            return FALSE;
 
1080
    }
 
1081
 
 
1082
    if (display->buggy_gradients) {
 
1083
        if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
 
1084
            return FALSE;
 
1085
    }
 
1086
 
 
1087
    if (! CAIRO_RENDER_HAS_PICTURE_TRANSFORM (display)) {
 
1088
        if (!_cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL))
 
1089
            return FALSE;
 
1090
    }
 
1091
 
 
1092
    if (! CAIRO_RENDER_HAS_FILTERS (display)) {
 
1093
            /* No filters implies no transforms, so we optimise away BILINEAR */
 
1094
    }
 
1095
 
 
1096
    return TRUE;
 
1097
}
 
1098
cairo_surface_t *
 
1099
_cairo_xlib_source_create_for_pattern (cairo_surface_t *_dst,
 
1100
                                       const cairo_pattern_t *pattern,
 
1101
                                       cairo_bool_t is_mask,
 
1102
                                       const cairo_rectangle_int_t *extents,
 
1103
                                       const cairo_rectangle_int_t *sample,
 
1104
                                       int *src_x, int *src_y)
 
1105
{
 
1106
    cairo_xlib_surface_t *dst = (cairo_xlib_surface_t *)_dst;
 
1107
 
 
1108
    *src_x = *src_y = 0;
 
1109
 
 
1110
    if (pattern == NULL || pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
 
1111
        if (pattern == NULL)
 
1112
            pattern = &_cairo_pattern_white.base;
 
1113
 
 
1114
        return solid_source (dst, &((cairo_solid_pattern_t *)pattern)->color);
 
1115
    }
 
1116
 
 
1117
    if (pattern_is_supported (dst->display, pattern)) {
 
1118
        if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
 
1119
            cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t *)pattern;
 
1120
            if (spattern->surface->type == CAIRO_SURFACE_TYPE_XLIB &&
 
1121
                _cairo_xlib_surface_same_screen (dst,
 
1122
                                                 unwrap_source (spattern)))
 
1123
                return native_source (dst, spattern, is_mask,
 
1124
                                      extents, sample,
 
1125
                                      src_x, src_y);
 
1126
 
 
1127
            if (spattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
 
1128
                return record_source (dst, spattern, is_mask,
 
1129
                                      extents, sample,
 
1130
                                      src_x, src_y);
 
1131
 
 
1132
            return surface_source (dst, spattern, is_mask,
 
1133
                                   extents, sample,
 
1134
                                   src_x, src_y);
 
1135
        }
 
1136
 
 
1137
        if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
 
1138
            pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
 
1139
        {
 
1140
            cairo_gradient_pattern_t *gpattern = (cairo_gradient_pattern_t *)pattern;
 
1141
            return gradient_source (dst, gpattern, is_mask, extents, src_x, src_y);
 
1142
        }
 
1143
    }
 
1144
 
 
1145
    return render_pattern (dst, pattern, is_mask, extents, src_x, src_y);
 
1146
}
 
1147
 
 
1148
#endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */