Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.  * Copyright © 2011 Intel Corporation
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it either under the terms of the GNU Lesser General Public
  10.  * License version 2.1 as published by the Free Software Foundation
  11.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  12.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  13.  * notice, a recipient may use your version of this file under either
  14.  * the MPL or the LGPL.
  15.  *
  16.  * You should have received a copy of the LGPL along with this library
  17.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  18.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  19.  * You should have received a copy of the MPL along with this library
  20.  * in the file COPYING-MPL-1.1
  21.  *
  22.  * The contents of this file are subject to the Mozilla Public License
  23.  * Version 1.1 (the "License"); you may not use this file except in
  24.  * compliance with the License. You may obtain a copy of the License at
  25.  * http://www.mozilla.org/MPL/
  26.  *
  27.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  28.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  29.  * the specific language governing rights and limitations.
  30.  *
  31.  * The Original Code is the cairo graphics library.
  32.  *
  33.  * The Initial Developer of the Original Code is University of Southern
  34.  * California.
  35.  *
  36.  * Contributor(s):
  37.  *      Carl D. Worth <cworth@cworth.org>
  38.  *      Behdad Esfahbod <behdad@behdad.org>
  39.  *      Chris Wilson <chris@chris-wilson.co.uk>
  40.  *      Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
  41.  */
  42.  
  43. /* The original X drawing API was very restrictive in what it could handle,
  44.  * pixel-aligned fill/blits are all that map into Cairo's drawing model.
  45.  */
  46.  
  47. #include "cairoint.h"
  48.  
  49. #if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
  50.  
  51. #include "cairo-xlib-private.h"
  52. #include "cairo-xlib-surface-private.h"
  53.  
  54. #include "cairo-boxes-private.h"
  55. #include "cairo-clip-inline.h"
  56. #include "cairo-compositor-private.h"
  57. #include "cairo-image-surface-private.h"
  58. #include "cairo-pattern-private.h"
  59. #include "cairo-region-private.h"
  60. #include "cairo-surface-offset-private.h"
  61.  
  62. /* the low-level interface */
  63.  
  64. static cairo_int_status_t
  65. acquire (void *abstract_dst)
  66. {
  67.     cairo_xlib_surface_t *dst = abstract_dst;
  68.     return _cairo_xlib_display_acquire (dst->base.device, &dst->display);
  69. }
  70.  
  71. static cairo_int_status_t
  72. release (void *abstract_dst)
  73. {
  74.     cairo_xlib_surface_t *dst = abstract_dst;
  75.  
  76.     cairo_device_release (&dst->display->base);
  77.     dst->display = NULL;
  78.  
  79.     return CAIRO_STATUS_SUCCESS;
  80. }
  81.  
  82. struct _fill_box {
  83.     Display *dpy;
  84.     Drawable drawable;
  85.     GC gc;
  86.     //cairo_surface_t *dither = NULL;
  87. };
  88.  
  89. static cairo_bool_t fill_box (cairo_box_t *box, void *closure)
  90. {
  91.     struct _fill_box *data = closure;
  92.     int x = _cairo_fixed_integer_part (box->p1.x);
  93.     int y = _cairo_fixed_integer_part (box->p1.y);
  94.     int width  = _cairo_fixed_integer_part (box->p2.x - box->p1.x);
  95.     int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y);
  96.  
  97.     XFillRectangle (data->dpy, data->drawable, data->gc, x, y, width, height);
  98.     return TRUE;
  99. }
  100.  
  101. static void
  102. _characterize_field (uint32_t mask, int *width, int *shift)
  103. {
  104.     *width = _cairo_popcount (mask);
  105.     /* The final '& 31' is to force a 0 mask to result in 0 shift. */
  106.     *shift = _cairo_popcount ((mask - 1) & ~mask) & 31;
  107. }
  108.  
  109. static uint32_t
  110. color_to_pixel (cairo_xlib_surface_t    *dst,
  111.                 const cairo_color_t     *color)
  112. {
  113.     uint32_t rgba = 0;
  114.     int width, shift;
  115.  
  116.     _characterize_field (dst->a_mask, &width, &shift);
  117.     rgba |= color->alpha_short >> (16 - width) << shift;
  118.  
  119.     _characterize_field (dst->r_mask, &width, &shift);
  120.     rgba |= color->red_short >> (16 - width) << shift;
  121.  
  122.     _characterize_field (dst->g_mask, &width, &shift);
  123.     rgba |= color->green_short >> (16 - width) << shift;
  124.  
  125.     _characterize_field (dst->b_mask, &width, &shift);
  126.     rgba |= color->blue_short >> (16 - width) << shift;
  127.  
  128.     return rgba;
  129. }
  130.  
  131. static cairo_int_status_t
  132. _fill_box_init (struct _fill_box *fb,
  133.                 cairo_xlib_surface_t *dst,
  134.                 const cairo_color_t *color)
  135. {
  136.     cairo_int_status_t status;
  137.  
  138.     status = _cairo_xlib_surface_get_gc (dst->display, dst, &fb->gc);
  139.     if (unlikely (status))
  140.         return status;
  141.  
  142.     fb->dpy = dst->display->display;
  143.     fb->drawable = dst->drawable;
  144.  
  145.     if (dst->visual && dst->visual->class != TrueColor && 0) {
  146. #if 0
  147.         cairo_solid_pattern_t solid;
  148.         cairo_surface_attributes_t attrs;
  149.  
  150.         _cairo_pattern_init_solid (&solid, color);
  151.         status = _cairo_pattern_acquire_surface (&solid.base, &dst->base,
  152.                                                  0, 0,
  153.                                                  ARRAY_LENGTH (dither_pattern[0]),
  154.                                                  ARRAY_LENGTH (dither_pattern),
  155.                                                  CAIRO_PATTERN_ACQUIRE_NONE,
  156.                                                  &dither,
  157.                                                  &attrs);
  158.         if (unlikely (status)) {
  159.             _cairo_xlib_surface_put_gc (dst->display, dst, fb.gc);
  160.             return status;
  161.         }
  162.  
  163.         XSetTSOrigin (fb->dpy, fb->gc,
  164.                       - (dst->base.device_transform.x0 + attrs.x_offset),
  165.                       - (dst->base.device_transform.y0 + attrs.y_offset));
  166.         XSetTile (fb->dpy, fb->gc, ((cairo_xlib_surface_t *) dither)->drawable);
  167. #endif
  168.     } else {
  169.         XGCValues gcv;
  170.  
  171.         gcv.foreground = color_to_pixel (dst, color);
  172.         gcv.fill_style = FillSolid;
  173.  
  174.         XChangeGC (fb->dpy, fb->gc, GCFillStyle | GCForeground, &gcv);
  175.     }
  176.  
  177.     return CAIRO_INT_STATUS_SUCCESS;
  178. }
  179.  
  180. static void
  181. _fill_box_fini (struct _fill_box *fb,
  182.                 cairo_xlib_surface_t *dst)
  183. {
  184.     _cairo_xlib_surface_put_gc (dst->display, dst, fb->gc);
  185.     //cairo_surface_destroy (fb->dither);
  186. }
  187.  
  188. cairo_int_status_t
  189. _cairo_xlib_core_fill_boxes (cairo_xlib_surface_t    *dst,
  190.                              const cairo_color_t     *color,
  191.                              cairo_boxes_t          *boxes)
  192. {
  193.     cairo_int_status_t status;
  194.     struct _fill_box fb;
  195.  
  196.     status = _fill_box_init (&fb, dst, color);
  197.     if (unlikely (status))
  198.         return status;
  199.  
  200.     _cairo_boxes_for_each_box (boxes, fill_box, &fb);
  201.  
  202.     _fill_box_fini (&fb, dst);
  203.     return CAIRO_STATUS_SUCCESS;
  204. }
  205.  
  206. cairo_int_status_t
  207. _cairo_xlib_core_fill_rectangles (cairo_xlib_surface_t    *dst,
  208.                                   const cairo_color_t     *color,
  209.                                   int num_rects,
  210.                                   cairo_rectangle_int_t *rects)
  211. {
  212.     cairo_int_status_t status;
  213.     struct _fill_box fb;
  214.     int i;
  215.  
  216.     status = _fill_box_init (&fb, dst, color);
  217.     if (unlikely (status))
  218.         return status;
  219.  
  220.     for (i = 0; i < num_rects; i++)
  221.         XFillRectangle (fb.dpy, fb.drawable, fb.gc,
  222.                         rects[i].x, rects[i].y,
  223.                         rects[i].width, rects[i].height);
  224.  
  225.     _fill_box_fini (&fb, dst);
  226.     return CAIRO_STATUS_SUCCESS;
  227. }
  228.  
  229. struct _fallback_box {
  230.     cairo_xlib_surface_t        *dst;
  231.     cairo_format_t               format;
  232.     const cairo_pattern_t       *pattern;
  233. };
  234.  
  235. static cairo_bool_t fallback_box (cairo_box_t *box, void *closure)
  236. {
  237.     struct _fallback_box *data = closure;
  238.     int x = _cairo_fixed_integer_part (box->p1.x);
  239.     int y = _cairo_fixed_integer_part (box->p1.y);
  240.     int width  = _cairo_fixed_integer_part (box->p2.x - box->p1.x);
  241.     int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y);
  242.     cairo_surface_t *image;
  243.     cairo_status_t status;
  244.  
  245.     /* XXX for EXTEND_NONE and if the box is wholly outside we can just fill */
  246.  
  247.     image = cairo_surface_create_similar_image (&data->dst->base, data->format,
  248.                                                 width, height);
  249.     status = _cairo_surface_offset_paint (image, x, y,
  250.                                           CAIRO_OPERATOR_SOURCE,
  251.                                           data->pattern, NULL);
  252.     if (status == CAIRO_STATUS_SUCCESS) {
  253.         status = _cairo_xlib_surface_draw_image (data->dst,
  254.                                                  (cairo_image_surface_t *)image,
  255.                                                  0, 0,
  256.                                                  width, height,
  257.                                                  x, y);
  258.     }
  259.     cairo_surface_destroy (image);
  260.  
  261.     return status == CAIRO_STATUS_SUCCESS;
  262. }
  263.  
  264. static cairo_int_status_t
  265. fallback_boxes (cairo_xlib_surface_t    *dst,
  266.                 const cairo_pattern_t   *pattern,
  267.                 cairo_boxes_t           *boxes)
  268. {
  269.     struct _fallback_box fb;
  270.  
  271.     /* XXX create_similar_image using pixman_format? */
  272.     switch (dst->depth) {
  273.     case 8: fb.format = CAIRO_FORMAT_A8; break;
  274.     case 16: fb.format = CAIRO_FORMAT_RGB16_565; break;
  275.     case 24: fb.format = CAIRO_FORMAT_RGB24; break;
  276.     case 30: fb.format = CAIRO_FORMAT_RGB30; break;
  277.     case 32: fb.format = CAIRO_FORMAT_ARGB32; break;
  278.     default: return CAIRO_INT_STATUS_UNSUPPORTED;
  279.     }
  280.  
  281.     fb.dst = dst;
  282.     fb.pattern = pattern;
  283.  
  284.     if (! _cairo_boxes_for_each_box (boxes, fallback_box, &fb))
  285.         return CAIRO_INT_STATUS_UNSUPPORTED;
  286.  
  287.     return CAIRO_STATUS_SUCCESS;
  288. }
  289.  
  290. static cairo_int_status_t
  291. render_boxes (cairo_xlib_surface_t      *dst,
  292.               const cairo_pattern_t     *pattern,
  293.               cairo_boxes_t             *boxes)
  294. {
  295.     double pad;
  296.  
  297.     if (_cairo_pattern_analyze_filter (pattern, &pad) != CAIRO_FILTER_NEAREST)
  298.         return fallback_boxes (dst, pattern, boxes);
  299.  
  300.     switch (pattern->extend) {
  301.     default:
  302.     case CAIRO_EXTEND_NONE:
  303.     case CAIRO_EXTEND_REFLECT:
  304.     case CAIRO_EXTEND_PAD:
  305.         return fallback_boxes (dst, pattern, boxes);
  306.  
  307.     case CAIRO_EXTEND_REPEAT: /* XXX Use tiling */
  308.         return fallback_boxes (dst, pattern, boxes);
  309.     }
  310. }
  311.  
  312. /* the mid-level: converts boxes into drawing operations */
  313.  
  314. struct _box_data {
  315.     Display *dpy;
  316.     cairo_xlib_surface_t *dst;
  317.     cairo_surface_t *src;
  318.     GC gc;
  319.     int tx, ty;
  320.     int width, height;
  321. };
  322.  
  323. static cairo_bool_t source_contains_box (cairo_box_t *box, void *closure)
  324. {
  325.     struct _box_data *data = closure;
  326.  
  327.     /* The box is pixel-aligned so the truncation is safe. */
  328.     return
  329.         _cairo_fixed_integer_part (box->p1.x) + data->tx >= 0 &&
  330.         _cairo_fixed_integer_part (box->p1.y) + data->ty >= 0 &&
  331.         _cairo_fixed_integer_part (box->p2.x) + data->tx <= data->width &&
  332.         _cairo_fixed_integer_part (box->p2.y) + data->ty <= data->height;
  333. }
  334.  
  335. static cairo_bool_t image_upload_box (cairo_box_t *box, void *closure)
  336. {
  337.     const struct _box_data *iub = closure;
  338.     int x = _cairo_fixed_integer_part (box->p1.x);
  339.     int y = _cairo_fixed_integer_part (box->p1.y);
  340.     int width  = _cairo_fixed_integer_part (box->p2.x - box->p1.x);
  341.     int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y);
  342.  
  343.     return _cairo_xlib_surface_draw_image (iub->dst,
  344.                                            (cairo_image_surface_t *)iub->src,
  345.                                            x + iub->tx, y + iub->ty,
  346.                                            width, height,
  347.                                            x, y) == CAIRO_STATUS_SUCCESS;
  348. }
  349.  
  350. static cairo_bool_t
  351. surface_matches_image_format (cairo_xlib_surface_t *surface,
  352.                               cairo_image_surface_t *image)
  353. {
  354.     cairo_format_masks_t format;
  355.  
  356.     return (_pixman_format_to_masks (image->pixman_format, &format) &&
  357.             (format.alpha_mask == surface->a_mask || surface->a_mask == 0) &&
  358.             (format.red_mask   == surface->r_mask || surface->r_mask == 0) &&
  359.             (format.green_mask == surface->g_mask || surface->g_mask == 0) &&
  360.             (format.blue_mask  == surface->b_mask || surface->b_mask == 0));
  361. }
  362.  
  363. static cairo_status_t
  364. upload_image_inplace (cairo_xlib_surface_t *dst,
  365.                       const cairo_pattern_t *source,
  366.                       cairo_boxes_t *boxes)
  367. {
  368.     const cairo_surface_pattern_t *pattern;
  369.     struct _box_data iub;
  370.     cairo_image_surface_t *image;
  371.  
  372.     if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
  373.         return CAIRO_INT_STATUS_UNSUPPORTED;
  374.  
  375.     pattern = (const cairo_surface_pattern_t *) source;
  376.     if (pattern->surface->type != CAIRO_SURFACE_TYPE_IMAGE)
  377.         return CAIRO_INT_STATUS_UNSUPPORTED;
  378.  
  379.     image = (cairo_image_surface_t *) pattern->surface;
  380.     if (image->format == CAIRO_FORMAT_INVALID)
  381.         return CAIRO_INT_STATUS_UNSUPPORTED;
  382.  
  383.     if (image->depth != dst->depth)
  384.         return CAIRO_INT_STATUS_UNSUPPORTED;
  385.  
  386.     if (! surface_matches_image_format (dst, image))
  387.         return CAIRO_INT_STATUS_UNSUPPORTED;
  388.  
  389.     /* XXX subsurface */
  390.  
  391.     if (! _cairo_matrix_is_integer_translation (&source->matrix,
  392.                                                 &iub.tx, &iub.ty))
  393.         return CAIRO_INT_STATUS_UNSUPPORTED;
  394.  
  395.     iub.dst = dst;
  396.     iub.src = &image->base;
  397.     iub.width  = image->width;
  398.     iub.height = image->height;
  399.  
  400.     /* First check that the data is entirely within the image */
  401.     if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &iub))
  402.         return CAIRO_INT_STATUS_UNSUPPORTED;
  403.  
  404.     if (! _cairo_boxes_for_each_box (boxes, image_upload_box, &iub))
  405.         return CAIRO_INT_STATUS_UNSUPPORTED;
  406.  
  407.     return CAIRO_STATUS_SUCCESS;
  408. }
  409.  
  410. static cairo_bool_t copy_box (cairo_box_t *box, void *closure)
  411. {
  412.     const struct _box_data *cb = closure;
  413.     int x = _cairo_fixed_integer_part (box->p1.x);
  414.     int y = _cairo_fixed_integer_part (box->p1.y);
  415.     int width  = _cairo_fixed_integer_part (box->p2.x - box->p1.x);
  416.     int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y);
  417.  
  418.     XCopyArea (cb->dpy,
  419.                ((cairo_xlib_surface_t *)cb->src)->drawable,
  420.                cb->dst->drawable,
  421.                cb->gc,
  422.                x + cb->tx, y + cb->ty,
  423.                width, height,
  424.                x, y);
  425.     return TRUE;
  426. }
  427.  
  428. static cairo_status_t
  429. copy_boxes (cairo_xlib_surface_t *dst,
  430.             const cairo_pattern_t *source,
  431.             cairo_boxes_t *boxes)
  432. {
  433.     const cairo_surface_pattern_t *pattern;
  434.     struct _box_data cb;
  435.     cairo_xlib_surface_t *src;
  436.     cairo_status_t status;
  437.  
  438.     if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
  439.         return CAIRO_INT_STATUS_UNSUPPORTED;
  440.  
  441.     /* XXX subsurface */
  442.  
  443.     pattern = (const cairo_surface_pattern_t *) source;
  444.     if (pattern->surface->backend->type != CAIRO_SURFACE_TYPE_XLIB)
  445.         return CAIRO_INT_STATUS_UNSUPPORTED;
  446.  
  447.     src = (cairo_xlib_surface_t *) pattern->surface;
  448.     if (src->depth != dst->depth)
  449.         return CAIRO_INT_STATUS_UNSUPPORTED;
  450.  
  451.     /* We can only have a single control for subwindow_mode on the
  452.      * GC. If we have a Window destination, we need to set ClipByChildren,
  453.      * but if we have a Window source, we need IncludeInferiors. If we have
  454.      * both a Window destination and source, we must fallback. There is
  455.      * no convenient way to detect if a drawable is a Pixmap or Window,
  456.      * therefore we can only rely on those surfaces that we created
  457.      * ourselves to be Pixmaps, and treat everything else as a potential
  458.      * Window.
  459.      */
  460.     if (! src->owns_pixmap && ! dst->owns_pixmap)
  461.         return CAIRO_INT_STATUS_UNSUPPORTED;
  462.  
  463.     if (! _cairo_xlib_surface_same_screen (dst, src))
  464.         return CAIRO_INT_STATUS_UNSUPPORTED;
  465.  
  466.     if (! _cairo_matrix_is_integer_translation (&source->matrix,
  467.                                                 &cb.tx, &cb.ty))
  468.         return CAIRO_INT_STATUS_UNSUPPORTED;
  469.  
  470.     cb.dpy = dst->display->display;
  471.     cb.dst = dst;
  472.     cb.src = &src->base;
  473.     cb.width  = src->width;
  474.     cb.height = src->height;
  475.  
  476.     /* First check that the data is entirely within the image */
  477.     if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &cb))
  478.         return CAIRO_INT_STATUS_UNSUPPORTED;
  479.  
  480.     status = _cairo_xlib_surface_get_gc (dst->display, dst, &cb.gc);
  481.     if (unlikely (status))
  482.         return status;
  483.  
  484.     if (! src->owns_pixmap) {
  485.         XGCValues gcv;
  486.  
  487.         gcv.subwindow_mode = IncludeInferiors;
  488.         XChangeGC (dst->display->display, cb.gc, GCSubwindowMode, &gcv);
  489.     }
  490.  
  491.     status = CAIRO_STATUS_SUCCESS;
  492.     if (! _cairo_boxes_for_each_box (boxes, copy_box, &cb))
  493.         status = CAIRO_INT_STATUS_UNSUPPORTED;
  494.  
  495.     if (! src->owns_pixmap) {
  496.         XGCValues gcv;
  497.  
  498.         gcv.subwindow_mode = ClipByChildren;
  499.         XChangeGC (dst->display->display, cb.gc, GCSubwindowMode, &gcv);
  500.     }
  501.  
  502.     _cairo_xlib_surface_put_gc (dst->display, dst, cb.gc);
  503.  
  504.     return status;
  505. }
  506.  
  507. static cairo_status_t
  508. draw_boxes (cairo_composite_rectangles_t *extents,
  509.             cairo_boxes_t *boxes)
  510. {
  511.     cairo_xlib_surface_t *dst = (cairo_xlib_surface_t *)extents->surface;
  512.     cairo_operator_t op = extents->op;
  513.     const cairo_pattern_t *src = &extents->source_pattern.base;
  514.     cairo_int_status_t status;
  515.  
  516.     if (boxes->num_boxes == 0 && extents->is_bounded)
  517.         return CAIRO_STATUS_SUCCESS;
  518.  
  519.     if (! boxes->is_pixel_aligned)
  520.         return CAIRO_INT_STATUS_UNSUPPORTED;
  521.  
  522.     if (op == CAIRO_OPERATOR_CLEAR)
  523.         op = CAIRO_OPERATOR_SOURCE;
  524.  
  525.     if (op == CAIRO_OPERATOR_OVER &&
  526.         _cairo_pattern_is_opaque (src, &extents->bounded))
  527.         op = CAIRO_OPERATOR_SOURCE;
  528.  
  529.     if (dst->base.is_clear && op == CAIRO_OPERATOR_OVER)
  530.         op = CAIRO_OPERATOR_SOURCE;
  531.  
  532.     if (op != CAIRO_OPERATOR_SOURCE)
  533.         return CAIRO_INT_STATUS_UNSUPPORTED;
  534.  
  535.     status = acquire (dst);
  536.     if (unlikely (status))
  537.         return status;
  538.  
  539.     if (src->type == CAIRO_PATTERN_TYPE_SOLID) {
  540.         status = _cairo_xlib_core_fill_boxes
  541.             (dst, &((cairo_solid_pattern_t *) src)->color, boxes);
  542.     } else {
  543.         status = upload_image_inplace (dst, src, boxes);
  544.         if (status == CAIRO_INT_STATUS_UNSUPPORTED)
  545.             status = copy_boxes (dst, src, boxes);
  546.         if (status == CAIRO_INT_STATUS_UNSUPPORTED)
  547.             status = render_boxes (dst, src, boxes);
  548.     }
  549.  
  550.     release (dst);
  551.  
  552.     return status;
  553. }
  554.  
  555. /* high-level compositor interface */
  556.  
  557. static cairo_int_status_t
  558. _cairo_xlib_core_compositor_paint (const cairo_compositor_t     *compositor,
  559.                                    cairo_composite_rectangles_t *extents)
  560. {
  561.     cairo_int_status_t status;
  562.  
  563.     status = CAIRO_INT_STATUS_UNSUPPORTED;
  564.     if (_cairo_clip_is_region (extents->clip)) {
  565.         cairo_boxes_t boxes;
  566.  
  567.          _cairo_clip_steal_boxes (extents->clip, &boxes);
  568.          status = draw_boxes (extents, &boxes);
  569.          _cairo_clip_unsteal_boxes (extents->clip, &boxes);
  570.     }
  571.  
  572.     return status;
  573. }
  574.  
  575. static cairo_int_status_t
  576. _cairo_xlib_core_compositor_stroke (const cairo_compositor_t    *compositor,
  577.                                     cairo_composite_rectangles_t *extents,
  578.                                     const cairo_path_fixed_t    *path,
  579.                                     const cairo_stroke_style_t  *style,
  580.                                     const cairo_matrix_t        *ctm,
  581.                                     const cairo_matrix_t        *ctm_inverse,
  582.                                     double                       tolerance,
  583.                                     cairo_antialias_t            antialias)
  584. {
  585.     cairo_int_status_t status;
  586.  
  587.     status = CAIRO_INT_STATUS_UNSUPPORTED;
  588.     if (extents->clip->path == NULL &&
  589.         _cairo_path_fixed_stroke_is_rectilinear (path)) {
  590.         cairo_boxes_t boxes;
  591.  
  592.         _cairo_boxes_init_with_clip (&boxes, extents->clip);
  593.         status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
  594.                                                                 style,
  595.                                                                 ctm,
  596.                                                                 antialias,
  597.                                                                 &boxes);
  598.         if (likely (status == CAIRO_INT_STATUS_SUCCESS))
  599.             status = draw_boxes (extents, &boxes);
  600.         _cairo_boxes_fini (&boxes);
  601.     }
  602.  
  603.     return status;
  604. }
  605.  
  606. static cairo_int_status_t
  607. _cairo_xlib_core_compositor_fill (const cairo_compositor_t      *compositor,
  608.                                   cairo_composite_rectangles_t  *extents,
  609.                                   const cairo_path_fixed_t      *path,
  610.                                   cairo_fill_rule_t              fill_rule,
  611.                                   double                         tolerance,
  612.                                   cairo_antialias_t              antialias)
  613. {
  614.     cairo_int_status_t status;
  615.  
  616.     status = CAIRO_INT_STATUS_UNSUPPORTED;
  617.     if (extents->clip->path == NULL &&
  618.         _cairo_path_fixed_fill_is_rectilinear (path)) {
  619.         cairo_boxes_t boxes;
  620.  
  621.         _cairo_boxes_init_with_clip (&boxes, extents->clip);
  622.         status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
  623.                                                               fill_rule,
  624.                                                               antialias,
  625.                                                               &boxes);
  626.         if (likely (status == CAIRO_INT_STATUS_SUCCESS))
  627.             status = draw_boxes (extents, &boxes);
  628.         _cairo_boxes_fini (&boxes);
  629.     }
  630.  
  631.     return status;
  632. }
  633.  
  634. const cairo_compositor_t *
  635. _cairo_xlib_core_compositor_get (void)
  636. {
  637.     static cairo_compositor_t compositor;
  638.  
  639.     if (compositor.delegate == NULL) {
  640.         compositor.delegate = _cairo_xlib_fallback_compositor_get ();
  641.  
  642.         compositor.paint = _cairo_xlib_core_compositor_paint;
  643.         compositor.mask  = NULL;
  644.         compositor.fill  = _cairo_xlib_core_compositor_fill;
  645.         compositor.stroke = _cairo_xlib_core_compositor_stroke;
  646.         compositor.glyphs = NULL; /* XXX PolyGlyph? */
  647.     }
  648.  
  649.     return &compositor;
  650. }
  651.  
  652. #endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */
  653.