Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
  2. /*
  3.  * Copyright © 2002 Keith Packard
  4.  * Copyright © 2007 Red Hat, Inc.
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it either under the terms of the GNU Lesser General Public
  8.  * License version 2.1 as published by the Free Software Foundation
  9.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  10.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  11.  * notice, a recipient may use your version of this file under either
  12.  * the MPL or the LGPL.
  13.  *
  14.  * You should have received a copy of the LGPL along with this library
  15.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  17.  * You should have received a copy of the MPL along with this library
  18.  * in the file COPYING-MPL-1.1
  19.  *
  20.  * The contents of this file are subject to the Mozilla Public License
  21.  * Version 1.1 (the "License"); you may not use this file except in
  22.  * compliance with the License. You may obtain a copy of the License at
  23.  * http://www.mozilla.org/MPL/
  24.  *
  25.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  26.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  27.  * the specific language governing rights and limitations.
  28.  *
  29.  * The Original Code is the cairo graphics library.
  30.  *
  31.  * The Initial Developer of the Original Code is Keith Packard
  32.  *
  33.  * Contributor(s):
  34.  *      Keith R. Packard <keithp@keithp.com>
  35.  *      Carl D. Worth <cworth@cworth.org>
  36.  *
  37.  * 2002-07-15: Converted from XRenderCompositeDoublePoly to #cairo_trap_t. Carl D. Worth
  38.  */
  39.  
  40. #include "cairoint.h"
  41.  
  42. #include "cairo-box-inline.h"
  43. #include "cairo-boxes-private.h"
  44. #include "cairo-error-private.h"
  45. #include "cairo-region-private.h"
  46. #include "cairo-slope-private.h"
  47. #include "cairo-traps-private.h"
  48. #include "cairo-spans-private.h"
  49.  
  50. /* private functions */
  51.  
  52. void
  53. _cairo_traps_init (cairo_traps_t *traps)
  54. {
  55.     VG (VALGRIND_MAKE_MEM_UNDEFINED (traps, sizeof (cairo_traps_t)));
  56.  
  57.     traps->status = CAIRO_STATUS_SUCCESS;
  58.  
  59.     traps->maybe_region = 1;
  60.     traps->is_rectilinear = 0;
  61.     traps->is_rectangular = 0;
  62.  
  63.     traps->num_traps = 0;
  64.  
  65.     traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
  66.     traps->traps = traps->traps_embedded;
  67.  
  68.     traps->num_limits = 0;
  69.     traps->has_intersections = FALSE;
  70. }
  71.  
  72. void
  73. _cairo_traps_limit (cairo_traps_t       *traps,
  74.                     const cairo_box_t   *limits,
  75.                     int                  num_limits)
  76. {
  77.     int i;
  78.  
  79.     traps->limits = limits;
  80.     traps->num_limits = num_limits;
  81.  
  82.     traps->bounds = limits[0];
  83.     for (i = 1; i < num_limits; i++)
  84.         _cairo_box_add_box (&traps->bounds, &limits[i]);
  85. }
  86.  
  87. void
  88. _cairo_traps_init_with_clip (cairo_traps_t *traps,
  89.                              const cairo_clip_t *clip)
  90. {
  91.     _cairo_traps_init (traps);
  92.     if (clip)
  93.         _cairo_traps_limit (traps, clip->boxes, clip->num_boxes);
  94. }
  95.  
  96. void
  97. _cairo_traps_clear (cairo_traps_t *traps)
  98. {
  99.     traps->status = CAIRO_STATUS_SUCCESS;
  100.  
  101.     traps->maybe_region = 1;
  102.     traps->is_rectilinear = 0;
  103.     traps->is_rectangular = 0;
  104.  
  105.     traps->num_traps = 0;
  106.     traps->has_intersections = FALSE;
  107. }
  108.  
  109. void
  110. _cairo_traps_fini (cairo_traps_t *traps)
  111. {
  112.     if (traps->traps != traps->traps_embedded)
  113.         free (traps->traps);
  114.  
  115.     VG (VALGRIND_MAKE_MEM_NOACCESS (traps, sizeof (cairo_traps_t)));
  116. }
  117.  
  118. /* make room for at least one more trap */
  119. static cairo_bool_t
  120. _cairo_traps_grow (cairo_traps_t *traps)
  121. {
  122.     cairo_trapezoid_t *new_traps;
  123.     int new_size = 4 * traps->traps_size;
  124.  
  125.     if (CAIRO_INJECT_FAULT ()) {
  126.         traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  127.         return FALSE;
  128.     }
  129.  
  130.     if (traps->traps == traps->traps_embedded) {
  131.         new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
  132.         if (new_traps != NULL)
  133.             memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
  134.     } else {
  135.         new_traps = _cairo_realloc_ab (traps->traps,
  136.                                        new_size, sizeof (cairo_trapezoid_t));
  137.     }
  138.  
  139.     if (unlikely (new_traps == NULL)) {
  140.         traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  141.         return FALSE;
  142.     }
  143.  
  144.     traps->traps = new_traps;
  145.     traps->traps_size = new_size;
  146.     return TRUE;
  147. }
  148.  
  149. void
  150. _cairo_traps_add_trap (cairo_traps_t *traps,
  151.                        cairo_fixed_t top, cairo_fixed_t bottom,
  152.                        cairo_line_t *left, cairo_line_t *right)
  153. {
  154.     cairo_trapezoid_t *trap;
  155.  
  156.     if (unlikely (traps->num_traps == traps->traps_size)) {
  157.         if (unlikely (! _cairo_traps_grow (traps)))
  158.             return;
  159.     }
  160.  
  161.     trap = &traps->traps[traps->num_traps++];
  162.     trap->top = top;
  163.     trap->bottom = bottom;
  164.     trap->left = *left;
  165.     trap->right = *right;
  166. }
  167.  
  168. static void
  169. _cairo_traps_add_clipped_trap (cairo_traps_t *traps,
  170.                                cairo_fixed_t _top, cairo_fixed_t _bottom,
  171.                                cairo_line_t *_left, cairo_line_t *_right)
  172. {
  173.     /* Note: With the goofy trapezoid specification, (where an
  174.      * arbitrary two points on the lines can specified for the left
  175.      * and right edges), these limit checks would not work in
  176.      * general. For example, one can imagine a trapezoid entirely
  177.      * within the limits, but with two points used to specify the left
  178.      * edge entirely to the right of the limits.  Fortunately, for our
  179.      * purposes, cairo will never generate such a crazy
  180.      * trapezoid. Instead, cairo always uses for its points the
  181.      * extreme positions of the edge that are visible on at least some
  182.      * trapezoid. With this constraint, it's impossible for both
  183.      * points to be outside the limits while the relevant edge is
  184.      * entirely inside the limits.
  185.      */
  186.     if (traps->num_limits) {
  187.         const cairo_box_t *b = &traps->bounds;
  188.         cairo_fixed_t top = _top, bottom = _bottom;
  189.         cairo_line_t left = *_left, right = *_right;
  190.  
  191.         /* Trivially reject if trapezoid is entirely to the right or
  192.          * to the left of the limits. */
  193.         if (left.p1.x >= b->p2.x && left.p2.x >= b->p2.x)
  194.             return;
  195.  
  196.         if (right.p1.x <= b->p1.x && right.p2.x <= b->p1.x)
  197.             return;
  198.  
  199.         /* And reject if the trapezoid is entirely above or below */
  200.         if (top >= b->p2.y || bottom <= b->p1.y)
  201.             return;
  202.  
  203.         /* Otherwise, clip the trapezoid to the limits. We only clip
  204.          * where an edge is entirely outside the limits. If we wanted
  205.          * to be more clever, we could handle cases where a trapezoid
  206.          * edge intersects the edge of the limits, but that would
  207.          * require slicing this trapezoid into multiple trapezoids,
  208.          * and I'm not sure the effort would be worth it. */
  209.         if (top < b->p1.y)
  210.             top = b->p1.y;
  211.  
  212.         if (bottom > b->p2.y)
  213.             bottom = b->p2.y;
  214.  
  215.         if (left.p1.x <= b->p1.x && left.p2.x <= b->p1.x)
  216.             left.p1.x = left.p2.x = b->p1.x;
  217.  
  218.         if (right.p1.x >= b->p2.x && right.p2.x >= b->p2.x)
  219.             right.p1.x = right.p2.x = b->p2.x;
  220.  
  221.         /* Trivial discards for empty trapezoids that are likely to
  222.          * be produced by our tessellators (most notably convex_quad
  223.          * when given a simple rectangle).
  224.          */
  225.         if (top >= bottom)
  226.             return;
  227.  
  228.         /* cheap colinearity check */
  229.         if (right.p1.x <= left.p1.x && right.p1.y == left.p1.y &&
  230.             right.p2.x <= left.p2.x && right.p2.y == left.p2.y)
  231.             return;
  232.  
  233.         _cairo_traps_add_trap (traps, top, bottom, &left, &right);
  234.     } else
  235.         _cairo_traps_add_trap (traps, _top, _bottom, _left, _right);
  236. }
  237.  
  238. static int
  239. _compare_point_fixed_by_y (const void *av, const void *bv)
  240. {
  241.     const cairo_point_t *a = av, *b = bv;
  242.     int ret = a->y - b->y;
  243.     if (ret == 0)
  244.         ret = a->x - b->x;
  245.     return ret;
  246. }
  247.  
  248. void
  249. _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
  250.                                      const cairo_point_t q[4])
  251. {
  252.     int a, b, c, d;
  253.     int i;
  254.     cairo_slope_t ab, ad;
  255.     cairo_bool_t b_left_of_d;
  256.     cairo_line_t left;
  257.     cairo_line_t right;
  258.  
  259.     /* Choose a as a point with minimal y */
  260.     a = 0;
  261.     for (i = 1; i < 4; i++)
  262.         if (_compare_point_fixed_by_y (&q[i], &q[a]) < 0)
  263.             a = i;
  264.  
  265.     /* b and d are adjacent to a, while c is opposite */
  266.     b = (a + 1) % 4;
  267.     c = (a + 2) % 4;
  268.     d = (a + 3) % 4;
  269.  
  270.     /* Choose between b and d so that b.y is less than d.y */
  271.     if (_compare_point_fixed_by_y (&q[d], &q[b]) < 0) {
  272.         b = (a + 3) % 4;
  273.         d = (a + 1) % 4;
  274.     }
  275.  
  276.     /* Without freedom left to choose anything else, we have four
  277.      * cases to tessellate.
  278.      *
  279.      * First, we have to determine the Y-axis sort of the four
  280.      * vertices, (either abcd or abdc). After that we need to detemine
  281.      * which edges will be "left" and which will be "right" in the
  282.      * resulting trapezoids. This can be determined by computing a
  283.      * slope comparison of ab and ad to determine if b is left of d or
  284.      * not.
  285.      *
  286.      * Note that "left of" here is in the sense of which edges should
  287.      * be the left vs. right edges of the trapezoid. In particular, b
  288.      * left of d does *not* mean that b.x is less than d.x.
  289.      *
  290.      * This should hopefully be made clear in the lame ASCII art
  291.      * below. Since the same slope comparison is used in all cases, we
  292.      * compute it before testing for the Y-value sort. */
  293.  
  294.     /* Note: If a == b then the ab slope doesn't give us any
  295.      * information. In that case, we can replace it with the ac (or
  296.      * equivalenly the bc) slope which gives us exactly the same
  297.      * information we need. At worst the names of the identifiers ab
  298.      * and b_left_of_d are inaccurate in this case, (would be ac, and
  299.      * c_left_of_d). */
  300.     if (q[a].x == q[b].x && q[a].y == q[b].y)
  301.         _cairo_slope_init (&ab, &q[a], &q[c]);
  302.     else
  303.         _cairo_slope_init (&ab, &q[a], &q[b]);
  304.  
  305.     _cairo_slope_init (&ad, &q[a], &q[d]);
  306.  
  307.     b_left_of_d = _cairo_slope_compare (&ab, &ad) > 0;
  308.  
  309.     if (q[c].y <= q[d].y) {
  310.         if (b_left_of_d) {
  311.             /* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad))
  312.              *
  313.              *                      top bot left right
  314.              *        _a  a  a
  315.              *      / /  /|  |\      a.y b.y  ab   ad
  316.              *     b /  b |  b \
  317.              *    / /   | |   \ \    b.y c.y  bc   ad
  318.              *   c /    c |    c \
  319.              *  | /      \|     \ \  c.y d.y  cd   ad
  320.              *  d         d       d
  321.              */
  322.             left.p1  = q[a]; left.p2  = q[b];
  323.             right.p1 = q[a]; right.p2 = q[d];
  324.             _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right);
  325.             left.p1  = q[b]; left.p2  = q[c];
  326.             _cairo_traps_add_clipped_trap (traps, q[b].y, q[c].y, &left, &right);
  327.             left.p1  = q[c]; left.p2  = q[d];
  328.             _cairo_traps_add_clipped_trap (traps, q[c].y, q[d].y, &left, &right);
  329.         } else {
  330.             /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
  331.              *
  332.              *       a  a  a_
  333.              *      /|  |\  \ \     a.y b.y  ad  ab
  334.              *     / b  | b  \ b
  335.              *    / /   | |   \ \   b.y c.y  ad  bc
  336.              *   / c    | c    \ c
  337.              *  / /     |/      \ | c.y d.y  ad  cd
  338.              *  d       d         d
  339.              */
  340.             left.p1  = q[a]; left.p2  = q[d];
  341.             right.p1 = q[a]; right.p2 = q[b];
  342.             _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right);
  343.             right.p1 = q[b]; right.p2 = q[c];
  344.             _cairo_traps_add_clipped_trap (traps, q[b].y, q[c].y, &left, &right);
  345.             right.p1 = q[c]; right.p2 = q[d];
  346.             _cairo_traps_add_clipped_trap (traps, q[c].y, q[d].y, &left, &right);
  347.         }
  348.     } else {
  349.         if (b_left_of_d) {
  350.             /* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad))
  351.              *
  352.              *        a   a     a
  353.              *       //  / \    |\     a.y b.y  ab  ad
  354.              *     /b/  b   \   b \
  355.              *    / /    \   \   \ \   b.y d.y  bc  ad
  356.              *   /d/      \   d   \ d
  357.              *  //         \ /     \|  d.y c.y  bc  dc
  358.              *  c           c       c
  359.              */
  360.             left.p1  = q[a]; left.p2  = q[b];
  361.             right.p1 = q[a]; right.p2 = q[d];
  362.             _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right);
  363.             left.p1  = q[b]; left.p2  = q[c];
  364.             _cairo_traps_add_clipped_trap (traps, q[b].y, q[d].y, &left, &right);
  365.             right.p1 = q[d]; right.p2 = q[c];
  366.             _cairo_traps_add_clipped_trap (traps, q[d].y, q[c].y, &left, &right);
  367.         } else {
  368.             /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
  369.              *
  370.              *      a     a   a
  371.              *     /|    / \  \\       a.y b.y  ad  ab
  372.              *    / b   /   b  \b\
  373.              *   / /   /   /    \ \    b.y d.y  ad  bc
  374.              *  d /   d   /      \d\
  375.              *  |/     \ /         \\  d.y c.y  dc  bc
  376.              *  c       c          c
  377.              */
  378.             left.p1  = q[a]; left.p2  = q[d];
  379.             right.p1 = q[a]; right.p2 = q[b];
  380.             _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right);
  381.             right.p1 = q[b]; right.p2 = q[c];
  382.             _cairo_traps_add_clipped_trap (traps, q[b].y, q[d].y, &left, &right);
  383.             left.p1  = q[d]; left.p2  = q[c];
  384.             _cairo_traps_add_clipped_trap (traps, q[d].y, q[c].y, &left, &right);
  385.         }
  386.     }
  387. }
  388.  
  389. /* A triangle is simply a degenerate case of a convex
  390.  * quadrilateral. We would not benefit from having any distinct
  391.  * implementation of triangle vs. quadrilateral tessellation here. */
  392. void
  393. _cairo_traps_tessellate_triangle (cairo_traps_t *traps,
  394.                                   const cairo_point_t t[3])
  395. {
  396.     cairo_point_t quad[4];
  397.  
  398.     quad[0] = t[0];
  399.     quad[1] = t[0];
  400.     quad[2] = t[1];
  401.     quad[3] = t[2];
  402.  
  403.     _cairo_traps_tessellate_convex_quad (traps, quad);
  404. }
  405.  
  406.  
  407. /**
  408.  * _cairo_traps_init_boxes:
  409.  * @traps: a #cairo_traps_t
  410.  * @box: an array box that will each be converted to a single trapezoid
  411.  *       to store in @traps.
  412.  *
  413.  * Initializes a #cairo_traps_t to contain an array of rectangular
  414.  * trapezoids.
  415.  **/
  416. cairo_status_t
  417. _cairo_traps_init_boxes (cairo_traps_t      *traps,
  418.                          const cairo_boxes_t *boxes)
  419. {
  420.     cairo_trapezoid_t *trap;
  421.     const struct _cairo_boxes_chunk *chunk;
  422.  
  423.     _cairo_traps_init (traps);
  424.  
  425.     while (traps->traps_size < boxes->num_boxes) {
  426.         if (unlikely (! _cairo_traps_grow (traps))) {
  427.             _cairo_traps_fini (traps);
  428.             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  429.         }
  430.     }
  431.  
  432.     traps->num_traps = boxes->num_boxes;
  433.     traps->is_rectilinear = TRUE;
  434.     traps->is_rectangular = TRUE;
  435.     traps->maybe_region = boxes->is_pixel_aligned;
  436.  
  437.     trap = &traps->traps[0];
  438.     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
  439.         const cairo_box_t *box;
  440.         int i;
  441.  
  442.         box = chunk->base;
  443.         for (i = 0; i < chunk->count; i++) {
  444.             trap->top    = box->p1.y;
  445.             trap->bottom = box->p2.y;
  446.  
  447.             trap->left.p1   = box->p1;
  448.             trap->left.p2.x = box->p1.x;
  449.             trap->left.p2.y = box->p2.y;
  450.  
  451.             trap->right.p1.x = box->p2.x;
  452.             trap->right.p1.y = box->p1.y;
  453.             trap->right.p2   = box->p2;
  454.  
  455.             box++, trap++;
  456.         }
  457.     }
  458.  
  459.     return CAIRO_STATUS_SUCCESS;
  460. }
  461.  
  462. cairo_status_t
  463. _cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
  464.                                    const cairo_point_t *top_left,
  465.                                    const cairo_point_t *bottom_right)
  466. {
  467.     cairo_line_t left;
  468.     cairo_line_t right;
  469.     cairo_fixed_t top, bottom;
  470.  
  471.     if (top_left->y == bottom_right->y)
  472.         return CAIRO_STATUS_SUCCESS;
  473.  
  474.     if (top_left->x == bottom_right->x)
  475.         return CAIRO_STATUS_SUCCESS;
  476.  
  477.      left.p1.x =  left.p2.x = top_left->x;
  478.      left.p1.y = right.p1.y = top_left->y;
  479.     right.p1.x = right.p2.x = bottom_right->x;
  480.      left.p2.y = right.p2.y = bottom_right->y;
  481.  
  482.      top = top_left->y;
  483.      bottom = bottom_right->y;
  484.  
  485.     if (traps->num_limits) {
  486.         cairo_bool_t reversed;
  487.         int n;
  488.  
  489.         if (top >= traps->bounds.p2.y || bottom <= traps->bounds.p1.y)
  490.             return CAIRO_STATUS_SUCCESS;
  491.  
  492.         /* support counter-clockwise winding for rectangular tessellation */
  493.         reversed = top_left->x > bottom_right->x;
  494.         if (reversed) {
  495.             right.p1.x = right.p2.x = top_left->x;
  496.             left.p1.x = left.p2.x = bottom_right->x;
  497.         }
  498.  
  499.         if (left.p1.x >= traps->bounds.p2.x || right.p1.x <= traps->bounds.p1.x)
  500.             return CAIRO_STATUS_SUCCESS;
  501.  
  502.         for (n = 0; n < traps->num_limits; n++) {
  503.             const cairo_box_t *limits = &traps->limits[n];
  504.             cairo_line_t _left, _right;
  505.             cairo_fixed_t _top, _bottom;
  506.  
  507.             if (top >= limits->p2.y)
  508.                 continue;
  509.             if (bottom <= limits->p1.y)
  510.                 continue;
  511.  
  512.             /* Trivially reject if trapezoid is entirely to the right or
  513.              * to the left of the limits. */
  514.             if (left.p1.x >= limits->p2.x)
  515.                 continue;
  516.             if (right.p1.x <= limits->p1.x)
  517.                 continue;
  518.  
  519.             /* Otherwise, clip the trapezoid to the limits. */
  520.             _top = top;
  521.             if (_top < limits->p1.y)
  522.                 _top = limits->p1.y;
  523.  
  524.             _bottom = bottom;
  525.             if (_bottom > limits->p2.y)
  526.                 _bottom = limits->p2.y;
  527.  
  528.             if (_bottom <= _top)
  529.                 continue;
  530.  
  531.             _left = left;
  532.             if (_left.p1.x < limits->p1.x) {
  533.                 _left.p1.x = limits->p1.x;
  534.                 _left.p1.y = limits->p1.y;
  535.                 _left.p2.x = limits->p1.x;
  536.                 _left.p2.y = limits->p2.y;
  537.             }
  538.  
  539.             _right = right;
  540.             if (_right.p1.x > limits->p2.x) {
  541.                 _right.p1.x = limits->p2.x;
  542.                 _right.p1.y = limits->p1.y;
  543.                 _right.p2.x = limits->p2.x;
  544.                 _right.p2.y = limits->p2.y;
  545.             }
  546.  
  547.             if (left.p1.x >= right.p1.x)
  548.                 continue;
  549.  
  550.             if (reversed)
  551.                 _cairo_traps_add_trap (traps, _top, _bottom, &_right, &_left);
  552.             else
  553.                 _cairo_traps_add_trap (traps, _top, _bottom, &_left, &_right);
  554.         }
  555.     } else {
  556.         _cairo_traps_add_trap (traps, top, bottom, &left, &right);
  557.     }
  558.  
  559.     return traps->status;
  560. }
  561.  
  562. void
  563. _cairo_traps_translate (cairo_traps_t *traps, int x, int y)
  564. {
  565.     cairo_fixed_t xoff, yoff;
  566.     cairo_trapezoid_t *t;
  567.     int i;
  568.  
  569.     /* Ugh. The cairo_composite/(Render) interface doesn't allow
  570.        an offset for the trapezoids. Need to manually shift all
  571.        the coordinates to align with the offset origin of the
  572.        intermediate surface. */
  573.  
  574.     xoff = _cairo_fixed_from_int (x);
  575.     yoff = _cairo_fixed_from_int (y);
  576.  
  577.     for (i = 0, t = traps->traps; i < traps->num_traps; i++, t++) {
  578.         t->top += yoff;
  579.         t->bottom += yoff;
  580.         t->left.p1.x += xoff;
  581.         t->left.p1.y += yoff;
  582.         t->left.p2.x += xoff;
  583.         t->left.p2.y += yoff;
  584.         t->right.p1.x += xoff;
  585.         t->right.p1.y += yoff;
  586.         t->right.p2.x += xoff;
  587.         t->right.p2.y += yoff;
  588.     }
  589. }
  590.  
  591. void
  592. _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
  593.                                             cairo_trapezoid_t *src_traps,
  594.                                             int num_traps,
  595.                                             double tx, double ty,
  596.                                             double sx, double sy)
  597. {
  598.     int i;
  599.     cairo_fixed_t xoff = _cairo_fixed_from_double (tx);
  600.     cairo_fixed_t yoff = _cairo_fixed_from_double (ty);
  601.  
  602.     if (sx == 1.0 && sy == 1.0) {
  603.         for (i = 0; i < num_traps; i++) {
  604.             offset_traps[i].top = src_traps[i].top + yoff;
  605.             offset_traps[i].bottom = src_traps[i].bottom + yoff;
  606.             offset_traps[i].left.p1.x = src_traps[i].left.p1.x + xoff;
  607.             offset_traps[i].left.p1.y = src_traps[i].left.p1.y + yoff;
  608.             offset_traps[i].left.p2.x = src_traps[i].left.p2.x + xoff;
  609.             offset_traps[i].left.p2.y = src_traps[i].left.p2.y + yoff;
  610.             offset_traps[i].right.p1.x = src_traps[i].right.p1.x + xoff;
  611.             offset_traps[i].right.p1.y = src_traps[i].right.p1.y + yoff;
  612.             offset_traps[i].right.p2.x = src_traps[i].right.p2.x + xoff;
  613.             offset_traps[i].right.p2.y = src_traps[i].right.p2.y + yoff;
  614.         }
  615.     } else {
  616.         cairo_fixed_t xsc = _cairo_fixed_from_double (sx);
  617.         cairo_fixed_t ysc = _cairo_fixed_from_double (sy);
  618.  
  619.         for (i = 0; i < num_traps; i++) {
  620.             offset_traps[i].top = _cairo_fixed_mul (src_traps[i].top + yoff, ysc);
  621.             offset_traps[i].bottom = _cairo_fixed_mul (src_traps[i].bottom + yoff, ysc);
  622.             offset_traps[i].left.p1.x = _cairo_fixed_mul (src_traps[i].left.p1.x + xoff, xsc);
  623.             offset_traps[i].left.p1.y = _cairo_fixed_mul (src_traps[i].left.p1.y + yoff, ysc);
  624.             offset_traps[i].left.p2.x = _cairo_fixed_mul (src_traps[i].left.p2.x + xoff, xsc);
  625.             offset_traps[i].left.p2.y = _cairo_fixed_mul (src_traps[i].left.p2.y + yoff, ysc);
  626.             offset_traps[i].right.p1.x = _cairo_fixed_mul (src_traps[i].right.p1.x + xoff, xsc);
  627.             offset_traps[i].right.p1.y = _cairo_fixed_mul (src_traps[i].right.p1.y + yoff, ysc);
  628.             offset_traps[i].right.p2.x = _cairo_fixed_mul (src_traps[i].right.p2.x + xoff, xsc);
  629.             offset_traps[i].right.p2.y = _cairo_fixed_mul (src_traps[i].right.p2.y + yoff, ysc);
  630.         }
  631.     }
  632. }
  633.  
  634. static cairo_bool_t
  635. _cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt)
  636. {
  637.     cairo_slope_t slope_left, slope_pt, slope_right;
  638.  
  639.     if (t->top > pt->y)
  640.         return FALSE;
  641.     if (t->bottom < pt->y)
  642.         return FALSE;
  643.  
  644.     _cairo_slope_init (&slope_left, &t->left.p1, &t->left.p2);
  645.     _cairo_slope_init (&slope_pt, &t->left.p1, pt);
  646.  
  647.     if (_cairo_slope_compare (&slope_left, &slope_pt) < 0)
  648.         return FALSE;
  649.  
  650.     _cairo_slope_init (&slope_right, &t->right.p1, &t->right.p2);
  651.     _cairo_slope_init (&slope_pt, &t->right.p1, pt);
  652.  
  653.     if (_cairo_slope_compare (&slope_pt, &slope_right) < 0)
  654.         return FALSE;
  655.  
  656.     return TRUE;
  657. }
  658.  
  659. cairo_bool_t
  660. _cairo_traps_contain (const cairo_traps_t *traps,
  661.                       double x, double y)
  662. {
  663.     int i;
  664.     cairo_point_t point;
  665.  
  666.     point.x = _cairo_fixed_from_double (x);
  667.     point.y = _cairo_fixed_from_double (y);
  668.  
  669.     for (i = 0; i < traps->num_traps; i++) {
  670.         if (_cairo_trap_contains (&traps->traps[i], &point))
  671.             return TRUE;
  672.     }
  673.  
  674.     return FALSE;
  675. }
  676.  
  677. static cairo_fixed_t
  678. _line_compute_intersection_x_for_y (const cairo_line_t *line,
  679.                                     cairo_fixed_t y)
  680. {
  681.     return _cairo_edge_compute_intersection_x_for_y (&line->p1, &line->p2, y);
  682. }
  683.  
  684. void
  685. _cairo_traps_extents (const cairo_traps_t *traps,
  686.                       cairo_box_t *extents)
  687. {
  688.     int i;
  689.  
  690.     if (traps->num_traps == 0) {
  691.         extents->p1.x = extents->p1.y = 0;
  692.         extents->p2.x = extents->p2.y = 0;
  693.         return;
  694.     }
  695.  
  696.     extents->p1.x = extents->p1.y = INT32_MAX;
  697.     extents->p2.x = extents->p2.y = INT32_MIN;
  698.  
  699.     for (i = 0; i < traps->num_traps; i++) {
  700.         const cairo_trapezoid_t *trap =  &traps->traps[i];
  701.  
  702.         if (trap->top < extents->p1.y)
  703.             extents->p1.y = trap->top;
  704.         if (trap->bottom > extents->p2.y)
  705.             extents->p2.y = trap->bottom;
  706.  
  707.         if (trap->left.p1.x < extents->p1.x) {
  708.             cairo_fixed_t x = trap->left.p1.x;
  709.             if (trap->top != trap->left.p1.y) {
  710.                 x = _line_compute_intersection_x_for_y (&trap->left,
  711.                                                         trap->top);
  712.                 if (x < extents->p1.x)
  713.                     extents->p1.x = x;
  714.             } else
  715.                 extents->p1.x = x;
  716.         }
  717.         if (trap->left.p2.x < extents->p1.x) {
  718.             cairo_fixed_t x = trap->left.p2.x;
  719.             if (trap->bottom != trap->left.p2.y) {
  720.                 x = _line_compute_intersection_x_for_y (&trap->left,
  721.                                                         trap->bottom);
  722.                 if (x < extents->p1.x)
  723.                     extents->p1.x = x;
  724.             } else
  725.                 extents->p1.x = x;
  726.         }
  727.  
  728.         if (trap->right.p1.x > extents->p2.x) {
  729.             cairo_fixed_t x = trap->right.p1.x;
  730.             if (trap->top != trap->right.p1.y) {
  731.                 x = _line_compute_intersection_x_for_y (&trap->right,
  732.                                                         trap->top);
  733.                 if (x > extents->p2.x)
  734.                     extents->p2.x = x;
  735.             } else
  736.                 extents->p2.x = x;
  737.         }
  738.         if (trap->right.p2.x > extents->p2.x) {
  739.             cairo_fixed_t x = trap->right.p2.x;
  740.             if (trap->bottom != trap->right.p2.y) {
  741.                 x = _line_compute_intersection_x_for_y (&trap->right,
  742.                                                         trap->bottom);
  743.                 if (x > extents->p2.x)
  744.                     extents->p2.x = x;
  745.             } else
  746.                 extents->p2.x = x;
  747.         }
  748.     }
  749. }
  750.  
  751. static cairo_bool_t
  752. _mono_edge_is_vertical (const cairo_line_t *line)
  753. {
  754.     return _cairo_fixed_integer_round_down (line->p1.x) == _cairo_fixed_integer_round_down (line->p2.x);
  755. }
  756.  
  757. static cairo_bool_t
  758. _traps_are_pixel_aligned (cairo_traps_t *traps,
  759.                           cairo_antialias_t antialias)
  760. {
  761.     int i;
  762.  
  763.     if (antialias == CAIRO_ANTIALIAS_NONE) {
  764.         for (i = 0; i < traps->num_traps; i++) {
  765.             if (! _mono_edge_is_vertical (&traps->traps[i].left)   ||
  766.                 ! _mono_edge_is_vertical (&traps->traps[i].right))
  767.             {
  768.                 traps->maybe_region = FALSE;
  769.                 return FALSE;
  770.             }
  771.         }
  772.     } else {
  773.         for (i = 0; i < traps->num_traps; i++) {
  774.             if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x   ||
  775.                 traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
  776.                 ! _cairo_fixed_is_integer (traps->traps[i].top)          ||
  777.                 ! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
  778.                 ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
  779.                 ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
  780.             {
  781.                 traps->maybe_region = FALSE;
  782.                 return FALSE;
  783.             }
  784.         }
  785.     }
  786.  
  787.     return TRUE;
  788. }
  789.  
  790. /**
  791.  * _cairo_traps_extract_region:
  792.  * @traps: a #cairo_traps_t
  793.  * @region: a #cairo_region_t
  794.  *
  795.  * Determines if a set of trapezoids are exactly representable as a
  796.  * cairo region.  If so, the passed-in region is initialized to
  797.  * the area representing the given traps.  It should be finalized
  798.  * with cairo_region_fini().  If not, %CAIRO_INT_STATUS_UNSUPPORTED
  799.  * is returned.
  800.  *
  801.  * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
  802.  * or %CAIRO_STATUS_NO_MEMORY
  803.  **/
  804. cairo_int_status_t
  805. _cairo_traps_extract_region (cairo_traps_t   *traps,
  806.                              cairo_antialias_t antialias,
  807.                              cairo_region_t **region)
  808. {
  809.     cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
  810.     cairo_rectangle_int_t *rects = stack_rects;
  811.     cairo_int_status_t status;
  812.     int i, rect_count;
  813.  
  814.     /* we only treat this a hint... */
  815.     if (antialias != CAIRO_ANTIALIAS_NONE && ! traps->maybe_region)
  816.         return CAIRO_INT_STATUS_UNSUPPORTED;
  817.  
  818.     if (! _traps_are_pixel_aligned (traps, antialias)) {
  819.         traps->maybe_region = FALSE;
  820.         return CAIRO_INT_STATUS_UNSUPPORTED;
  821.     }
  822.  
  823.     if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
  824.         rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t));
  825.  
  826.         if (unlikely (rects == NULL))
  827.             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  828.     }
  829.  
  830.     rect_count = 0;
  831.     for (i = 0; i < traps->num_traps; i++) {
  832.         int x1, y1, x2, y2;
  833.  
  834.         if (antialias == CAIRO_ANTIALIAS_NONE) {
  835.             x1 = _cairo_fixed_integer_round_down (traps->traps[i].left.p1.x);
  836.             y1 = _cairo_fixed_integer_round_down (traps->traps[i].top);
  837.             x2 = _cairo_fixed_integer_round_down (traps->traps[i].right.p1.x);
  838.             y2 = _cairo_fixed_integer_round_down (traps->traps[i].bottom);
  839.         } else {
  840.             x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
  841.             y1 = _cairo_fixed_integer_part (traps->traps[i].top);
  842.             x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
  843.             y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
  844.         }
  845.  
  846.         if (x2 > x1 && y2 > y1) {
  847.             rects[rect_count].x = x1;
  848.             rects[rect_count].y = y1;
  849.             rects[rect_count].width  = x2 - x1;
  850.             rects[rect_count].height = y2 - y1;
  851.             rect_count++;
  852.         }
  853.     }
  854.  
  855.  
  856.     *region = cairo_region_create_rectangles (rects, rect_count);
  857.     status = (*region)->status;
  858.  
  859.     if (rects != stack_rects)
  860.         free (rects);
  861.  
  862.     return status;
  863. }
  864.  
  865. cairo_bool_t
  866. _cairo_traps_to_boxes (cairo_traps_t *traps,
  867.                        cairo_antialias_t antialias,
  868.                        cairo_boxes_t *boxes)
  869. {
  870.     int i;
  871.  
  872.     for (i = 0; i < traps->num_traps; i++) {
  873.         if (traps->traps[i].left.p1.x  != traps->traps[i].left.p2.x ||
  874.             traps->traps[i].right.p1.x != traps->traps[i].right.p2.x)
  875.             return FALSE;
  876.     }
  877.  
  878.     _cairo_boxes_init (boxes);
  879.  
  880.     boxes->num_boxes    = traps->num_traps;
  881.     boxes->chunks.base  = (cairo_box_t *) traps->traps;
  882.     boxes->chunks.count = traps->num_traps;
  883.     boxes->chunks.size  = traps->num_traps;
  884.  
  885.     if (antialias != CAIRO_ANTIALIAS_NONE) {
  886.         for (i = 0; i < traps->num_traps; i++) {
  887.             /* Note the traps and boxes alias so we need to take the local copies first. */
  888.             cairo_fixed_t x1 = traps->traps[i].left.p1.x;
  889.             cairo_fixed_t x2 = traps->traps[i].right.p1.x;
  890.             cairo_fixed_t y1 = traps->traps[i].top;
  891.             cairo_fixed_t y2 = traps->traps[i].bottom;
  892.  
  893.             boxes->chunks.base[i].p1.x = x1;
  894.             boxes->chunks.base[i].p1.y = y1;
  895.             boxes->chunks.base[i].p2.x = x2;
  896.             boxes->chunks.base[i].p2.y = y2;
  897.  
  898.             if (boxes->is_pixel_aligned) {
  899.                 boxes->is_pixel_aligned =
  900.                     _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
  901.                     _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
  902.             }
  903.         }
  904.     } else {
  905.         boxes->is_pixel_aligned = TRUE;
  906.  
  907.         for (i = 0; i < traps->num_traps; i++) {
  908.             /* Note the traps and boxes alias so we need to take the local copies first. */
  909.             cairo_fixed_t x1 = traps->traps[i].left.p1.x;
  910.             cairo_fixed_t x2 = traps->traps[i].right.p1.x;
  911.             cairo_fixed_t y1 = traps->traps[i].top;
  912.             cairo_fixed_t y2 = traps->traps[i].bottom;
  913.  
  914.             /* round down here to match Pixman's behavior when using traps. */
  915.             boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
  916.             boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
  917.             boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
  918.             boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
  919.         }
  920.     }
  921.  
  922.     return TRUE;
  923. }
  924.  
  925. /* moves trap points such that they become the actual corners of the trapezoid */
  926. static void
  927. _sanitize_trap (cairo_trapezoid_t *t)
  928. {
  929.     cairo_trapezoid_t s = *t;
  930.  
  931. #define FIX(lr, tb, p) \
  932.     if (t->lr.p.y != t->tb) { \
  933.         t->lr.p.x = s.lr.p2.x + _cairo_fixed_mul_div_floor (s.lr.p1.x - s.lr.p2.x, s.tb - s.lr.p2.y, s.lr.p1.y - s.lr.p2.y); \
  934.         t->lr.p.y = s.tb; \
  935.     }
  936.     FIX (left,  top,    p1);
  937.     FIX (left,  bottom, p2);
  938.     FIX (right, top,    p1);
  939.     FIX (right, bottom, p2);
  940. }
  941.  
  942. cairo_private cairo_status_t
  943. _cairo_traps_path (const cairo_traps_t *traps,
  944.                    cairo_path_fixed_t  *path)
  945. {
  946.     int i;
  947.  
  948.     for (i = 0; i < traps->num_traps; i++) {
  949.         cairo_status_t status;
  950.         cairo_trapezoid_t trap = traps->traps[i];
  951.  
  952.         if (trap.top == trap.bottom)
  953.             continue;
  954.  
  955.         _sanitize_trap (&trap);
  956.  
  957.         status = _cairo_path_fixed_move_to (path, trap.left.p1.x, trap.top);
  958.         if (unlikely (status)) return status;
  959.         status = _cairo_path_fixed_line_to (path, trap.right.p1.x, trap.top);
  960.         if (unlikely (status)) return status;
  961.         status = _cairo_path_fixed_line_to (path, trap.right.p2.x, trap.bottom);
  962.         if (unlikely (status)) return status;
  963.         status = _cairo_path_fixed_line_to (path, trap.left.p2.x, trap.bottom);
  964.         if (unlikely (status)) return status;
  965.         status = _cairo_path_fixed_close_path (path);
  966.         if (unlikely (status)) return status;
  967.     }
  968.  
  969.     return CAIRO_STATUS_SUCCESS;
  970. }
  971.  
  972. void
  973. _cairo_debug_print_traps (FILE *file, const cairo_traps_t *traps)
  974. {
  975.     cairo_box_t extents;
  976.     int n;
  977.  
  978. #if 0
  979.     if (traps->has_limits) {
  980.         printf ("%s: limits=(%d, %d, %d, %d)\n",
  981.                 filename,
  982.                 traps->limits.p1.x, traps->limits.p1.y,
  983.                 traps->limits.p2.x, traps->limits.p2.y);
  984.     }
  985. #endif
  986.  
  987.     _cairo_traps_extents (traps, &extents);
  988.     fprintf (file, "extents=(%d, %d, %d, %d)\n",
  989.              extents.p1.x, extents.p1.y,
  990.              extents.p2.x, extents.p2.y);
  991.  
  992.     for (n = 0; n < traps->num_traps; n++) {
  993.         fprintf (file, "%d %d L:(%d, %d), (%d, %d) R:(%d, %d), (%d, %d)\n",
  994.                  traps->traps[n].top,
  995.                  traps->traps[n].bottom,
  996.                  traps->traps[n].left.p1.x,
  997.                  traps->traps[n].left.p1.y,
  998.                  traps->traps[n].left.p2.x,
  999.                  traps->traps[n].left.p2.y,
  1000.                  traps->traps[n].right.p1.x,
  1001.                  traps->traps[n].right.p1.y,
  1002.                  traps->traps[n].right.p2.x,
  1003.                  traps->traps[n].right.p2.y);
  1004.     }
  1005. }
  1006.  
  1007. struct cairo_trap_renderer {
  1008.     cairo_span_renderer_t base;
  1009.     cairo_traps_t *traps;
  1010. };
  1011.  
  1012. static cairo_status_t
  1013. span_to_traps (void *abstract_renderer, int y, int h,
  1014.                const cairo_half_open_span_t *spans, unsigned num_spans)
  1015. {
  1016.     struct cairo_trap_renderer *r = abstract_renderer;
  1017.     cairo_fixed_t top, bot;
  1018.  
  1019.     if (num_spans == 0)
  1020.         return CAIRO_STATUS_SUCCESS;
  1021.  
  1022.     top = _cairo_fixed_from_int (y);
  1023.     bot = _cairo_fixed_from_int (y + h);
  1024.     do {
  1025.         if (spans[0].coverage) {
  1026.             cairo_fixed_t x0 = _cairo_fixed_from_int(spans[0].x);
  1027.             cairo_fixed_t x1 = _cairo_fixed_from_int(spans[1].x);
  1028.             cairo_line_t left = { { x0, top }, { x0, bot } },
  1029.                          right = { { x1, top }, { x1, bot } };
  1030.             _cairo_traps_add_trap (r->traps, top, bot, &left, &right);
  1031.         }
  1032.         spans++;
  1033.     } while (--num_spans > 1);
  1034.  
  1035.     return CAIRO_STATUS_SUCCESS;
  1036. }
  1037.  
  1038. cairo_int_status_t
  1039. _cairo_rasterise_polygon_to_traps (cairo_polygon_t                      *polygon,
  1040.                                    cairo_fill_rule_t                     fill_rule,
  1041.                                    cairo_antialias_t                     antialias,
  1042.                                    cairo_traps_t *traps)
  1043. {
  1044.     struct cairo_trap_renderer renderer;
  1045.     cairo_scan_converter_t *converter;
  1046.     cairo_int_status_t status;
  1047.     cairo_rectangle_int_t r;
  1048.  
  1049.     TRACE ((stderr, "%s: fill_rule=%d, antialias=%d\n",
  1050.             __FUNCTION__, fill_rule, antialias));
  1051.     assert(antialias == CAIRO_ANTIALIAS_NONE);
  1052.  
  1053.     renderer.traps = traps;
  1054.     renderer.base.render_rows = span_to_traps;
  1055.  
  1056.     _cairo_box_round_to_rectangle (&polygon->extents, &r);
  1057.     converter = _cairo_mono_scan_converter_create (r.x, r.y,
  1058.                                                    r.x + r.width,
  1059.                                                    r.y + r.height,
  1060.                                                    fill_rule);
  1061.     status = _cairo_mono_scan_converter_add_polygon (converter, polygon);
  1062.     if (likely (status == CAIRO_INT_STATUS_SUCCESS))
  1063.         status = converter->generate (converter, &renderer.base);
  1064.     converter->destroy (converter);
  1065.     return status;
  1066. }
  1067.