Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
  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.  *      Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
  38.  *      Chris Wilson <chris@chris-wilson.co.uk>
  39.  */
  40.  
  41. #include "cairoint.h"
  42.  
  43. #include "cairo-boxes-private.h"
  44. #include "cairo-clip-private.h"
  45. #include "cairo-composite-rectangles-private.h"
  46. #include "cairo-error-private.h"
  47. #include "cairo-region-private.h"
  48. #include "cairo-spans-private.h"
  49. #include "cairo-surface-fallback-private.h"
  50.  
  51. typedef struct {
  52.     cairo_surface_t *dst;
  53.     cairo_rectangle_int_t extents;
  54.     cairo_image_surface_t *image;
  55.     cairo_rectangle_int_t image_rect;
  56.     void *image_extra;
  57. } fallback_state_t;
  58.  
  59. /**
  60.  * _fallback_init:
  61.  *
  62.  * Acquire destination image surface needed for an image-based
  63.  * fallback.
  64.  *
  65.  * Return value: %CAIRO_INT_STATUS_NOTHING_TO_DO if the extents are not
  66.  * visible, %CAIRO_STATUS_SUCCESS if some portion is visible and all
  67.  * went well, or some error status otherwise.
  68.  **/
  69. static cairo_int_status_t
  70. _fallback_init (fallback_state_t *state,
  71.                 cairo_surface_t  *dst,
  72.                 int               x,
  73.                 int               y,
  74.                 int               width,
  75.                 int               height)
  76. {
  77.     cairo_status_t status;
  78.  
  79.     state->extents.x = x;
  80.     state->extents.y = y;
  81.     state->extents.width = width;
  82.     state->extents.height = height;
  83.  
  84.     state->dst = dst;
  85.  
  86.     status = _cairo_surface_acquire_dest_image (dst, &state->extents,
  87.                                                 &state->image, &state->image_rect,
  88.                                                 &state->image_extra);
  89.     if (unlikely (status))
  90.         return status;
  91.  
  92.  
  93.     /* XXX: This NULL value tucked away in state->image is a rather
  94.      * ugly interface. Cleaner would be to push the
  95.      * CAIRO_INT_STATUS_NOTHING_TO_DO value down into
  96.      * _cairo_surface_acquire_dest_image and its backend
  97.      * counterparts. */
  98.     assert (state->image != NULL);
  99.  
  100.     return CAIRO_STATUS_SUCCESS;
  101. }
  102.  
  103. static void
  104. _fallback_fini (fallback_state_t *state)
  105. {
  106.     _cairo_surface_release_dest_image (state->dst, &state->extents,
  107.                                        state->image, &state->image_rect,
  108.                                        state->image_extra);
  109. }
  110.  
  111. typedef cairo_status_t
  112. (*cairo_draw_func_t) (void                          *closure,
  113.                       cairo_operator_t               op,
  114.                       const cairo_pattern_t         *src,
  115.                       cairo_surface_t               *dst,
  116.                       int                            dst_x,
  117.                       int                            dst_y,
  118.                       const cairo_rectangle_int_t   *extents,
  119.                       cairo_region_t                *clip_region);
  120.  
  121. static cairo_status_t
  122. _create_composite_mask_pattern (cairo_surface_pattern_t       *mask_pattern,
  123.                                 cairo_clip_t                  *clip,
  124.                                 cairo_draw_func_t              draw_func,
  125.                                 void                          *draw_closure,
  126.                                 cairo_surface_t               *dst,
  127.                                 const cairo_rectangle_int_t   *extents)
  128. {
  129.     cairo_surface_t *mask;
  130.     cairo_region_t *clip_region = NULL, *fallback_region = NULL;
  131.     cairo_status_t status;
  132.     cairo_bool_t clip_surface = FALSE;
  133.  
  134.     if (clip != NULL) {
  135.         status = _cairo_clip_get_region (clip, &clip_region);
  136.         if (unlikely (_cairo_status_is_error (status) ||
  137.                       status == CAIRO_INT_STATUS_NOTHING_TO_DO))
  138.         {
  139.             return status;
  140.         }
  141.  
  142.         clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
  143.     }
  144.  
  145.     /* We need to use solid here, because to use CAIRO_OPERATOR_SOURCE with
  146.      * a mask (as called via _cairo_surface_mask) triggers assertion failures.
  147.      */
  148.     mask = _cairo_surface_create_similar_solid (dst,
  149.                                                 CAIRO_CONTENT_ALPHA,
  150.                                                 extents->width,
  151.                                                 extents->height,
  152.                                                 CAIRO_COLOR_TRANSPARENT,
  153.                                                 TRUE);
  154.     if (unlikely (mask->status))
  155.         return mask->status;
  156.  
  157.     if (clip_region && (extents->x || extents->y)) {
  158.         fallback_region = cairo_region_copy (clip_region);
  159.         status = fallback_region->status;
  160.         if (unlikely (status))
  161.             goto CLEANUP_SURFACE;
  162.  
  163.         cairo_region_translate (fallback_region,
  164.                                 -extents->x,
  165.                                 -extents->y);
  166.         clip_region = fallback_region;
  167.     }
  168.  
  169.     status = draw_func (draw_closure, CAIRO_OPERATOR_ADD,
  170.                         &_cairo_pattern_white.base, mask,
  171.                         extents->x, extents->y,
  172.                         extents,
  173.                         clip_region);
  174.     if (unlikely (status))
  175.         goto CLEANUP_SURFACE;
  176.  
  177.     if (clip_surface)
  178.         status = _cairo_clip_combine_with_surface (clip, mask, extents->x, extents->y);
  179.  
  180.     _cairo_pattern_init_for_surface (mask_pattern, mask);
  181.  
  182.  CLEANUP_SURFACE:
  183.     if (fallback_region)
  184.         cairo_region_destroy (fallback_region);
  185.     cairo_surface_destroy (mask);
  186.  
  187.     return status;
  188. }
  189.  
  190. /* Handles compositing with a clip surface when the operator allows
  191.  * us to combine the clip with the mask
  192.  */
  193. static cairo_status_t
  194. _clip_and_composite_with_mask (cairo_clip_t                  *clip,
  195.                                cairo_operator_t               op,
  196.                                const cairo_pattern_t         *src,
  197.                                cairo_draw_func_t              draw_func,
  198.                                void                          *draw_closure,
  199.                                cairo_surface_t               *dst,
  200.                                const cairo_rectangle_int_t   *extents)
  201. {
  202.     cairo_surface_pattern_t mask_pattern;
  203.     cairo_status_t status;
  204.  
  205.     status = _create_composite_mask_pattern (&mask_pattern,
  206.                                              clip,
  207.                                              draw_func, draw_closure,
  208.                                              dst, extents);
  209.     if (likely (status == CAIRO_STATUS_SUCCESS)) {
  210.         status = _cairo_surface_composite (op,
  211.                                            src, &mask_pattern.base, dst,
  212.                                            extents->x,     extents->y,
  213.                                            0,              0,
  214.                                            extents->x,     extents->y,
  215.                                            extents->width, extents->height,
  216.                                            NULL);
  217.  
  218.         _cairo_pattern_fini (&mask_pattern.base);
  219.     }
  220.  
  221.     return status;
  222. }
  223.  
  224. /* Handles compositing with a clip surface when we have to do the operation
  225.  * in two pieces and combine them together.
  226.  */
  227. static cairo_status_t
  228. _clip_and_composite_combine (cairo_clip_t                  *clip,
  229.                              cairo_operator_t               op,
  230.                              const cairo_pattern_t         *src,
  231.                              cairo_draw_func_t              draw_func,
  232.                              void                          *draw_closure,
  233.                              cairo_surface_t               *dst,
  234.                              const cairo_rectangle_int_t   *extents)
  235. {
  236.     cairo_surface_t *intermediate;
  237.     cairo_surface_pattern_t pattern;
  238.     cairo_surface_pattern_t clip_pattern;
  239.     cairo_surface_t *clip_surface;
  240.     int clip_x, clip_y;
  241.     cairo_status_t status;
  242.  
  243.     /* We'd be better off here creating a surface identical in format
  244.      * to dst, but we have no way of getting that information. Instead
  245.      * we ask the backend to create a similar surface of identical content,
  246.      * in the belief that the backend will do something useful - like use
  247.      * an identical format. For example, the xlib backend will endeavor to
  248.      * use a compatible depth to enable core protocol routines.
  249.      */
  250.     intermediate =
  251.         _cairo_surface_create_similar_scratch (dst, dst->content,
  252.                                                extents->width,
  253.                                                extents->height);
  254.     if (intermediate == NULL) {
  255.         intermediate =
  256.             _cairo_image_surface_create_with_content (dst->content,
  257.                                                       extents->width,
  258.                                                       extents->width);
  259.     }
  260.     if (unlikely (intermediate->status))
  261.         return intermediate->status;
  262.  
  263.     /* Initialize the intermediate surface from the destination surface */
  264.     _cairo_pattern_init_for_surface (&pattern, dst);
  265.     status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
  266.                                        &pattern.base, NULL, intermediate,
  267.                                        extents->x,     extents->y,
  268.                                        0,              0,
  269.                                        0,              0,
  270.                                        extents->width, extents->height,
  271.                                        NULL);
  272.     _cairo_pattern_fini (&pattern.base);
  273.     if (unlikely (status))
  274.         goto CLEANUP_SURFACE;
  275.  
  276.     status = (*draw_func) (draw_closure, op,
  277.                            src, intermediate,
  278.                            extents->x, extents->y,
  279.                            extents,
  280.                            NULL);
  281.     if (unlikely (status))
  282.         goto CLEANUP_SURFACE;
  283.  
  284.     assert (clip->path != NULL);
  285.     clip_surface = _cairo_clip_get_surface (clip, dst, &clip_x, &clip_y);
  286.     if (unlikely (clip_surface->status))
  287.         goto CLEANUP_SURFACE;
  288.  
  289.     _cairo_pattern_init_for_surface (&clip_pattern, clip_surface);
  290.  
  291.     /* Combine that with the clip */
  292.     status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_IN,
  293.                                        &clip_pattern.base, NULL, intermediate,
  294.                                        extents->x - clip_x,
  295.                                        extents->y - clip_y,
  296.                                        0, 0,
  297.                                        0, 0,
  298.                                        extents->width, extents->height,
  299.                                        NULL);
  300.     if (unlikely (status))
  301.         goto CLEANUP_CLIP;
  302.  
  303.     /* Punch the clip out of the destination */
  304.     status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT,
  305.                                        &clip_pattern.base, NULL, dst,
  306.                                        extents->x - clip_x,
  307.                                        extents->y - clip_y,
  308.                                        0, 0,
  309.                                        extents->x, extents->y,
  310.                                        extents->width, extents->height,
  311.                                        NULL);
  312.     if (unlikely (status))
  313.         goto CLEANUP_CLIP;
  314.  
  315.     /* Now add the two results together */
  316.     _cairo_pattern_init_for_surface (&pattern, intermediate);
  317.     status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
  318.                                        &pattern.base, NULL, dst,
  319.                                        0,              0,
  320.                                        0,              0,
  321.                                        extents->x,     extents->y,
  322.                                        extents->width, extents->height,
  323.                                        NULL);
  324.     _cairo_pattern_fini (&pattern.base);
  325.  
  326.  CLEANUP_CLIP:
  327.     _cairo_pattern_fini (&clip_pattern.base);
  328.  CLEANUP_SURFACE:
  329.     cairo_surface_destroy (intermediate);
  330.  
  331.     return status;
  332. }
  333.  
  334. /* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
  335.  * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
  336.  */
  337. static cairo_status_t
  338. _clip_and_composite_source (cairo_clip_t                  *clip,
  339.                             const cairo_pattern_t         *src,
  340.                             cairo_draw_func_t              draw_func,
  341.                             void                          *draw_closure,
  342.                             cairo_surface_t               *dst,
  343.                             const cairo_rectangle_int_t   *extents)
  344. {
  345.     cairo_surface_pattern_t mask_pattern;
  346.     cairo_region_t *clip_region = NULL;
  347.     cairo_status_t status;
  348.  
  349.     if (clip != NULL) {
  350.         status = _cairo_clip_get_region (clip, &clip_region);
  351.         if (unlikely (_cairo_status_is_error (status) ||
  352.                       status == CAIRO_INT_STATUS_NOTHING_TO_DO))
  353.         {
  354.             return status;
  355.         }
  356.     }
  357.  
  358.     /* Create a surface that is mask IN clip */
  359.     status = _create_composite_mask_pattern (&mask_pattern,
  360.                                              clip,
  361.                                              draw_func, draw_closure,
  362.                                              dst, extents);
  363.     if (unlikely (status))
  364.         return status;
  365.  
  366.     /* Compute dest' = dest OUT (mask IN clip) */
  367.     status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT,
  368.                                        &mask_pattern.base, NULL, dst,
  369.                                        0,              0,
  370.                                        0,              0,
  371.                                        extents->x,     extents->y,
  372.                                        extents->width, extents->height,
  373.                                        clip_region);
  374.  
  375.     if (unlikely (status))
  376.         goto CLEANUP_MASK_PATTERN;
  377.  
  378.     /* Now compute (src IN (mask IN clip)) ADD dest' */
  379.     status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
  380.                                        src, &mask_pattern.base, dst,
  381.                                        extents->x,     extents->y,
  382.                                        0,              0,
  383.                                        extents->x,     extents->y,
  384.                                        extents->width, extents->height,
  385.                                        clip_region);
  386.  
  387.  CLEANUP_MASK_PATTERN:
  388.     _cairo_pattern_fini (&mask_pattern.base);
  389.     return status;
  390. }
  391.  
  392. static int
  393. _cairo_rectangle_empty (const cairo_rectangle_int_t *rect)
  394. {
  395.     return rect->width == 0 || rect->height == 0;
  396. }
  397.  
  398. /**
  399.  * _clip_and_composite:
  400.  * @clip: a #cairo_clip_t
  401.  * @op: the operator to draw with
  402.  * @src: source pattern
  403.  * @draw_func: function that can be called to draw with the mask onto a surface.
  404.  * @draw_closure: data to pass to @draw_func.
  405.  * @dst: destination surface
  406.  * @extents: rectangle holding a bounding box for the operation; this
  407.  *           rectangle will be used as the size for the temporary
  408.  *           surface.
  409.  *
  410.  * When there is a surface clip, we typically need to create an intermediate
  411.  * surface. This function handles the logic of creating a temporary surface
  412.  * drawing to it, then compositing the result onto the target surface.
  413.  *
  414.  * @draw_func is to called to draw the mask; it will be called no more
  415.  * than once.
  416.  *
  417.  * Return value: %CAIRO_STATUS_SUCCESS if the drawing succeeded.
  418.  **/
  419. static cairo_status_t
  420. _clip_and_composite (cairo_clip_t                  *clip,
  421.                      cairo_operator_t               op,
  422.                      const cairo_pattern_t         *src,
  423.                      cairo_draw_func_t              draw_func,
  424.                      void                          *draw_closure,
  425.                      cairo_surface_t               *dst,
  426.                      const cairo_rectangle_int_t   *extents)
  427. {
  428.     cairo_status_t status;
  429.  
  430.     if (_cairo_rectangle_empty (extents))
  431.         /* Nothing to do */
  432.         return CAIRO_STATUS_SUCCESS;
  433.  
  434.     if (op == CAIRO_OPERATOR_CLEAR) {
  435.         src = &_cairo_pattern_white.base;
  436.         op = CAIRO_OPERATOR_DEST_OUT;
  437.     }
  438.  
  439.     if (op == CAIRO_OPERATOR_SOURCE) {
  440.         status = _clip_and_composite_source (clip,
  441.                                              src,
  442.                                              draw_func, draw_closure,
  443.                                              dst, extents);
  444.     } else {
  445.         cairo_bool_t clip_surface = FALSE;
  446.         cairo_region_t *clip_region = NULL;
  447.  
  448.         if (clip != NULL) {
  449.             status = _cairo_clip_get_region (clip, &clip_region);
  450.             if (unlikely (_cairo_status_is_error (status) ||
  451.                           status == CAIRO_INT_STATUS_NOTHING_TO_DO))
  452.             {
  453.                 return status;
  454.             }
  455.  
  456.             clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
  457.         }
  458.  
  459.         if (clip_surface) {
  460.             if (_cairo_operator_bounded_by_mask (op)) {
  461.                 status = _clip_and_composite_with_mask (clip, op,
  462.                                                         src,
  463.                                                         draw_func, draw_closure,
  464.                                                         dst, extents);
  465.             } else {
  466.                 status = _clip_and_composite_combine (clip, op,
  467.                                                       src,
  468.                                                       draw_func, draw_closure,
  469.                                                       dst, extents);
  470.             }
  471.         } else {
  472.             status = draw_func (draw_closure, op,
  473.                                 src, dst,
  474.                                 0, 0,
  475.                                 extents,
  476.                                 clip_region);
  477.         }
  478.     }
  479.  
  480.     return status;
  481. }
  482.  
  483. /* Composites a region representing a set of trapezoids.
  484.  */
  485. static cairo_status_t
  486. _composite_trap_region (cairo_clip_t            *clip,
  487.                         const cairo_pattern_t   *src,
  488.                         cairo_operator_t         op,
  489.                         cairo_surface_t         *dst,
  490.                         cairo_region_t          *trap_region,
  491.                         const cairo_rectangle_int_t   *extents)
  492. {
  493.     cairo_status_t status;
  494.     cairo_surface_pattern_t mask_pattern;
  495.     cairo_pattern_t *mask = NULL;
  496.     int mask_x = 0, mask_y =0;
  497.  
  498.     if (clip != NULL) {
  499.         cairo_surface_t *clip_surface = NULL;
  500.         int clip_x, clip_y;
  501.  
  502.         clip_surface = _cairo_clip_get_surface (clip, dst, &clip_x, &clip_y);
  503.         if (unlikely (clip_surface->status))
  504.             return clip_surface->status;
  505.  
  506.         if (op == CAIRO_OPERATOR_CLEAR) {
  507.             src = &_cairo_pattern_white.base;
  508.             op = CAIRO_OPERATOR_DEST_OUT;
  509.         }
  510.  
  511.         _cairo_pattern_init_for_surface (&mask_pattern, clip_surface);
  512.         mask_x = extents->x - clip_x;
  513.         mask_y = extents->y - clip_y;
  514.         mask = &mask_pattern.base;
  515.     }
  516.  
  517.     status = _cairo_surface_composite (op, src, mask, dst,
  518.                                        extents->x, extents->y,
  519.                                        mask_x, mask_y,
  520.                                        extents->x, extents->y,
  521.                                        extents->width, extents->height,
  522.                                        trap_region);
  523.  
  524.     if (mask != NULL)
  525.       _cairo_pattern_fini (mask);
  526.  
  527.     return status;
  528. }
  529.  
  530. typedef struct {
  531.     cairo_traps_t *traps;
  532.     cairo_antialias_t antialias;
  533. } cairo_composite_traps_info_t;
  534.  
  535. static cairo_status_t
  536. _composite_traps_draw_func (void                          *closure,
  537.                             cairo_operator_t               op,
  538.                             const cairo_pattern_t         *src,
  539.                             cairo_surface_t               *dst,
  540.                             int                            dst_x,
  541.                             int                            dst_y,
  542.                             const cairo_rectangle_int_t   *extents,
  543.                             cairo_region_t                *clip_region)
  544. {
  545.     cairo_composite_traps_info_t *info = closure;
  546.     cairo_status_t status;
  547.     cairo_region_t *extents_region = NULL;
  548.  
  549.     if (dst_x != 0 || dst_y != 0)
  550.         _cairo_traps_translate (info->traps, - dst_x, - dst_y);
  551.  
  552.     if (clip_region == NULL &&
  553.         !_cairo_operator_bounded_by_source (op)) {
  554.         extents_region = cairo_region_create_rectangle (extents);
  555.         if (unlikely (extents_region->status))
  556.             return extents_region->status;
  557.         cairo_region_translate (extents_region, -dst_x, -dst_y);
  558.         clip_region = extents_region;
  559.     }
  560.  
  561.     status = _cairo_surface_composite_trapezoids (op,
  562.                                                   src, dst, info->antialias,
  563.                                                   extents->x,         extents->y,
  564.                                                   extents->x - dst_x, extents->y - dst_y,
  565.                                                   extents->width,     extents->height,
  566.                                                   info->traps->traps,
  567.                                                   info->traps->num_traps,
  568.                                                   clip_region);
  569.  
  570.     if (extents_region)
  571.         cairo_region_destroy (extents_region);
  572.  
  573.     return status;
  574. }
  575.  
  576. enum {
  577.     HAS_CLEAR_REGION = 0x1,
  578. };
  579.  
  580. static cairo_status_t
  581. _clip_and_composite_region (const cairo_pattern_t *src,
  582.                             cairo_operator_t op,
  583.                             cairo_surface_t *dst,
  584.                             cairo_region_t *trap_region,
  585.                             cairo_clip_t *clip,
  586.                             cairo_rectangle_int_t *extents)
  587. {
  588.     cairo_region_t clear_region;
  589.     unsigned int has_region = 0;
  590.     cairo_status_t status;
  591.  
  592.     if (! _cairo_operator_bounded_by_mask (op) && clip == NULL) {
  593.         /* If we optimize drawing with an unbounded operator to
  594.          * _cairo_surface_fill_rectangles() or to drawing with a
  595.          * clip region, then we have an additional region to clear.
  596.          */
  597.         _cairo_region_init_rectangle (&clear_region, extents);
  598.         status = cairo_region_subtract (&clear_region, trap_region);
  599.         if (unlikely (status))
  600.             return status;
  601.  
  602.         if (! cairo_region_is_empty (&clear_region))
  603.             has_region |= HAS_CLEAR_REGION;
  604.     }
  605.  
  606.     if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) &&
  607.         clip == NULL)
  608.     {
  609.         const cairo_color_t *color;
  610.  
  611.         if (op == CAIRO_OPERATOR_CLEAR)
  612.             color = CAIRO_COLOR_TRANSPARENT;
  613.         else
  614.             color = &((cairo_solid_pattern_t *)src)->color;
  615.  
  616.         /* Solid rectangles special case */
  617.         status = _cairo_surface_fill_region (dst, op, color, trap_region);
  618.     } else {
  619.         /* For a simple rectangle, we can just use composite(), for more
  620.          * rectangles, we have to set a clip region. The cost of rasterizing
  621.          * trapezoids is pretty high for most backends currently, so it's
  622.          * worthwhile even if a region is needed.
  623.          *
  624.          * If we have a clip surface, we set it as the mask; this only works
  625.          * for bounded operators other than SOURCE; for unbounded operators,
  626.          * clip and mask cannot be interchanged. For SOURCE, the operator
  627.          * as implemented by the backends is different in its handling
  628.          * of the mask then what we want.
  629.          *
  630.          * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
  631.          * more than rectangle and the destination doesn't support clip
  632.          * regions. In that case, we fall through.
  633.          */
  634.         status = _composite_trap_region (clip, src, op, dst,
  635.                                          trap_region, extents);
  636.     }
  637.  
  638.     if (has_region & HAS_CLEAR_REGION) {
  639.         if (status == CAIRO_STATUS_SUCCESS) {
  640.             status = _cairo_surface_fill_region (dst,
  641.                                                  CAIRO_OPERATOR_CLEAR,
  642.                                                  CAIRO_COLOR_TRANSPARENT,
  643.                                                  &clear_region);
  644.         }
  645.         _cairo_region_fini (&clear_region);
  646.     }
  647.  
  648.     return status;
  649. }
  650.  
  651. /* avoid using region code to re-validate boxes */
  652. static cairo_status_t
  653. _fill_rectangles (cairo_surface_t *dst,
  654.                   cairo_operator_t op,
  655.                   const cairo_pattern_t *src,
  656.                   cairo_traps_t *traps,
  657.                   cairo_clip_t *clip)
  658. {
  659.     const cairo_color_t *color;
  660.     cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
  661.     cairo_rectangle_int_t *rects = stack_rects;
  662.     cairo_status_t status;
  663.     int i;
  664.  
  665.     if (! traps->is_rectilinear || ! traps->maybe_region)
  666.         return CAIRO_INT_STATUS_UNSUPPORTED;
  667.  
  668.     /* XXX: convert clip region to geometric boxes? */
  669.     if (clip != NULL)
  670.         return CAIRO_INT_STATUS_UNSUPPORTED;
  671.  
  672.     /* XXX: fallback for the region_subtract() operation */
  673.     if (! _cairo_operator_bounded_by_mask (op))
  674.         return CAIRO_INT_STATUS_UNSUPPORTED;
  675.  
  676.     if (! (src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR))
  677.         return CAIRO_INT_STATUS_UNSUPPORTED;
  678.  
  679.     if (traps->has_intersections) {
  680.         if (traps->is_rectangular) {
  681.             status = _cairo_bentley_ottmann_tessellate_rectangular_traps (traps, CAIRO_FILL_RULE_WINDING);
  682.         } else {
  683.             status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (traps, CAIRO_FILL_RULE_WINDING);
  684.         }
  685.         if (unlikely (status))
  686.             return status;
  687.     }
  688.  
  689.     for (i = 0; i < traps->num_traps; i++) {
  690.         if (! _cairo_fixed_is_integer (traps->traps[i].top)          ||
  691.             ! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
  692.             ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
  693.             ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
  694.         {
  695.             traps->maybe_region = FALSE;
  696.             return CAIRO_INT_STATUS_UNSUPPORTED;
  697.         }
  698.     }
  699.  
  700.     if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
  701.         rects = _cairo_malloc_ab (traps->num_traps,
  702.                                   sizeof (cairo_rectangle_int_t));
  703.         if (unlikely (rects == NULL))
  704.             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  705.     }
  706.  
  707.     for (i = 0; i < traps->num_traps; i++) {
  708.         int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
  709.         int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
  710.         int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
  711.         int y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
  712.  
  713.         rects[i].x = x1;
  714.         rects[i].y = y1;
  715.         rects[i].width = x2 - x1;
  716.         rects[i].height = y2 - y1;
  717.     }
  718.  
  719.     if (op == CAIRO_OPERATOR_CLEAR)
  720.         color = CAIRO_COLOR_TRANSPARENT;
  721.     else
  722.         color = &((cairo_solid_pattern_t *)src)->color;
  723.  
  724.     status =  _cairo_surface_fill_rectangles (dst, op, color, rects, i);
  725.  
  726.     if (rects != stack_rects)
  727.         free (rects);
  728.  
  729.     return status;
  730. }
  731.  
  732. /* fast-path for very common composite of a single rectangle */
  733. static cairo_status_t
  734. _composite_rectangle (cairo_surface_t *dst,
  735.                       cairo_operator_t op,
  736.                       const cairo_pattern_t *src,
  737.                       cairo_traps_t *traps,
  738.                       cairo_clip_t *clip)
  739. {
  740.     cairo_rectangle_int_t rect;
  741.  
  742.     if (clip != NULL)
  743.         return CAIRO_INT_STATUS_UNSUPPORTED;
  744.  
  745.     if (traps->num_traps > 1 || ! traps->is_rectilinear || ! traps->maybe_region)
  746.         return CAIRO_INT_STATUS_UNSUPPORTED;
  747.  
  748.     if (! _cairo_fixed_is_integer (traps->traps[0].top)          ||
  749.         ! _cairo_fixed_is_integer (traps->traps[0].bottom)       ||
  750.         ! _cairo_fixed_is_integer (traps->traps[0].left.p1.x)    ||
  751.         ! _cairo_fixed_is_integer (traps->traps[0].right.p1.x))
  752.     {
  753.         traps->maybe_region = FALSE;
  754.         return CAIRO_INT_STATUS_UNSUPPORTED;
  755.     }
  756.  
  757.     rect.x = _cairo_fixed_integer_part (traps->traps[0].left.p1.x);
  758.     rect.y = _cairo_fixed_integer_part (traps->traps[0].top);
  759.     rect.width  = _cairo_fixed_integer_part (traps->traps[0].right.p1.x) - rect.x;
  760.     rect.height = _cairo_fixed_integer_part (traps->traps[0].bottom) - rect.y;
  761.  
  762.     return _cairo_surface_composite (op, src, NULL, dst,
  763.                                      rect.x, rect.y,
  764.                                      0, 0,
  765.                                      rect.x, rect.y,
  766.                                      rect.width, rect.height,
  767.                                      NULL);
  768. }
  769.  
  770. /* Warning: This call modifies the coordinates of traps */
  771. static cairo_status_t
  772. _clip_and_composite_trapezoids (const cairo_pattern_t *src,
  773.                                 cairo_operator_t op,
  774.                                 cairo_surface_t *dst,
  775.                                 cairo_traps_t *traps,
  776.                                 cairo_antialias_t antialias,
  777.                                 cairo_clip_t *clip,
  778.                                 cairo_rectangle_int_t *extents)
  779. {
  780.     cairo_composite_traps_info_t traps_info;
  781.     cairo_region_t *clip_region = NULL;
  782.     cairo_bool_t clip_surface = FALSE;
  783.     cairo_status_t status;
  784.  
  785.     if (traps->num_traps == 0 && _cairo_operator_bounded_by_mask (op))
  786.         return CAIRO_STATUS_SUCCESS;
  787.  
  788.     if (clip != NULL) {
  789.         status = _cairo_clip_get_region (clip, &clip_region);
  790.         if (unlikely (_cairo_status_is_error (status)))
  791.             return status;
  792.         if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
  793.             return CAIRO_STATUS_SUCCESS;
  794.  
  795.         clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
  796.     }
  797.  
  798.     /* Use a fast path if the trapezoids consist of a simple region,
  799.      * but we can only do this if we do not have a clip surface, or can
  800.      * substitute the mask with the clip.
  801.      */
  802.     if (! clip_surface ||
  803.         (_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE))
  804.     {
  805.         cairo_region_t *trap_region = NULL;
  806.  
  807.         if (_cairo_operator_bounded_by_source (op)) {
  808.             status = _fill_rectangles (dst, op, src, traps, clip);
  809.             if (status != CAIRO_INT_STATUS_UNSUPPORTED)
  810.                 return status;
  811.  
  812.             status = _composite_rectangle (dst, op, src, traps, clip);
  813.             if (status != CAIRO_INT_STATUS_UNSUPPORTED)
  814.                 return status;
  815.         }
  816.  
  817.         status = _cairo_traps_extract_region (traps, &trap_region);
  818.         if (unlikely (_cairo_status_is_error (status)))
  819.             return status;
  820.  
  821.         if (trap_region != NULL) {
  822.             status = cairo_region_intersect_rectangle (trap_region, extents);
  823.             if (unlikely (status)) {
  824.                 cairo_region_destroy (trap_region);
  825.                 return status;
  826.             }
  827.  
  828.             if (clip_region != NULL) {
  829.                 status = cairo_region_intersect (trap_region, clip_region);
  830.                 if (unlikely (status)) {
  831.                     cairo_region_destroy (trap_region);
  832.                     return status;
  833.                 }
  834.             }
  835.  
  836.             if (_cairo_operator_bounded_by_mask (op)) {
  837.                 cairo_rectangle_int_t trap_extents;
  838.  
  839.                 cairo_region_get_extents (trap_region, &trap_extents);
  840.                 if (! _cairo_rectangle_intersect (extents, &trap_extents)) {
  841.                     cairo_region_destroy (trap_region);
  842.                     return CAIRO_STATUS_SUCCESS;
  843.                 }
  844.             }
  845.  
  846.             status = _clip_and_composite_region (src, op, dst,
  847.                                                  trap_region,
  848.                                                  clip_surface ? clip : NULL,
  849.                                                  extents);
  850.             cairo_region_destroy (trap_region);
  851.  
  852.             if (likely (status != CAIRO_INT_STATUS_UNSUPPORTED))
  853.                 return status;
  854.         }
  855.     }
  856.  
  857.     /* No fast path, exclude self-intersections and clip trapezoids. */
  858.     if (traps->has_intersections) {
  859.         if (traps->is_rectangular)
  860.             status = _cairo_bentley_ottmann_tessellate_rectangular_traps (traps, CAIRO_FILL_RULE_WINDING);
  861.         else if (traps->is_rectilinear)
  862.             status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (traps, CAIRO_FILL_RULE_WINDING);
  863.         else
  864.             status = _cairo_bentley_ottmann_tessellate_traps (traps, CAIRO_FILL_RULE_WINDING);
  865.         if (unlikely (status))
  866.             return status;
  867.     }
  868.  
  869.     /* Otherwise render the trapezoids to a mask and composite in the usual
  870.      * fashion.
  871.      */
  872.     traps_info.traps = traps;
  873.     traps_info.antialias = antialias;
  874.  
  875.     return _clip_and_composite (clip, op, src,
  876.                                 _composite_traps_draw_func,
  877.                                 &traps_info, dst, extents);
  878. }
  879.  
  880. cairo_status_t
  881. _cairo_surface_fallback_paint (cairo_surface_t          *surface,
  882.                                cairo_operator_t          op,
  883.                                const cairo_pattern_t    *source,
  884.                                cairo_clip_t             *clip)
  885. {
  886.     cairo_composite_rectangles_t extents;
  887.     cairo_rectangle_int_t rect;
  888.     cairo_clip_path_t *clip_path = clip ? clip->path : NULL;
  889.     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
  890.     cairo_boxes_t  boxes;
  891.     int num_boxes = ARRAY_LENGTH (boxes_stack);
  892.     cairo_status_t status;
  893.     cairo_traps_t traps;
  894.  
  895.     if (!_cairo_surface_get_extents (surface, &rect))
  896.         ASSERT_NOT_REACHED;
  897.  
  898.     status = _cairo_composite_rectangles_init_for_paint (&extents,
  899.                                                          rect.width,
  900.                                                          rect.height,
  901.                                                          op, source,
  902.                                                          clip);
  903.     if (unlikely (status))
  904.         return status;
  905.  
  906.     if (_cairo_clip_contains_extents (clip, &extents))
  907.         clip = NULL;
  908.  
  909.     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
  910.     if (unlikely (status))
  911.         return status;
  912.  
  913.     /* If the clip cannot be reduced to a set of boxes, we will need to
  914.      * use a clipmask. Paint is special as it is the only operation that
  915.      * does not implicitly use a mask, so we may be able to reduce this
  916.      * operation to a fill...
  917.      */
  918.     if (clip != NULL && clip_path->prev == NULL &&
  919.         _cairo_operator_bounded_by_mask (op))
  920.     {
  921.         return _cairo_surface_fill (surface, op, source,
  922.                                     &clip_path->path,
  923.                                     clip_path->fill_rule,
  924.                                     clip_path->tolerance,
  925.                                     clip_path->antialias,
  926.                                     NULL);
  927.     }
  928.  
  929.     /* meh, surface-fallback is dying anyway... */
  930.     _cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes);
  931.     status = _cairo_traps_init_boxes (&traps, &boxes);
  932.     if (unlikely (status))
  933.         goto CLEANUP_BOXES;
  934.  
  935.     status = _clip_and_composite_trapezoids (source, op, surface,
  936.                                              &traps, CAIRO_ANTIALIAS_DEFAULT,
  937.                                              clip,
  938.                                              extents.is_bounded ? &extents.bounded : &extents.unbounded);
  939.     _cairo_traps_fini (&traps);
  940.  
  941. CLEANUP_BOXES:
  942.     if (clip_boxes != boxes_stack)
  943.         free (clip_boxes);
  944.  
  945.     return status;
  946. }
  947.  
  948. static cairo_status_t
  949. _cairo_surface_mask_draw_func (void                        *closure,
  950.                                cairo_operator_t             op,
  951.                                const cairo_pattern_t       *src,
  952.                                cairo_surface_t             *dst,
  953.                                int                          dst_x,
  954.                                int                          dst_y,
  955.                                const cairo_rectangle_int_t *extents,
  956.                                cairo_region_t              *clip_region)
  957. {
  958.     cairo_pattern_t *mask = closure;
  959.     cairo_status_t status;
  960.     cairo_region_t *extents_region = NULL;
  961.  
  962.     if (clip_region == NULL &&
  963.         !_cairo_operator_bounded_by_source (op)) {
  964.         extents_region = cairo_region_create_rectangle (extents);
  965.         if (unlikely (extents_region->status))
  966.             return extents_region->status;
  967.         cairo_region_translate (extents_region, -dst_x, -dst_y);
  968.         clip_region = extents_region;
  969.     }
  970.  
  971.     if (src) {
  972.         status = _cairo_surface_composite (op,
  973.                                            src, mask, dst,
  974.                                            extents->x,         extents->y,
  975.                                            extents->x,         extents->y,
  976.                                            extents->x - dst_x, extents->y - dst_y,
  977.                                            extents->width,     extents->height,
  978.                                            clip_region);
  979.     } else {
  980.         status = _cairo_surface_composite (op,
  981.                                            mask, NULL, dst,
  982.                                            extents->x,         extents->y,
  983.                                            0,                  0, /* unused */
  984.                                            extents->x - dst_x, extents->y - dst_y,
  985.                                            extents->width,     extents->height,
  986.                                            clip_region);
  987.     }
  988.  
  989.     if (extents_region)
  990.         cairo_region_destroy (extents_region);
  991.  
  992.     return status;
  993. }
  994.  
  995. cairo_status_t
  996. _cairo_surface_fallback_mask (cairo_surface_t           *surface,
  997.                               cairo_operator_t           op,
  998.                               const cairo_pattern_t     *source,
  999.                               const cairo_pattern_t     *mask,
  1000.                               cairo_clip_t              *clip)
  1001. {
  1002.     cairo_composite_rectangles_t extents;
  1003.     cairo_rectangle_int_t rect;
  1004.     cairo_status_t status;
  1005.  
  1006.     if (!_cairo_surface_get_extents (surface, &rect))
  1007.         ASSERT_NOT_REACHED;
  1008.  
  1009.     status = _cairo_composite_rectangles_init_for_mask (&extents,
  1010.                                                         rect.width, rect.height,
  1011.                                                         op, source, mask, clip);
  1012.     if (unlikely (status))
  1013.         return status;
  1014.  
  1015.     if (_cairo_clip_contains_extents (clip, &extents))
  1016.         clip = NULL;
  1017.  
  1018.     if (clip != NULL && extents.is_bounded) {
  1019.         status = _cairo_clip_rectangle (clip, &extents.bounded);
  1020.         if (unlikely (status))
  1021.             return status;
  1022.     }
  1023.  
  1024.     return _clip_and_composite (clip, op, source,
  1025.                                 _cairo_surface_mask_draw_func,
  1026.                                 (void *) mask,
  1027.                                 surface,
  1028.                                 extents.is_bounded ? &extents.bounded : &extents.unbounded);
  1029. }
  1030.  
  1031. cairo_status_t
  1032. _cairo_surface_fallback_stroke (cairo_surface_t         *surface,
  1033.                                 cairo_operator_t         op,
  1034.                                 const cairo_pattern_t   *source,
  1035.                                 cairo_path_fixed_t      *path,
  1036.                                 const cairo_stroke_style_t      *stroke_style,
  1037.                                 const cairo_matrix_t            *ctm,
  1038.                                 const cairo_matrix_t            *ctm_inverse,
  1039.                                 double                   tolerance,
  1040.                                 cairo_antialias_t        antialias,
  1041.                                 cairo_clip_t            *clip)
  1042. {
  1043.     cairo_polygon_t polygon;
  1044.     cairo_traps_t traps;
  1045.     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
  1046.     int num_boxes = ARRAY_LENGTH (boxes_stack);
  1047.     cairo_composite_rectangles_t extents;
  1048.     cairo_rectangle_int_t rect;
  1049.     cairo_status_t status;
  1050.  
  1051.     if (!_cairo_surface_get_extents (surface, &rect))
  1052.         ASSERT_NOT_REACHED;
  1053.  
  1054.     status = _cairo_composite_rectangles_init_for_stroke (&extents,
  1055.                                                           rect.width,
  1056.                                                           rect.height,
  1057.                                                           op, source,
  1058.                                                           path, stroke_style, ctm,
  1059.                                                           clip);
  1060.     if (unlikely (status))
  1061.         return status;
  1062.  
  1063.     if (_cairo_clip_contains_extents (clip, &extents))
  1064.         clip = NULL;
  1065.  
  1066.     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
  1067.     if (unlikely (status))
  1068.         return status;
  1069.  
  1070.     _cairo_polygon_init (&polygon);
  1071.     _cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
  1072.  
  1073.     _cairo_traps_init (&traps);
  1074.     _cairo_traps_limit (&traps, clip_boxes, num_boxes);
  1075.  
  1076.     if (path->is_rectilinear) {
  1077.         status = _cairo_path_fixed_stroke_rectilinear_to_traps (path,
  1078.                                                                 stroke_style,
  1079.                                                                 ctm,
  1080.                                                                 &traps);
  1081.         if (likely (status == CAIRO_STATUS_SUCCESS))
  1082.             goto DO_TRAPS;
  1083.  
  1084.         if (_cairo_status_is_error (status))
  1085.             goto CLEANUP;
  1086.     }
  1087.  
  1088.     status = _cairo_path_fixed_stroke_to_polygon (path,
  1089.                                                   stroke_style,
  1090.                                                   ctm, ctm_inverse,
  1091.                                                   tolerance,
  1092.                                                   &polygon);
  1093.     if (unlikely (status))
  1094.         goto CLEANUP;
  1095.  
  1096.     if (polygon.num_edges == 0)
  1097.         goto DO_TRAPS;
  1098.  
  1099.     if (_cairo_operator_bounded_by_mask (op)) {
  1100.         _cairo_box_round_to_rectangle (&polygon.extents, &extents.mask);
  1101.         if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
  1102.             goto CLEANUP;
  1103.     }
  1104.  
  1105.     /* Fall back to trapezoid fills. */
  1106.     status = _cairo_bentley_ottmann_tessellate_polygon (&traps,
  1107.                                                         &polygon,
  1108.                                                         CAIRO_FILL_RULE_WINDING);
  1109.     if (unlikely (status))
  1110.         goto CLEANUP;
  1111.  
  1112.   DO_TRAPS:
  1113.     status = _clip_and_composite_trapezoids (source, op, surface,
  1114.                                              &traps, antialias,
  1115.                                              clip,
  1116.                                              extents.is_bounded ? &extents.bounded : &extents.unbounded);
  1117.   CLEANUP:
  1118.     _cairo_traps_fini (&traps);
  1119.     _cairo_polygon_fini (&polygon);
  1120.     if (clip_boxes != boxes_stack)
  1121.         free (clip_boxes);
  1122.  
  1123.     return status;
  1124. }
  1125.  
  1126. cairo_status_t
  1127. _cairo_surface_fallback_fill (cairo_surface_t           *surface,
  1128.                               cairo_operator_t           op,
  1129.                               const cairo_pattern_t     *source,
  1130.                               cairo_path_fixed_t        *path,
  1131.                               cairo_fill_rule_t          fill_rule,
  1132.                               double                     tolerance,
  1133.                               cairo_antialias_t          antialias,
  1134.                               cairo_clip_t              *clip)
  1135. {
  1136.     cairo_polygon_t polygon;
  1137.     cairo_traps_t traps;
  1138.     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
  1139.     int num_boxes = ARRAY_LENGTH (boxes_stack);
  1140.     cairo_bool_t is_rectilinear;
  1141.     cairo_composite_rectangles_t extents;
  1142.     cairo_rectangle_int_t rect;
  1143.     cairo_status_t status;
  1144.  
  1145.     if (!_cairo_surface_get_extents (surface, &rect))
  1146.         ASSERT_NOT_REACHED;
  1147.  
  1148.     status = _cairo_composite_rectangles_init_for_fill (&extents,
  1149.                                                         rect.width,
  1150.                                                         rect.height,
  1151.                                                         op, source, path,
  1152.                                                         clip);
  1153.     if (unlikely (status))
  1154.         return status;
  1155.  
  1156.     if (_cairo_clip_contains_extents (clip, &extents))
  1157.         clip = NULL;
  1158.  
  1159.     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
  1160.     if (unlikely (status))
  1161.         return status;
  1162.  
  1163.     _cairo_traps_init (&traps);
  1164.     _cairo_traps_limit (&traps, clip_boxes, num_boxes);
  1165.  
  1166.     _cairo_polygon_init (&polygon);
  1167.     _cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
  1168.  
  1169.     if (path->is_empty_fill)
  1170.         goto DO_TRAPS;
  1171.  
  1172.     is_rectilinear = _cairo_path_fixed_is_rectilinear_fill (path);
  1173.     if (is_rectilinear) {
  1174.         status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
  1175.                                                               fill_rule,
  1176.                                                               &traps);
  1177.         if (likely (status == CAIRO_STATUS_SUCCESS))
  1178.             goto DO_TRAPS;
  1179.  
  1180.         if (_cairo_status_is_error (status))
  1181.             goto CLEANUP;
  1182.     }
  1183.  
  1184.     status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
  1185.     if (unlikely (status))
  1186.         goto CLEANUP;
  1187.  
  1188.     if (polygon.num_edges == 0)
  1189.         goto DO_TRAPS;
  1190.  
  1191.     if (_cairo_operator_bounded_by_mask (op)) {
  1192.         _cairo_box_round_to_rectangle (&polygon.extents, &extents.mask);
  1193.         if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
  1194.             goto CLEANUP;
  1195.     }
  1196.  
  1197.     if (is_rectilinear) {
  1198.         status = _cairo_bentley_ottmann_tessellate_rectilinear_polygon (&traps,
  1199.                                                                         &polygon,
  1200.                                                                         fill_rule);
  1201.         if (likely (status == CAIRO_STATUS_SUCCESS))
  1202.             goto DO_TRAPS;
  1203.  
  1204.         if (unlikely (_cairo_status_is_error (status)))
  1205.             goto CLEANUP;
  1206.     }
  1207.  
  1208.     /* Fall back to trapezoid fills. */
  1209.     status = _cairo_bentley_ottmann_tessellate_polygon (&traps,
  1210.                                                         &polygon,
  1211.                                                         fill_rule);
  1212.     if (unlikely (status))
  1213.         goto CLEANUP;
  1214.  
  1215.   DO_TRAPS:
  1216.     status = _clip_and_composite_trapezoids (source, op, surface,
  1217.                                              &traps, antialias,
  1218.                                              clip,
  1219.                                              extents.is_bounded ? &extents.bounded : &extents.unbounded);
  1220.   CLEANUP:
  1221.     _cairo_traps_fini (&traps);
  1222.     _cairo_polygon_fini (&polygon);
  1223.     if (clip_boxes != boxes_stack)
  1224.         free (clip_boxes);
  1225.  
  1226.     return status;
  1227. }
  1228.  
  1229. typedef struct {
  1230.     cairo_scaled_font_t *font;
  1231.     cairo_glyph_t *glyphs;
  1232.     int num_glyphs;
  1233. } cairo_show_glyphs_info_t;
  1234.  
  1235. static cairo_status_t
  1236. _cairo_surface_old_show_glyphs_draw_func (void                          *closure,
  1237.                                           cairo_operator_t               op,
  1238.                                           const cairo_pattern_t         *src,
  1239.                                           cairo_surface_t               *dst,
  1240.                                           int                            dst_x,
  1241.                                           int                            dst_y,
  1242.                                           const cairo_rectangle_int_t   *extents,
  1243.                                           cairo_region_t                *clip_region)
  1244. {
  1245.     cairo_show_glyphs_info_t *glyph_info = closure;
  1246.     cairo_status_t status;
  1247.     cairo_region_t *extents_region = NULL;
  1248.  
  1249.     if (clip_region == NULL &&
  1250.         !_cairo_operator_bounded_by_source (op)) {
  1251.         extents_region = cairo_region_create_rectangle (extents);
  1252.         if (unlikely (extents_region->status))
  1253.             return extents_region->status;
  1254.         cairo_region_translate (extents_region, -dst_x, -dst_y);
  1255.         clip_region = extents_region;
  1256.     }
  1257.  
  1258.     /* Modifying the glyph array is fine because we know that this function
  1259.      * will be called only once, and we've already made a copy of the
  1260.      * glyphs in the wrapper.
  1261.      */
  1262.     if (dst_x != 0 || dst_y != 0) {
  1263.         int i;
  1264.  
  1265.         for (i = 0; i < glyph_info->num_glyphs; ++i) {
  1266.             ((cairo_glyph_t *) glyph_info->glyphs)[i].x -= dst_x;
  1267.             ((cairo_glyph_t *) glyph_info->glyphs)[i].y -= dst_y;
  1268.         }
  1269.     }
  1270.  
  1271.     status = _cairo_surface_old_show_glyphs (glyph_info->font, op, src,
  1272.                                              dst,
  1273.                                              extents->x, extents->y,
  1274.                                              extents->x - dst_x,
  1275.                                              extents->y - dst_y,
  1276.                                              extents->width,
  1277.                                              extents->height,
  1278.                                              glyph_info->glyphs,
  1279.                                              glyph_info->num_glyphs,
  1280.                                              clip_region);
  1281.  
  1282.     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
  1283.         status = _cairo_scaled_font_show_glyphs (glyph_info->font,
  1284.                                                  op,
  1285.                                                  src, dst,
  1286.                                                  extents->x,         extents->y,
  1287.                                                  extents->x - dst_x,
  1288.                                                  extents->y - dst_y,
  1289.                                                  extents->width,     extents->height,
  1290.                                                  glyph_info->glyphs,
  1291.                                                  glyph_info->num_glyphs,
  1292.                                                  clip_region);
  1293.     }
  1294.  
  1295.     if (extents_region)
  1296.         cairo_region_destroy (extents_region);
  1297.  
  1298.     return status;
  1299. }
  1300.  
  1301. cairo_status_t
  1302. _cairo_surface_fallback_show_glyphs (cairo_surface_t            *surface,
  1303.                                      cairo_operator_t            op,
  1304.                                      const cairo_pattern_t      *source,
  1305.                                      cairo_glyph_t              *glyphs,
  1306.                                      int                         num_glyphs,
  1307.                                      cairo_scaled_font_t        *scaled_font,
  1308.                                      cairo_clip_t               *clip)
  1309. {
  1310.     cairo_show_glyphs_info_t glyph_info;
  1311.     cairo_composite_rectangles_t extents;
  1312.     cairo_rectangle_int_t rect;
  1313.     cairo_status_t status;
  1314.  
  1315.     if (!_cairo_surface_get_extents (surface, &rect))
  1316.         ASSERT_NOT_REACHED;
  1317.  
  1318.     status = _cairo_composite_rectangles_init_for_glyphs (&extents,
  1319.                                                           rect.width,
  1320.                                                           rect.height,
  1321.                                                           op, source,
  1322.                                                           scaled_font,
  1323.                                                           glyphs, num_glyphs,
  1324.                                                           clip,
  1325.                                                           NULL);
  1326.     if (unlikely (status))
  1327.         return status;
  1328.  
  1329.     if (_cairo_clip_contains_rectangle (clip, &extents.mask))
  1330.         clip = NULL;
  1331.  
  1332.     if (clip != NULL && extents.is_bounded) {
  1333.         status = _cairo_clip_rectangle (clip, &extents.bounded);
  1334.         if (unlikely (status))
  1335.             return status;
  1336.     }
  1337.  
  1338.     glyph_info.font = scaled_font;
  1339.     glyph_info.glyphs = glyphs;
  1340.     glyph_info.num_glyphs = num_glyphs;
  1341.  
  1342.     return _clip_and_composite (clip, op, source,
  1343.                                 _cairo_surface_old_show_glyphs_draw_func,
  1344.                                 &glyph_info,
  1345.                                 surface,
  1346.                                 extents.is_bounded ? &extents.bounded : &extents.unbounded);
  1347. }
  1348.  
  1349. cairo_surface_t *
  1350. _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
  1351. {
  1352.     cairo_surface_t *snapshot;
  1353.     cairo_status_t status;
  1354.     cairo_format_t format;
  1355.     cairo_surface_pattern_t pattern;
  1356.     cairo_image_surface_t *image;
  1357.     void *image_extra;
  1358.  
  1359.     status = _cairo_surface_acquire_source_image (surface,
  1360.                                                   &image, &image_extra);
  1361.     if (unlikely (status))
  1362.         return _cairo_surface_create_in_error (status);
  1363.  
  1364.     format = image->format;
  1365.     if (format == CAIRO_FORMAT_INVALID) {
  1366.         /* Non-standard images formats can be generated when retrieving
  1367.          * images from unusual xservers, for example.
  1368.          */
  1369.         format = _cairo_format_from_content (image->base.content);
  1370.     }
  1371.     snapshot = cairo_image_surface_create (format,
  1372.                                            image->width,
  1373.                                            image->height);
  1374.     if (cairo_surface_status (snapshot)) {
  1375.         _cairo_surface_release_source_image (surface, image, image_extra);
  1376.         return snapshot;
  1377.     }
  1378.  
  1379.     _cairo_pattern_init_for_surface (&pattern, &image->base);
  1380.     status = _cairo_surface_paint (snapshot,
  1381.                                    CAIRO_OPERATOR_SOURCE,
  1382.                                    &pattern.base,
  1383.                                    NULL);
  1384.     _cairo_pattern_fini (&pattern.base);
  1385.     _cairo_surface_release_source_image (surface, image, image_extra);
  1386.     if (unlikely (status)) {
  1387.         cairo_surface_destroy (snapshot);
  1388.         return _cairo_surface_create_in_error (status);
  1389.     }
  1390.  
  1391.     return snapshot;
  1392. }
  1393.  
  1394. cairo_status_t
  1395. _cairo_surface_fallback_composite (cairo_operator_t              op,
  1396.                                    const cairo_pattern_t        *src,
  1397.                                    const cairo_pattern_t        *mask,
  1398.                                    cairo_surface_t              *dst,
  1399.                                    int                           src_x,
  1400.                                    int                           src_y,
  1401.                                    int                           mask_x,
  1402.                                    int                           mask_y,
  1403.                                    int                           dst_x,
  1404.                                    int                           dst_y,
  1405.                                    unsigned int                  width,
  1406.                                    unsigned int                  height,
  1407.                                    cairo_region_t               *clip_region)
  1408. {
  1409.     fallback_state_t state;
  1410.     cairo_region_t *fallback_region = NULL;
  1411.     cairo_status_t status;
  1412.  
  1413.     status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
  1414.     if (unlikely (status))
  1415.         return status;
  1416.  
  1417.     /* We know this will never fail with the image backend; but
  1418.      * instead of calling into it directly, we call
  1419.      * _cairo_surface_composite so that we get the correct device
  1420.      * offset handling.
  1421.      */
  1422.  
  1423.     if (clip_region != NULL && (state.image_rect.x || state.image_rect.y)) {
  1424.         fallback_region = cairo_region_copy (clip_region);
  1425.         status = fallback_region->status;
  1426.         if (unlikely (status))
  1427.             goto FAIL;
  1428.  
  1429.         cairo_region_translate (fallback_region,
  1430.                                 -state.image_rect.x,
  1431.                                 -state.image_rect.y);
  1432.         clip_region = fallback_region;
  1433.     }
  1434.  
  1435.     status = _cairo_surface_composite (op, src, mask,
  1436.                                        &state.image->base,
  1437.                                        src_x, src_y, mask_x, mask_y,
  1438.                                        dst_x - state.image_rect.x,
  1439.                                        dst_y - state.image_rect.y,
  1440.                                        width, height,
  1441.                                        clip_region);
  1442.   FAIL:
  1443.     if (fallback_region != NULL)
  1444.         cairo_region_destroy (fallback_region);
  1445.     _fallback_fini (&state);
  1446.  
  1447.     return status;
  1448. }
  1449.  
  1450. cairo_status_t
  1451. _cairo_surface_fallback_fill_rectangles (cairo_surface_t         *surface,
  1452.                                          cairo_operator_t         op,
  1453.                                          const cairo_color_t     *color,
  1454.                                          cairo_rectangle_int_t   *rects,
  1455.                                          int                      num_rects)
  1456. {
  1457.     fallback_state_t state;
  1458.     cairo_rectangle_int_t *offset_rects = NULL;
  1459.     cairo_status_t status;
  1460.     int x1, y1, x2, y2;
  1461.     int i;
  1462.  
  1463.     assert (surface->snapshot_of == NULL);
  1464.  
  1465.     if (num_rects <= 0)
  1466.         return CAIRO_STATUS_SUCCESS;
  1467.  
  1468.     /* Compute the bounds of the rectangles, so that we know what area of the
  1469.      * destination surface to fetch
  1470.      */
  1471.     x1 = rects[0].x;
  1472.     y1 = rects[0].y;
  1473.     x2 = rects[0].x + rects[0].width;
  1474.     y2 = rects[0].y + rects[0].height;
  1475.  
  1476.     for (i = 1; i < num_rects; i++) {
  1477.         if (rects[i].x < x1)
  1478.             x1 = rects[i].x;
  1479.         if (rects[i].y < y1)
  1480.             y1 = rects[i].y;
  1481.  
  1482.         if ((int) (rects[i].x + rects[i].width) > x2)
  1483.             x2 = rects[i].x + rects[i].width;
  1484.         if ((int) (rects[i].y + rects[i].height) > y2)
  1485.             y2 = rects[i].y + rects[i].height;
  1486.     }
  1487.  
  1488.     status = _fallback_init (&state, surface, x1, y1, x2 - x1, y2 - y1);
  1489.     if (unlikely (status))
  1490.         return status;
  1491.  
  1492.     /* If the fetched image isn't at 0,0, we need to offset the rectangles */
  1493.  
  1494.     if (state.image_rect.x != 0 || state.image_rect.y != 0) {
  1495.         offset_rects = _cairo_malloc_ab (num_rects, sizeof (cairo_rectangle_int_t));
  1496.         if (unlikely (offset_rects == NULL)) {
  1497.             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1498.             goto DONE;
  1499.         }
  1500.  
  1501.         for (i = 0; i < num_rects; i++) {
  1502.             offset_rects[i].x = rects[i].x - state.image_rect.x;
  1503.             offset_rects[i].y = rects[i].y - state.image_rect.y;
  1504.             offset_rects[i].width = rects[i].width;
  1505.             offset_rects[i].height = rects[i].height;
  1506.         }
  1507.  
  1508.         rects = offset_rects;
  1509.     }
  1510.  
  1511.     status = _cairo_surface_fill_rectangles (&state.image->base,
  1512.                                              op, color,
  1513.                                              rects, num_rects);
  1514.  
  1515.     free (offset_rects);
  1516.  
  1517.  DONE:
  1518.     _fallback_fini (&state);
  1519.  
  1520.     return status;
  1521. }
  1522.  
  1523. cairo_status_t
  1524. _cairo_surface_fallback_composite_trapezoids (cairo_operator_t          op,
  1525.                                               const cairo_pattern_t    *pattern,
  1526.                                               cairo_surface_t          *dst,
  1527.                                               cairo_antialias_t         antialias,
  1528.                                               int                       src_x,
  1529.                                               int                       src_y,
  1530.                                               int                       dst_x,
  1531.                                               int                       dst_y,
  1532.                                               unsigned int              width,
  1533.                                               unsigned int              height,
  1534.                                               cairo_trapezoid_t        *traps,
  1535.                                               int                       num_traps,
  1536.                                               cairo_region_t            *clip_region)
  1537. {
  1538.     fallback_state_t state;
  1539.     cairo_region_t *fallback_region = NULL;
  1540.     cairo_trapezoid_t *offset_traps = NULL;
  1541.     cairo_status_t status;
  1542.  
  1543.     status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
  1544.     if (unlikely (status))
  1545.         return status;
  1546.  
  1547.     /* If the destination image isn't at 0,0, we need to offset the trapezoids */
  1548.  
  1549.     if (state.image_rect.x != 0 || state.image_rect.y != 0) {
  1550.         offset_traps = _cairo_malloc_ab (num_traps, sizeof (cairo_trapezoid_t));
  1551.         if (offset_traps == NULL) {
  1552.             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1553.             goto FAIL;
  1554.         }
  1555.  
  1556.         _cairo_trapezoid_array_translate_and_scale (offset_traps, traps, num_traps,
  1557.                                                     - state.image_rect.x, - state.image_rect.y,
  1558.                                                     1.0, 1.0);
  1559.         traps = offset_traps;
  1560.  
  1561.         /* similarly we need to adjust the region */
  1562.         if (clip_region != NULL) {
  1563.             fallback_region = cairo_region_copy (clip_region);
  1564.             status = fallback_region->status;
  1565.             if (unlikely (status))
  1566.                 goto FAIL;
  1567.  
  1568.             cairo_region_translate (fallback_region,
  1569.                                     -state.image_rect.x,
  1570.                                     -state.image_rect.y);
  1571.             clip_region = fallback_region;
  1572.         }
  1573.     }
  1574.  
  1575.     status = _cairo_surface_composite_trapezoids (op, pattern,
  1576.                                                   &state.image->base,
  1577.                                                   antialias,
  1578.                                                   src_x, src_y,
  1579.                                                   dst_x - state.image_rect.x,
  1580.                                                   dst_y - state.image_rect.y,
  1581.                                                   width, height,
  1582.                                                   traps, num_traps,
  1583.                                                   clip_region);
  1584.  FAIL:
  1585.     if (offset_traps != NULL)
  1586.         free (offset_traps);
  1587.  
  1588.     if (fallback_region != NULL)
  1589.         cairo_region_destroy (fallback_region);
  1590.  
  1591.     _fallback_fini (&state);
  1592.  
  1593.     return status;
  1594. }
  1595.  
  1596. cairo_status_t
  1597. _cairo_surface_fallback_clone_similar (cairo_surface_t  *surface,
  1598.                                        cairo_surface_t  *src,
  1599.                                        int               src_x,
  1600.                                        int               src_y,
  1601.                                        int               width,
  1602.                                        int               height,
  1603.                                        int              *clone_offset_x,
  1604.                                        int              *clone_offset_y,
  1605.                                        cairo_surface_t **clone_out)
  1606. {
  1607.     cairo_surface_t *new_surface;
  1608.     cairo_surface_pattern_t pattern;
  1609.     cairo_status_t status;
  1610.  
  1611.     new_surface = _cairo_surface_create_similar_scratch (surface,
  1612.                                                          src->content,
  1613.                                                          width, height);
  1614.     if (new_surface == NULL)
  1615.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1616.     if (unlikely (new_surface->status))
  1617.         return new_surface->status;
  1618.  
  1619.     /* We have to copy these here, so that the coordinate spaces are correct */
  1620.     new_surface->device_transform = src->device_transform;
  1621.     new_surface->device_transform_inverse = src->device_transform_inverse;
  1622.  
  1623.     _cairo_pattern_init_for_surface (&pattern, src);
  1624.     cairo_matrix_init_translate (&pattern.base.matrix, src_x, src_y);
  1625.     pattern.base.filter = CAIRO_FILTER_NEAREST;
  1626.  
  1627.     status = _cairo_surface_paint (new_surface,
  1628.                                    CAIRO_OPERATOR_SOURCE,
  1629.                                    &pattern.base,
  1630.                                    NULL);
  1631.     _cairo_pattern_fini (&pattern.base);
  1632.  
  1633.     if (unlikely (status)) {
  1634.         cairo_surface_destroy (new_surface);
  1635.         return status;
  1636.     }
  1637.  
  1638.     *clone_offset_x = src_x;
  1639.     *clone_offset_y = src_y;
  1640.     *clone_out = new_surface;
  1641.     return CAIRO_STATUS_SUCCESS;
  1642. }
  1643.