LCOV - code coverage report
Current view: directory - gfx/cairo/cairo/src - cairo-traps.c (source / functions) Found Hit Coverage
Test: app.info Lines: 291 0 0.0 %
Date: 2012-06-02 Functions: 17 0 0.0 %

       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-boxes-private.h"
      43                 : #include "cairo-error-private.h"
      44                 : #include "cairo-region-private.h"
      45                 : #include "cairo-slope-private.h"
      46                 : 
      47                 : /* private functions */
      48                 : 
      49                 : void
      50               0 : _cairo_traps_init (cairo_traps_t *traps)
      51                 : {
      52                 :     VG (VALGRIND_MAKE_MEM_UNDEFINED (traps, sizeof (cairo_traps_t)));
      53                 : 
      54               0 :     traps->status = CAIRO_STATUS_SUCCESS;
      55                 : 
      56               0 :     traps->maybe_region = 1;
      57               0 :     traps->is_rectilinear = 0;
      58               0 :     traps->is_rectangular = 0;
      59                 : 
      60               0 :     traps->num_traps = 0;
      61                 : 
      62               0 :     traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
      63               0 :     traps->traps = traps->traps_embedded;
      64                 : 
      65               0 :     traps->num_limits = 0;
      66               0 :     traps->has_intersections = FALSE;
      67               0 : }
      68                 : 
      69                 : void
      70               0 : _cairo_traps_limit (cairo_traps_t       *traps,
      71                 :                     const cairo_box_t   *limits,
      72                 :                     int                  num_limits)
      73                 : {
      74               0 :     traps->limits = limits;
      75               0 :     traps->num_limits = num_limits;
      76               0 : }
      77                 : 
      78                 : void
      79               0 : _cairo_traps_clear (cairo_traps_t *traps)
      80                 : {
      81               0 :     traps->status = CAIRO_STATUS_SUCCESS;
      82                 : 
      83               0 :     traps->maybe_region = 1;
      84               0 :     traps->is_rectilinear = 0;
      85               0 :     traps->is_rectangular = 0;
      86                 : 
      87               0 :     traps->num_traps = 0;
      88               0 :     traps->has_intersections = FALSE;
      89               0 : }
      90                 : 
      91                 : void
      92               0 : _cairo_traps_fini (cairo_traps_t *traps)
      93                 : {
      94               0 :     if (traps->traps != traps->traps_embedded)
      95               0 :         free (traps->traps);
      96                 : 
      97                 :     VG (VALGRIND_MAKE_MEM_NOACCESS (traps, sizeof (cairo_traps_t)));
      98               0 : }
      99                 : 
     100                 : /* make room for at least one more trap */
     101                 : static cairo_bool_t
     102               0 : _cairo_traps_grow (cairo_traps_t *traps)
     103                 : {
     104                 :     cairo_trapezoid_t *new_traps;
     105               0 :     int new_size = 4 * traps->traps_size;
     106                 : 
     107                 :     if (CAIRO_INJECT_FAULT ()) {
     108                 :         traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
     109                 :         return FALSE;
     110                 :     }
     111                 : 
     112               0 :     if (traps->traps == traps->traps_embedded) {
     113               0 :         new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
     114               0 :         if (new_traps != NULL)
     115               0 :             memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
     116                 :     } else {
     117               0 :         new_traps = _cairo_realloc_ab (traps->traps,
     118                 :                                        new_size, sizeof (cairo_trapezoid_t));
     119                 :     }
     120                 : 
     121               0 :     if (unlikely (new_traps == NULL)) {
     122               0 :         traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
     123               0 :         return FALSE;
     124                 :     }
     125                 : 
     126               0 :     traps->traps = new_traps;
     127               0 :     traps->traps_size = new_size;
     128               0 :     return TRUE;
     129                 : }
     130                 : 
     131                 : void
     132               0 : _cairo_traps_add_trap (cairo_traps_t *traps,
     133                 :                        cairo_fixed_t top, cairo_fixed_t bottom,
     134                 :                        cairo_line_t *left, cairo_line_t *right)
     135                 : {
     136                 :     cairo_trapezoid_t *trap;
     137                 : 
     138               0 :     if (unlikely (traps->num_traps == traps->traps_size)) {
     139               0 :         if (unlikely (! _cairo_traps_grow (traps)))
     140               0 :             return;
     141                 :     }
     142                 : 
     143               0 :     trap = &traps->traps[traps->num_traps++];
     144               0 :     trap->top = top;
     145               0 :     trap->bottom = bottom;
     146               0 :     trap->left = *left;
     147               0 :     trap->right = *right;
     148                 : }
     149                 : 
     150                 : /**
     151                 :  * _cairo_traps_init_box:
     152                 :  * @traps: a #cairo_traps_t
     153                 :  * @box: an array box that will each be converted to a single trapezoid
     154                 :  *       to store in @traps.
     155                 :  *
     156                 :  * Initializes a #cairo_traps_t to contain an array of rectangular
     157                 :  * trapezoids.
     158                 :  **/
     159                 : cairo_status_t
     160               0 : _cairo_traps_init_boxes (cairo_traps_t      *traps,
     161                 :                          const cairo_boxes_t *boxes)
     162                 : {
     163                 :     cairo_trapezoid_t *trap;
     164                 :     const struct _cairo_boxes_chunk *chunk;
     165                 : 
     166               0 :     _cairo_traps_init (traps);
     167                 : 
     168               0 :     while (traps->traps_size < boxes->num_boxes) {
     169               0 :         if (unlikely (! _cairo_traps_grow (traps))) {
     170               0 :             _cairo_traps_fini (traps);
     171               0 :             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     172                 :         }
     173                 :     }
     174                 : 
     175               0 :     traps->num_traps = boxes->num_boxes;
     176               0 :     traps->is_rectilinear = TRUE;
     177               0 :     traps->is_rectangular = TRUE;
     178               0 :     traps->maybe_region = boxes->is_pixel_aligned;
     179                 : 
     180               0 :     trap = &traps->traps[0];
     181               0 :     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
     182                 :         const cairo_box_t *box;
     183                 :         int i;
     184                 : 
     185               0 :         box = chunk->base;
     186               0 :         for (i = 0; i < chunk->count; i++) {
     187               0 :             trap->top    = box->p1.y;
     188               0 :             trap->bottom = box->p2.y;
     189                 : 
     190               0 :             trap->left.p1   = box->p1;
     191               0 :             trap->left.p2.x = box->p1.x;
     192               0 :             trap->left.p2.y = box->p2.y;
     193                 : 
     194               0 :             trap->right.p1.x = box->p2.x;
     195               0 :             trap->right.p1.y = box->p1.y;
     196               0 :             trap->right.p2   = box->p2;
     197                 : 
     198               0 :             box++, trap++;
     199                 :         }
     200                 :     }
     201                 : 
     202               0 :     return CAIRO_STATUS_SUCCESS;
     203                 : }
     204                 : 
     205                 : cairo_status_t
     206               0 : _cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
     207                 :                                    const cairo_point_t *top_left,
     208                 :                                    const cairo_point_t *bottom_right)
     209                 : {
     210                 :     cairo_line_t left;
     211                 :     cairo_line_t right;
     212                 :     cairo_fixed_t top, bottom;
     213                 : 
     214               0 :     if (top_left->y == bottom_right->y)
     215               0 :         return CAIRO_STATUS_SUCCESS;
     216                 : 
     217               0 :     if (top_left->x == bottom_right->x)
     218               0 :         return CAIRO_STATUS_SUCCESS;
     219                 : 
     220               0 :      left.p1.x =  left.p2.x = top_left->x;
     221               0 :      left.p1.y = right.p1.y = top_left->y;
     222               0 :     right.p1.x = right.p2.x = bottom_right->x;
     223               0 :      left.p2.y = right.p2.y = bottom_right->y;
     224                 : 
     225               0 :      top = top_left->y;
     226               0 :      bottom = bottom_right->y;
     227                 : 
     228               0 :     if (traps->num_limits) {
     229                 :         cairo_bool_t reversed;
     230                 :         int n;
     231                 : 
     232                 :         /* support counter-clockwise winding for rectangular tessellation */
     233               0 :         reversed = top_left->x > bottom_right->x;
     234               0 :         if (reversed) {
     235               0 :             right.p1.x = right.p2.x = top_left->x;
     236               0 :             left.p1.x = left.p2.x = bottom_right->x;
     237                 :         }
     238                 : 
     239               0 :         for (n = 0; n < traps->num_limits; n++) {
     240               0 :             const cairo_box_t *limits = &traps->limits[n];
     241                 :             cairo_line_t _left, _right;
     242                 :             cairo_fixed_t _top, _bottom;
     243                 : 
     244               0 :             if (top >= limits->p2.y)
     245               0 :                 continue;
     246               0 :             if (bottom <= limits->p1.y)
     247               0 :                 continue;
     248                 : 
     249                 :             /* Trivially reject if trapezoid is entirely to the right or
     250                 :              * to the left of the limits. */
     251               0 :             if (left.p1.x >= limits->p2.x)
     252               0 :                 continue;
     253               0 :             if (right.p1.x <= limits->p1.x)
     254               0 :                 continue;
     255                 : 
     256                 :             /* Otherwise, clip the trapezoid to the limits. */
     257               0 :             _top = top;
     258               0 :             if (_top < limits->p1.y)
     259               0 :                 _top = limits->p1.y;
     260                 : 
     261               0 :             _bottom = bottom;
     262               0 :             if (_bottom > limits->p2.y)
     263               0 :                 _bottom = limits->p2.y;
     264                 : 
     265               0 :             if (_bottom <= _top)
     266               0 :                 continue;
     267                 : 
     268               0 :             _left = left;
     269               0 :             if (_left.p1.x < limits->p1.x) {
     270               0 :                 _left.p1.x = limits->p1.x;
     271               0 :                 _left.p1.y = limits->p1.y;
     272               0 :                 _left.p2.x = limits->p1.x;
     273               0 :                 _left.p2.y = limits->p2.y;
     274                 :             }
     275                 : 
     276               0 :             _right = right;
     277               0 :             if (_right.p1.x > limits->p2.x) {
     278               0 :                 _right.p1.x = limits->p2.x;
     279               0 :                 _right.p1.y = limits->p1.y;
     280               0 :                 _right.p2.x = limits->p2.x;
     281               0 :                 _right.p2.y = limits->p2.y;
     282                 :             }
     283                 : 
     284               0 :             if (left.p1.x >= right.p1.x)
     285               0 :                 continue;
     286                 : 
     287               0 :             if (reversed)
     288               0 :                 _cairo_traps_add_trap (traps, _top, _bottom, &_right, &_left);
     289                 :             else
     290               0 :                 _cairo_traps_add_trap (traps, _top, _bottom, &_left, &_right);
     291                 :         }
     292                 :     } else {
     293               0 :         _cairo_traps_add_trap (traps, top, bottom, &left, &right);
     294                 :     }
     295                 : 
     296               0 :     return traps->status;
     297                 : }
     298                 : 
     299                 : void
     300               0 : _cairo_traps_translate (cairo_traps_t *traps, int x, int y)
     301                 : {
     302                 :     cairo_fixed_t xoff, yoff;
     303                 :     cairo_trapezoid_t *t;
     304                 :     int i;
     305                 : 
     306                 :     /* Ugh. The cairo_composite/(Render) interface doesn't allow
     307                 :        an offset for the trapezoids. Need to manually shift all
     308                 :        the coordinates to align with the offset origin of the
     309                 :        intermediate surface. */
     310                 : 
     311               0 :     xoff = _cairo_fixed_from_int (x);
     312               0 :     yoff = _cairo_fixed_from_int (y);
     313                 : 
     314               0 :     for (i = 0, t = traps->traps; i < traps->num_traps; i++, t++) {
     315               0 :         t->top += yoff;
     316               0 :         t->bottom += yoff;
     317               0 :         t->left.p1.x += xoff;
     318               0 :         t->left.p1.y += yoff;
     319               0 :         t->left.p2.x += xoff;
     320               0 :         t->left.p2.y += yoff;
     321               0 :         t->right.p1.x += xoff;
     322               0 :         t->right.p1.y += yoff;
     323               0 :         t->right.p2.x += xoff;
     324               0 :         t->right.p2.y += yoff;
     325                 :     }
     326               0 : }
     327                 : 
     328                 : void
     329               0 : _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
     330                 :                                             cairo_trapezoid_t *src_traps,
     331                 :                                             int num_traps,
     332                 :                                             double tx, double ty,
     333                 :                                             double sx, double sy)
     334                 : {
     335                 :     int i;
     336               0 :     cairo_fixed_t xoff = _cairo_fixed_from_double (tx);
     337               0 :     cairo_fixed_t yoff = _cairo_fixed_from_double (ty);
     338                 : 
     339               0 :     if (sx == 1.0 && sy == 1.0) {
     340               0 :         for (i = 0; i < num_traps; i++) {
     341               0 :             offset_traps[i].top = src_traps[i].top + yoff;
     342               0 :             offset_traps[i].bottom = src_traps[i].bottom + yoff;
     343               0 :             offset_traps[i].left.p1.x = src_traps[i].left.p1.x + xoff;
     344               0 :             offset_traps[i].left.p1.y = src_traps[i].left.p1.y + yoff;
     345               0 :             offset_traps[i].left.p2.x = src_traps[i].left.p2.x + xoff;
     346               0 :             offset_traps[i].left.p2.y = src_traps[i].left.p2.y + yoff;
     347               0 :             offset_traps[i].right.p1.x = src_traps[i].right.p1.x + xoff;
     348               0 :             offset_traps[i].right.p1.y = src_traps[i].right.p1.y + yoff;
     349               0 :             offset_traps[i].right.p2.x = src_traps[i].right.p2.x + xoff;
     350               0 :             offset_traps[i].right.p2.y = src_traps[i].right.p2.y + yoff;
     351                 :         }
     352                 :     } else {
     353               0 :         cairo_fixed_t xsc = _cairo_fixed_from_double (sx);
     354               0 :         cairo_fixed_t ysc = _cairo_fixed_from_double (sy);
     355                 : 
     356               0 :         for (i = 0; i < num_traps; i++) {
     357               0 :             offset_traps[i].top = _cairo_fixed_mul (src_traps[i].top + yoff, ysc);
     358               0 :             offset_traps[i].bottom = _cairo_fixed_mul (src_traps[i].bottom + yoff, ysc);
     359               0 :             offset_traps[i].left.p1.x = _cairo_fixed_mul (src_traps[i].left.p1.x + xoff, xsc);
     360               0 :             offset_traps[i].left.p1.y = _cairo_fixed_mul (src_traps[i].left.p1.y + yoff, ysc);
     361               0 :             offset_traps[i].left.p2.x = _cairo_fixed_mul (src_traps[i].left.p2.x + xoff, xsc);
     362               0 :             offset_traps[i].left.p2.y = _cairo_fixed_mul (src_traps[i].left.p2.y + yoff, ysc);
     363               0 :             offset_traps[i].right.p1.x = _cairo_fixed_mul (src_traps[i].right.p1.x + xoff, xsc);
     364               0 :             offset_traps[i].right.p1.y = _cairo_fixed_mul (src_traps[i].right.p1.y + yoff, ysc);
     365               0 :             offset_traps[i].right.p2.x = _cairo_fixed_mul (src_traps[i].right.p2.x + xoff, xsc);
     366               0 :             offset_traps[i].right.p2.y = _cairo_fixed_mul (src_traps[i].right.p2.y + yoff, ysc);
     367                 :         }
     368                 :     }
     369               0 : }
     370                 : 
     371                 : static cairo_bool_t
     372               0 : _cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt)
     373                 : {
     374                 :     cairo_slope_t slope_left, slope_pt, slope_right;
     375                 : 
     376               0 :     if (t->top > pt->y)
     377               0 :         return FALSE;
     378               0 :     if (t->bottom < pt->y)
     379               0 :         return FALSE;
     380                 : 
     381               0 :     _cairo_slope_init (&slope_left, &t->left.p1, &t->left.p2);
     382               0 :     _cairo_slope_init (&slope_pt, &t->left.p1, pt);
     383                 : 
     384               0 :     if (_cairo_slope_compare (&slope_left, &slope_pt) < 0)
     385               0 :         return FALSE;
     386                 : 
     387               0 :     _cairo_slope_init (&slope_right, &t->right.p1, &t->right.p2);
     388               0 :     _cairo_slope_init (&slope_pt, &t->right.p1, pt);
     389                 : 
     390               0 :     if (_cairo_slope_compare (&slope_pt, &slope_right) < 0)
     391               0 :         return FALSE;
     392                 : 
     393               0 :     return TRUE;
     394                 : }
     395                 : 
     396                 : cairo_bool_t
     397               0 : _cairo_traps_contain (const cairo_traps_t *traps,
     398                 :                       double x, double y)
     399                 : {
     400                 :     int i;
     401                 :     cairo_point_t point;
     402                 : 
     403               0 :     point.x = _cairo_fixed_from_double (x);
     404               0 :     point.y = _cairo_fixed_from_double (y);
     405                 : 
     406               0 :     for (i = 0; i < traps->num_traps; i++) {
     407               0 :         if (_cairo_trap_contains (&traps->traps[i], &point))
     408               0 :             return TRUE;
     409                 :     }
     410                 : 
     411               0 :     return FALSE;
     412                 : }
     413                 : 
     414                 : static cairo_fixed_t
     415               0 : _line_compute_intersection_x_for_y (const cairo_line_t *line,
     416                 :                                     cairo_fixed_t y)
     417                 : {
     418               0 :     return _cairo_edge_compute_intersection_x_for_y (&line->p1, &line->p2, y);
     419                 : }
     420                 : 
     421                 : void
     422               0 : _cairo_traps_extents (const cairo_traps_t *traps,
     423                 :                       cairo_box_t *extents)
     424                 : {
     425                 :     int i;
     426                 : 
     427               0 :     if (traps->num_traps == 0) {
     428               0 :         extents->p1.x = extents->p1.y = 0;
     429               0 :         extents->p2.x = extents->p2.y = 0;
     430               0 :         return;
     431                 :     }
     432                 : 
     433               0 :     extents->p1.x = extents->p1.y = INT32_MAX;
     434               0 :     extents->p2.x = extents->p2.y = INT32_MIN;
     435                 : 
     436               0 :     for (i = 0; i < traps->num_traps; i++) {
     437               0 :         const cairo_trapezoid_t *trap =  &traps->traps[i];
     438                 : 
     439               0 :         if (trap->top < extents->p1.y)
     440               0 :             extents->p1.y = trap->top;
     441               0 :         if (trap->bottom > extents->p2.y)
     442               0 :             extents->p2.y = trap->bottom;
     443                 : 
     444               0 :         if (trap->left.p1.x < extents->p1.x) {
     445               0 :             cairo_fixed_t x = trap->left.p1.x;
     446               0 :             if (trap->top != trap->left.p1.y) {
     447               0 :                 x = _line_compute_intersection_x_for_y (&trap->left,
     448                 :                                                         trap->top);
     449               0 :                 if (x < extents->p1.x)
     450               0 :                     extents->p1.x = x;
     451                 :             } else
     452               0 :                 extents->p1.x = x;
     453                 :         }
     454               0 :         if (trap->left.p2.x < extents->p1.x) {
     455               0 :             cairo_fixed_t x = trap->left.p2.x;
     456               0 :             if (trap->bottom != trap->left.p2.y) {
     457               0 :                 x = _line_compute_intersection_x_for_y (&trap->left,
     458                 :                                                         trap->bottom);
     459               0 :                 if (x < extents->p1.x)
     460               0 :                     extents->p1.x = x;
     461                 :             } else
     462               0 :                 extents->p1.x = x;
     463                 :         }
     464                 : 
     465               0 :         if (trap->right.p1.x > extents->p2.x) {
     466               0 :             cairo_fixed_t x = trap->right.p1.x;
     467               0 :             if (trap->top != trap->right.p1.y) {
     468               0 :                 x = _line_compute_intersection_x_for_y (&trap->right,
     469                 :                                                         trap->top);
     470               0 :                 if (x > extents->p2.x)
     471               0 :                     extents->p2.x = x;
     472                 :             } else
     473               0 :                 extents->p2.x = x;
     474                 :         }
     475               0 :         if (trap->right.p2.x > extents->p2.x) {
     476               0 :             cairo_fixed_t x = trap->right.p2.x;
     477               0 :             if (trap->bottom != trap->right.p2.y) {
     478               0 :                 x = _line_compute_intersection_x_for_y (&trap->right,
     479                 :                                                         trap->bottom);
     480               0 :                 if (x > extents->p2.x)
     481               0 :                     extents->p2.x = x;
     482                 :             } else
     483               0 :                 extents->p2.x = x;
     484                 :         }
     485                 :     }
     486                 : }
     487                 : 
     488                 : 
     489                 : /**
     490                 :  * _cairo_traps_extract_region:
     491                 :  * @traps: a #cairo_traps_t
     492                 :  * @region: a #cairo_region_t
     493                 :  *
     494                 :  * Determines if a set of trapezoids are exactly representable as a
     495                 :  * cairo region.  If so, the passed-in region is initialized to
     496                 :  * the area representing the given traps.  It should be finalized
     497                 :  * with cairo_region_fini().  If not, %CAIRO_INT_STATUS_UNSUPPORTED
     498                 :  * is returned.
     499                 :  *
     500                 :  * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
     501                 :  * or %CAIRO_STATUS_NO_MEMORY
     502                 :  **/
     503                 : cairo_int_status_t
     504               0 : _cairo_traps_extract_region (cairo_traps_t   *traps,
     505                 :                              cairo_region_t **region)
     506                 : {
     507                 :     cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
     508               0 :     cairo_rectangle_int_t *rects = stack_rects;
     509                 :     cairo_int_status_t status;
     510                 :     int i, rect_count;
     511                 : 
     512                 :     /* we only treat this a hint... */
     513               0 :     if (! traps->maybe_region)
     514               0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
     515                 : 
     516               0 :     for (i = 0; i < traps->num_traps; i++) {
     517               0 :         if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x   ||
     518               0 :             traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
     519               0 :             ! _cairo_fixed_is_integer (traps->traps[i].top)          ||
     520               0 :             ! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
     521               0 :             ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
     522               0 :             ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
     523                 :         {
     524               0 :             traps->maybe_region = FALSE;
     525               0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
     526                 :         }
     527                 :     }
     528                 : 
     529               0 :     if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
     530               0 :         rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t));
     531                 : 
     532               0 :         if (unlikely (rects == NULL))
     533               0 :             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     534                 :     }
     535                 : 
     536               0 :     rect_count = 0;
     537               0 :     for (i = 0; i < traps->num_traps; i++) {
     538               0 :         int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
     539               0 :         int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
     540               0 :         int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
     541               0 :         int y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
     542                 : 
     543               0 :         rects[rect_count].x = x1;
     544               0 :         rects[rect_count].y = y1;
     545               0 :         rects[rect_count].width = x2 - x1;
     546               0 :         rects[rect_count].height = y2 - y1;
     547                 : 
     548               0 :         rect_count++;
     549                 :     }
     550                 : 
     551               0 :     *region = cairo_region_create_rectangles (rects, rect_count);
     552               0 :     status = (*region)->status;
     553                 : 
     554               0 :     if (rects != stack_rects)
     555               0 :         free (rects);
     556                 : 
     557               0 :     return status;
     558                 : }
     559                 : 
     560                 : /* moves trap points such that they become the actual corners of the trapezoid */
     561                 : static void
     562               0 : _sanitize_trap (cairo_trapezoid_t *t)
     563                 : {
     564               0 :     cairo_trapezoid_t s = *t;
     565                 : 
     566                 : #define FIX(lr, tb, p) \
     567                 :     if (t->lr.p.y != t->tb) { \
     568                 :         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); \
     569                 :         t->lr.p.y = s.tb; \
     570                 :     }
     571               0 :     FIX (left,  top,    p1);
     572               0 :     FIX (left,  bottom, p2);
     573               0 :     FIX (right, top,    p1);
     574               0 :     FIX (right, bottom, p2);
     575               0 : }
     576                 : 
     577                 : cairo_private cairo_status_t
     578               0 : _cairo_traps_path (const cairo_traps_t *traps,
     579                 :                    cairo_path_fixed_t  *path)
     580                 : {
     581                 :     int i;
     582                 : 
     583               0 :     for (i = 0; i < traps->num_traps; i++) {
     584                 :         cairo_status_t status;
     585               0 :         cairo_trapezoid_t trap = traps->traps[i];
     586                 : 
     587               0 :         if (trap.top == trap.bottom)
     588               0 :             continue;
     589                 : 
     590               0 :         _sanitize_trap (&trap);
     591                 : 
     592               0 :         status = _cairo_path_fixed_move_to (path, trap.left.p1.x, trap.top);
     593               0 :         if (unlikely (status)) return status;
     594               0 :         status = _cairo_path_fixed_line_to (path, trap.right.p1.x, trap.top);
     595               0 :         if (unlikely (status)) return status;
     596               0 :         status = _cairo_path_fixed_line_to (path, trap.right.p2.x, trap.bottom);
     597               0 :         if (unlikely (status)) return status;
     598               0 :         status = _cairo_path_fixed_line_to (path, trap.left.p2.x, trap.bottom);
     599               0 :         if (unlikely (status)) return status;
     600               0 :         status = _cairo_path_fixed_close_path (path);
     601               0 :         if (unlikely (status)) return status;
     602                 :     }
     603                 : 
     604               0 :     return CAIRO_STATUS_SUCCESS;
     605                 : }

Generated by: LCOV version 1.7