diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2015-12-28 11:39:07 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2015-12-28 11:39:07 +0000 |
commit | 28d16176960e908983aaa3926faddc374209de78 (patch) | |
tree | 3ad556334d7beeed199f153a3d75d5cd751f5943 /Build/source/libs/cairo/cairo-1.14.2/src/cairo-traps.c | |
parent | d2839bee530ce6b3a1639eb29947aa8ec07cf469 (diff) |
cairo-1.14.6
git-svn-id: svn://tug.org/texlive/trunk@39210 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/cairo/cairo-1.14.2/src/cairo-traps.c')
-rw-r--r-- | Build/source/libs/cairo/cairo-1.14.2/src/cairo-traps.c | 1123 |
1 files changed, 0 insertions, 1123 deletions
diff --git a/Build/source/libs/cairo/cairo-1.14.2/src/cairo-traps.c b/Build/source/libs/cairo/cairo-1.14.2/src/cairo-traps.c deleted file mode 100644 index 3aa0052f91f..00000000000 --- a/Build/source/libs/cairo/cairo-1.14.2/src/cairo-traps.c +++ /dev/null @@ -1,1123 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* - * Copyright © 2002 Keith Packard - * Copyright © 2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Keith Packard - * - * Contributor(s): - * Keith R. Packard <keithp@keithp.com> - * Carl D. Worth <cworth@cworth.org> - * - * 2002-07-15: Converted from XRenderCompositeDoublePoly to #cairo_trap_t. Carl D. Worth - */ - -#include "cairoint.h" - -#include "cairo-box-inline.h" -#include "cairo-boxes-private.h" -#include "cairo-error-private.h" -#include "cairo-line-private.h" -#include "cairo-region-private.h" -#include "cairo-slope-private.h" -#include "cairo-traps-private.h" -#include "cairo-spans-private.h" - -/* private functions */ - -void -_cairo_traps_init (cairo_traps_t *traps) -{ - VG (VALGRIND_MAKE_MEM_UNDEFINED (traps, sizeof (cairo_traps_t))); - - traps->status = CAIRO_STATUS_SUCCESS; - - traps->maybe_region = 1; - traps->is_rectilinear = 0; - traps->is_rectangular = 0; - - traps->num_traps = 0; - - traps->traps_size = ARRAY_LENGTH (traps->traps_embedded); - traps->traps = traps->traps_embedded; - - traps->num_limits = 0; - traps->has_intersections = FALSE; -} - -void -_cairo_traps_limit (cairo_traps_t *traps, - const cairo_box_t *limits, - int num_limits) -{ - int i; - - traps->limits = limits; - traps->num_limits = num_limits; - - traps->bounds = limits[0]; - for (i = 1; i < num_limits; i++) - _cairo_box_add_box (&traps->bounds, &limits[i]); -} - -void -_cairo_traps_init_with_clip (cairo_traps_t *traps, - const cairo_clip_t *clip) -{ - _cairo_traps_init (traps); - if (clip) - _cairo_traps_limit (traps, clip->boxes, clip->num_boxes); -} - -void -_cairo_traps_clear (cairo_traps_t *traps) -{ - traps->status = CAIRO_STATUS_SUCCESS; - - traps->maybe_region = 1; - traps->is_rectilinear = 0; - traps->is_rectangular = 0; - - traps->num_traps = 0; - traps->has_intersections = FALSE; -} - -void -_cairo_traps_fini (cairo_traps_t *traps) -{ - if (traps->traps != traps->traps_embedded) - free (traps->traps); - - VG (VALGRIND_MAKE_MEM_NOACCESS (traps, sizeof (cairo_traps_t))); -} - -/* make room for at least one more trap */ -static cairo_bool_t -_cairo_traps_grow (cairo_traps_t *traps) -{ - cairo_trapezoid_t *new_traps; - int new_size = 4 * traps->traps_size; - - if (CAIRO_INJECT_FAULT ()) { - traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return FALSE; - } - - if (traps->traps == traps->traps_embedded) { - new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t)); - if (new_traps != NULL) - memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded)); - } else { - new_traps = _cairo_realloc_ab (traps->traps, - new_size, sizeof (cairo_trapezoid_t)); - } - - if (unlikely (new_traps == NULL)) { - traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return FALSE; - } - - traps->traps = new_traps; - traps->traps_size = new_size; - return TRUE; -} - -void -_cairo_traps_add_trap (cairo_traps_t *traps, - cairo_fixed_t top, cairo_fixed_t bottom, - const cairo_line_t *left, - const cairo_line_t *right) -{ - cairo_trapezoid_t *trap; - - assert (left->p1.y != left->p2.y); - assert (right->p1.y != right->p2.y); - assert (bottom > top); - - if (unlikely (traps->num_traps == traps->traps_size)) { - if (unlikely (! _cairo_traps_grow (traps))) - return; - } - - trap = &traps->traps[traps->num_traps++]; - trap->top = top; - trap->bottom = bottom; - trap->left = *left; - trap->right = *right; -} - -static void -_cairo_traps_add_clipped_trap (cairo_traps_t *traps, - cairo_fixed_t _top, cairo_fixed_t _bottom, - const cairo_line_t *_left, - const cairo_line_t *_right) -{ - /* Note: With the goofy trapezoid specification, (where an - * arbitrary two points on the lines can specified for the left - * and right edges), these limit checks would not work in - * general. For example, one can imagine a trapezoid entirely - * within the limits, but with two points used to specify the left - * edge entirely to the right of the limits. Fortunately, for our - * purposes, cairo will never generate such a crazy - * trapezoid. Instead, cairo always uses for its points the - * extreme positions of the edge that are visible on at least some - * trapezoid. With this constraint, it's impossible for both - * points to be outside the limits while the relevant edge is - * entirely inside the limits. - */ - if (traps->num_limits) { - const cairo_box_t *b = &traps->bounds; - cairo_fixed_t top = _top, bottom = _bottom; - cairo_line_t left = *_left, right = *_right; - - /* Trivially reject if trapezoid is entirely to the right or - * to the left of the limits. */ - if (left.p1.x >= b->p2.x && left.p2.x >= b->p2.x) - return; - - if (right.p1.x <= b->p1.x && right.p2.x <= b->p1.x) - return; - - /* And reject if the trapezoid is entirely above or below */ - if (top >= b->p2.y || bottom <= b->p1.y) - return; - - /* Otherwise, clip the trapezoid to the limits. We only clip - * where an edge is entirely outside the limits. If we wanted - * to be more clever, we could handle cases where a trapezoid - * edge intersects the edge of the limits, but that would - * require slicing this trapezoid into multiple trapezoids, - * and I'm not sure the effort would be worth it. */ - if (top < b->p1.y) - top = b->p1.y; - - if (bottom > b->p2.y) - bottom = b->p2.y; - - if (left.p1.x <= b->p1.x && left.p2.x <= b->p1.x) - left.p1.x = left.p2.x = b->p1.x; - - if (right.p1.x >= b->p2.x && right.p2.x >= b->p2.x) - right.p1.x = right.p2.x = b->p2.x; - - /* Trivial discards for empty trapezoids that are likely to - * be produced by our tessellators (most notably convex_quad - * when given a simple rectangle). - */ - if (top >= bottom) - return; - - /* cheap colinearity check */ - if (right.p1.x <= left.p1.x && right.p1.y == left.p1.y && - right.p2.x <= left.p2.x && right.p2.y == left.p2.y) - return; - - _cairo_traps_add_trap (traps, top, bottom, &left, &right); - } else - _cairo_traps_add_trap (traps, _top, _bottom, _left, _right); -} - -static int -_compare_point_fixed_by_y (const void *av, const void *bv) -{ - const cairo_point_t *a = av, *b = bv; - int ret = a->y - b->y; - if (ret == 0) - ret = a->x - b->x; - return ret; -} - -void -_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, - const cairo_point_t q[4]) -{ - int a, b, c, d; - int i; - cairo_slope_t ab, ad; - cairo_bool_t b_left_of_d; - cairo_line_t left; - cairo_line_t right; - - /* Choose a as a point with minimal y */ - a = 0; - for (i = 1; i < 4; i++) - if (_compare_point_fixed_by_y (&q[i], &q[a]) < 0) - a = i; - - /* b and d are adjacent to a, while c is opposite */ - b = (a + 1) % 4; - c = (a + 2) % 4; - d = (a + 3) % 4; - - /* Choose between b and d so that b.y is less than d.y */ - if (_compare_point_fixed_by_y (&q[d], &q[b]) < 0) { - b = (a + 3) % 4; - d = (a + 1) % 4; - } - - /* Without freedom left to choose anything else, we have four - * cases to tessellate. - * - * First, we have to determine the Y-axis sort of the four - * vertices, (either abcd or abdc). After that we need to detemine - * which edges will be "left" and which will be "right" in the - * resulting trapezoids. This can be determined by computing a - * slope comparison of ab and ad to determine if b is left of d or - * not. - * - * Note that "left of" here is in the sense of which edges should - * be the left vs. right edges of the trapezoid. In particular, b - * left of d does *not* mean that b.x is less than d.x. - * - * This should hopefully be made clear in the lame ASCII art - * below. Since the same slope comparison is used in all cases, we - * compute it before testing for the Y-value sort. */ - - /* Note: If a == b then the ab slope doesn't give us any - * information. In that case, we can replace it with the ac (or - * equivalenly the bc) slope which gives us exactly the same - * information we need. At worst the names of the identifiers ab - * and b_left_of_d are inaccurate in this case, (would be ac, and - * c_left_of_d). */ - if (q[a].x == q[b].x && q[a].y == q[b].y) - _cairo_slope_init (&ab, &q[a], &q[c]); - else - _cairo_slope_init (&ab, &q[a], &q[b]); - - _cairo_slope_init (&ad, &q[a], &q[d]); - - b_left_of_d = _cairo_slope_compare (&ab, &ad) > 0; - - if (q[c].y <= q[d].y) { - if (b_left_of_d) { - /* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad)) - * - * top bot left right - * _a a a - * / / /| |\ a.y b.y ab ad - * b / b | b \ - * / / | | \ \ b.y c.y bc ad - * c / c | c \ - * | / \| \ \ c.y d.y cd ad - * d d d - */ - left.p1 = q[a]; left.p2 = q[b]; - right.p1 = q[a]; right.p2 = q[d]; - _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right); - left.p1 = q[b]; left.p2 = q[c]; - _cairo_traps_add_clipped_trap (traps, q[b].y, q[c].y, &left, &right); - left.p1 = q[c]; left.p2 = q[d]; - _cairo_traps_add_clipped_trap (traps, q[c].y, q[d].y, &left, &right); - } else { - /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad)) - * - * a a a_ - * /| |\ \ \ a.y b.y ad ab - * / b | b \ b - * / / | | \ \ b.y c.y ad bc - * / c | c \ c - * / / |/ \ | c.y d.y ad cd - * d d d - */ - left.p1 = q[a]; left.p2 = q[d]; - right.p1 = q[a]; right.p2 = q[b]; - _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right); - right.p1 = q[b]; right.p2 = q[c]; - _cairo_traps_add_clipped_trap (traps, q[b].y, q[c].y, &left, &right); - right.p1 = q[c]; right.p2 = q[d]; - _cairo_traps_add_clipped_trap (traps, q[c].y, q[d].y, &left, &right); - } - } else { - if (b_left_of_d) { - /* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad)) - * - * a a a - * // / \ |\ a.y b.y ab ad - * /b/ b \ b \ - * / / \ \ \ \ b.y d.y bc ad - * /d/ \ d \ d - * // \ / \| d.y c.y bc dc - * c c c - */ - left.p1 = q[a]; left.p2 = q[b]; - right.p1 = q[a]; right.p2 = q[d]; - _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right); - left.p1 = q[b]; left.p2 = q[c]; - _cairo_traps_add_clipped_trap (traps, q[b].y, q[d].y, &left, &right); - right.p1 = q[d]; right.p2 = q[c]; - _cairo_traps_add_clipped_trap (traps, q[d].y, q[c].y, &left, &right); - } else { - /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad)) - * - * a a a - * /| / \ \\ a.y b.y ad ab - * / b / b \b\ - * / / / / \ \ b.y d.y ad bc - * d / d / \d\ - * |/ \ / \\ d.y c.y dc bc - * c c c - */ - left.p1 = q[a]; left.p2 = q[d]; - right.p1 = q[a]; right.p2 = q[b]; - _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right); - right.p1 = q[b]; right.p2 = q[c]; - _cairo_traps_add_clipped_trap (traps, q[b].y, q[d].y, &left, &right); - left.p1 = q[d]; left.p2 = q[c]; - _cairo_traps_add_clipped_trap (traps, q[d].y, q[c].y, &left, &right); - } - } -} - -static void add_tri (cairo_traps_t *traps, - int y1, int y2, - const cairo_line_t *left, - const cairo_line_t *right) -{ - if (y2 < y1) { - int tmp = y1; - y1 = y2; - y2 = tmp; - } - - if (cairo_lines_compare_at_y (left, right, y1) > 0) { - const cairo_line_t *tmp = left; - left = right; - right = tmp; - } - - _cairo_traps_add_clipped_trap (traps, y1, y2, left, right); -} - -void -_cairo_traps_tessellate_triangle_with_edges (cairo_traps_t *traps, - const cairo_point_t t[3], - const cairo_point_t edges[4]) -{ - cairo_line_t lines[3]; - - if (edges[0].y <= edges[1].y) { - lines[0].p1 = edges[0]; - lines[0].p2 = edges[1]; - } else { - lines[0].p1 = edges[1]; - lines[0].p2 = edges[0]; - } - - if (edges[2].y <= edges[3].y) { - lines[1].p1 = edges[2]; - lines[1].p2 = edges[3]; - } else { - lines[1].p1 = edges[3]; - lines[1].p2 = edges[2]; - } - - if (t[1].y == t[2].y) { - add_tri (traps, t[0].y, t[1].y, &lines[0], &lines[1]); - return; - } - - if (t[1].y <= t[2].y) { - lines[2].p1 = t[1]; - lines[2].p2 = t[2]; - } else { - lines[2].p1 = t[2]; - lines[2].p2 = t[1]; - } - - if (((t[1].y - t[0].y) < 0) ^ ((t[2].y - t[0].y) < 0)) { - add_tri (traps, t[0].y, t[1].y, &lines[0], &lines[2]); - add_tri (traps, t[0].y, t[2].y, &lines[1], &lines[2]); - } else if (abs(t[1].y - t[0].y) < abs(t[2].y - t[0].y)) { - add_tri (traps, t[0].y, t[1].y, &lines[0], &lines[1]); - add_tri (traps, t[1].y, t[2].y, &lines[2], &lines[1]); - } else { - add_tri (traps, t[0].y, t[2].y, &lines[1], &lines[0]); - add_tri (traps, t[1].y, t[2].y, &lines[2], &lines[0]); - } -} - -/** - * _cairo_traps_init_boxes: - * @traps: a #cairo_traps_t - * @box: an array box that will each be converted to a single trapezoid - * to store in @traps. - * - * Initializes a #cairo_traps_t to contain an array of rectangular - * trapezoids. - **/ -cairo_status_t -_cairo_traps_init_boxes (cairo_traps_t *traps, - const cairo_boxes_t *boxes) -{ - cairo_trapezoid_t *trap; - const struct _cairo_boxes_chunk *chunk; - - _cairo_traps_init (traps); - - while (traps->traps_size < boxes->num_boxes) { - if (unlikely (! _cairo_traps_grow (traps))) { - _cairo_traps_fini (traps); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } - - traps->num_traps = boxes->num_boxes; - traps->is_rectilinear = TRUE; - traps->is_rectangular = TRUE; - traps->maybe_region = boxes->is_pixel_aligned; - - trap = &traps->traps[0]; - for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { - const cairo_box_t *box; - int i; - - box = chunk->base; - for (i = 0; i < chunk->count; i++) { - trap->top = box->p1.y; - trap->bottom = box->p2.y; - - trap->left.p1 = box->p1; - trap->left.p2.x = box->p1.x; - trap->left.p2.y = box->p2.y; - - trap->right.p1.x = box->p2.x; - trap->right.p1.y = box->p1.y; - trap->right.p2 = box->p2; - - box++, trap++; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_traps_tessellate_rectangle (cairo_traps_t *traps, - const cairo_point_t *top_left, - const cairo_point_t *bottom_right) -{ - cairo_line_t left; - cairo_line_t right; - cairo_fixed_t top, bottom; - - if (top_left->y == bottom_right->y) - return CAIRO_STATUS_SUCCESS; - - if (top_left->x == bottom_right->x) - return CAIRO_STATUS_SUCCESS; - - left.p1.x = left.p2.x = top_left->x; - left.p1.y = right.p1.y = top_left->y; - right.p1.x = right.p2.x = bottom_right->x; - left.p2.y = right.p2.y = bottom_right->y; - - top = top_left->y; - bottom = bottom_right->y; - - if (traps->num_limits) { - cairo_bool_t reversed; - int n; - - if (top >= traps->bounds.p2.y || bottom <= traps->bounds.p1.y) - return CAIRO_STATUS_SUCCESS; - - /* support counter-clockwise winding for rectangular tessellation */ - reversed = top_left->x > bottom_right->x; - if (reversed) { - right.p1.x = right.p2.x = top_left->x; - left.p1.x = left.p2.x = bottom_right->x; - } - - if (left.p1.x >= traps->bounds.p2.x || right.p1.x <= traps->bounds.p1.x) - return CAIRO_STATUS_SUCCESS; - - for (n = 0; n < traps->num_limits; n++) { - const cairo_box_t *limits = &traps->limits[n]; - cairo_line_t _left, _right; - cairo_fixed_t _top, _bottom; - - if (top >= limits->p2.y) - continue; - if (bottom <= limits->p1.y) - continue; - - /* Trivially reject if trapezoid is entirely to the right or - * to the left of the limits. */ - if (left.p1.x >= limits->p2.x) - continue; - if (right.p1.x <= limits->p1.x) - continue; - - /* Otherwise, clip the trapezoid to the limits. */ - _top = top; - if (_top < limits->p1.y) - _top = limits->p1.y; - - _bottom = bottom; - if (_bottom > limits->p2.y) - _bottom = limits->p2.y; - - if (_bottom <= _top) - continue; - - _left = left; - if (_left.p1.x < limits->p1.x) { - _left.p1.x = limits->p1.x; - _left.p1.y = limits->p1.y; - _left.p2.x = limits->p1.x; - _left.p2.y = limits->p2.y; - } - - _right = right; - if (_right.p1.x > limits->p2.x) { - _right.p1.x = limits->p2.x; - _right.p1.y = limits->p1.y; - _right.p2.x = limits->p2.x; - _right.p2.y = limits->p2.y; - } - - if (left.p1.x >= right.p1.x) - continue; - - if (reversed) - _cairo_traps_add_trap (traps, _top, _bottom, &_right, &_left); - else - _cairo_traps_add_trap (traps, _top, _bottom, &_left, &_right); - } - } else { - _cairo_traps_add_trap (traps, top, bottom, &left, &right); - } - - return traps->status; -} - -void -_cairo_traps_translate (cairo_traps_t *traps, int x, int y) -{ - cairo_fixed_t xoff, yoff; - cairo_trapezoid_t *t; - int i; - - /* Ugh. The cairo_composite/(Render) interface doesn't allow - an offset for the trapezoids. Need to manually shift all - the coordinates to align with the offset origin of the - intermediate surface. */ - - xoff = _cairo_fixed_from_int (x); - yoff = _cairo_fixed_from_int (y); - - for (i = 0, t = traps->traps; i < traps->num_traps; i++, t++) { - t->top += yoff; - t->bottom += yoff; - t->left.p1.x += xoff; - t->left.p1.y += yoff; - t->left.p2.x += xoff; - t->left.p2.y += yoff; - t->right.p1.x += xoff; - t->right.p1.y += yoff; - t->right.p2.x += xoff; - t->right.p2.y += yoff; - } -} - -void -_cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps, - cairo_trapezoid_t *src_traps, - int num_traps, - double tx, double ty, - double sx, double sy) -{ - int i; - cairo_fixed_t xoff = _cairo_fixed_from_double (tx); - cairo_fixed_t yoff = _cairo_fixed_from_double (ty); - - if (sx == 1.0 && sy == 1.0) { - for (i = 0; i < num_traps; i++) { - offset_traps[i].top = src_traps[i].top + yoff; - offset_traps[i].bottom = src_traps[i].bottom + yoff; - offset_traps[i].left.p1.x = src_traps[i].left.p1.x + xoff; - offset_traps[i].left.p1.y = src_traps[i].left.p1.y + yoff; - offset_traps[i].left.p2.x = src_traps[i].left.p2.x + xoff; - offset_traps[i].left.p2.y = src_traps[i].left.p2.y + yoff; - offset_traps[i].right.p1.x = src_traps[i].right.p1.x + xoff; - offset_traps[i].right.p1.y = src_traps[i].right.p1.y + yoff; - offset_traps[i].right.p2.x = src_traps[i].right.p2.x + xoff; - offset_traps[i].right.p2.y = src_traps[i].right.p2.y + yoff; - } - } else { - cairo_fixed_t xsc = _cairo_fixed_from_double (sx); - cairo_fixed_t ysc = _cairo_fixed_from_double (sy); - - for (i = 0; i < num_traps; i++) { - offset_traps[i].top = _cairo_fixed_mul (src_traps[i].top + yoff, ysc); - offset_traps[i].bottom = _cairo_fixed_mul (src_traps[i].bottom + yoff, ysc); - offset_traps[i].left.p1.x = _cairo_fixed_mul (src_traps[i].left.p1.x + xoff, xsc); - offset_traps[i].left.p1.y = _cairo_fixed_mul (src_traps[i].left.p1.y + yoff, ysc); - offset_traps[i].left.p2.x = _cairo_fixed_mul (src_traps[i].left.p2.x + xoff, xsc); - offset_traps[i].left.p2.y = _cairo_fixed_mul (src_traps[i].left.p2.y + yoff, ysc); - offset_traps[i].right.p1.x = _cairo_fixed_mul (src_traps[i].right.p1.x + xoff, xsc); - offset_traps[i].right.p1.y = _cairo_fixed_mul (src_traps[i].right.p1.y + yoff, ysc); - offset_traps[i].right.p2.x = _cairo_fixed_mul (src_traps[i].right.p2.x + xoff, xsc); - offset_traps[i].right.p2.y = _cairo_fixed_mul (src_traps[i].right.p2.y + yoff, ysc); - } - } -} - -static cairo_bool_t -_cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt) -{ - cairo_slope_t slope_left, slope_pt, slope_right; - - if (t->top > pt->y) - return FALSE; - if (t->bottom < pt->y) - return FALSE; - - _cairo_slope_init (&slope_left, &t->left.p1, &t->left.p2); - _cairo_slope_init (&slope_pt, &t->left.p1, pt); - - if (_cairo_slope_compare (&slope_left, &slope_pt) < 0) - return FALSE; - - _cairo_slope_init (&slope_right, &t->right.p1, &t->right.p2); - _cairo_slope_init (&slope_pt, &t->right.p1, pt); - - if (_cairo_slope_compare (&slope_pt, &slope_right) < 0) - return FALSE; - - return TRUE; -} - -cairo_bool_t -_cairo_traps_contain (const cairo_traps_t *traps, - double x, double y) -{ - int i; - cairo_point_t point; - - point.x = _cairo_fixed_from_double (x); - point.y = _cairo_fixed_from_double (y); - - for (i = 0; i < traps->num_traps; i++) { - if (_cairo_trap_contains (&traps->traps[i], &point)) - return TRUE; - } - - return FALSE; -} - -static cairo_fixed_t -_line_compute_intersection_x_for_y (const cairo_line_t *line, - cairo_fixed_t y) -{ - return _cairo_edge_compute_intersection_x_for_y (&line->p1, &line->p2, y); -} - -void -_cairo_traps_extents (const cairo_traps_t *traps, - cairo_box_t *extents) -{ - int i; - - if (traps->num_traps == 0) { - extents->p1.x = extents->p1.y = 0; - extents->p2.x = extents->p2.y = 0; - return; - } - - extents->p1.x = extents->p1.y = INT32_MAX; - extents->p2.x = extents->p2.y = INT32_MIN; - - for (i = 0; i < traps->num_traps; i++) { - const cairo_trapezoid_t *trap = &traps->traps[i]; - - if (trap->top < extents->p1.y) - extents->p1.y = trap->top; - if (trap->bottom > extents->p2.y) - extents->p2.y = trap->bottom; - - if (trap->left.p1.x < extents->p1.x) { - cairo_fixed_t x = trap->left.p1.x; - if (trap->top != trap->left.p1.y) { - x = _line_compute_intersection_x_for_y (&trap->left, - trap->top); - if (x < extents->p1.x) - extents->p1.x = x; - } else - extents->p1.x = x; - } - if (trap->left.p2.x < extents->p1.x) { - cairo_fixed_t x = trap->left.p2.x; - if (trap->bottom != trap->left.p2.y) { - x = _line_compute_intersection_x_for_y (&trap->left, - trap->bottom); - if (x < extents->p1.x) - extents->p1.x = x; - } else - extents->p1.x = x; - } - - if (trap->right.p1.x > extents->p2.x) { - cairo_fixed_t x = trap->right.p1.x; - if (trap->top != trap->right.p1.y) { - x = _line_compute_intersection_x_for_y (&trap->right, - trap->top); - if (x > extents->p2.x) - extents->p2.x = x; - } else - extents->p2.x = x; - } - if (trap->right.p2.x > extents->p2.x) { - cairo_fixed_t x = trap->right.p2.x; - if (trap->bottom != trap->right.p2.y) { - x = _line_compute_intersection_x_for_y (&trap->right, - trap->bottom); - if (x > extents->p2.x) - extents->p2.x = x; - } else - extents->p2.x = x; - } - } -} - -static cairo_bool_t -_mono_edge_is_vertical (const cairo_line_t *line) -{ - return _cairo_fixed_integer_round_down (line->p1.x) == _cairo_fixed_integer_round_down (line->p2.x); -} - -static cairo_bool_t -_traps_are_pixel_aligned (cairo_traps_t *traps, - cairo_antialias_t antialias) -{ - int i; - - if (antialias == CAIRO_ANTIALIAS_NONE) { - for (i = 0; i < traps->num_traps; i++) { - if (! _mono_edge_is_vertical (&traps->traps[i].left) || - ! _mono_edge_is_vertical (&traps->traps[i].right)) - { - traps->maybe_region = FALSE; - return FALSE; - } - } - } else { - for (i = 0; i < traps->num_traps; i++) { - if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x || - traps->traps[i].right.p1.x != traps->traps[i].right.p2.x || - ! _cairo_fixed_is_integer (traps->traps[i].top) || - ! _cairo_fixed_is_integer (traps->traps[i].bottom) || - ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x) || - ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x)) - { - traps->maybe_region = FALSE; - return FALSE; - } - } - } - - return TRUE; -} - -/** - * _cairo_traps_extract_region: - * @traps: a #cairo_traps_t - * @region: a #cairo_region_t - * - * Determines if a set of trapezoids are exactly representable as a - * cairo region. If so, the passed-in region is initialized to - * the area representing the given traps. It should be finalized - * with cairo_region_fini(). If not, %CAIRO_INT_STATUS_UNSUPPORTED - * is returned. - * - * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED - * or %CAIRO_STATUS_NO_MEMORY - **/ -cairo_int_status_t -_cairo_traps_extract_region (cairo_traps_t *traps, - cairo_antialias_t antialias, - cairo_region_t **region) -{ - cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)]; - cairo_rectangle_int_t *rects = stack_rects; - cairo_int_status_t status; - int i, rect_count; - - /* we only treat this a hint... */ - if (antialias != CAIRO_ANTIALIAS_NONE && ! traps->maybe_region) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _traps_are_pixel_aligned (traps, antialias)) { - traps->maybe_region = FALSE; - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - if (traps->num_traps > ARRAY_LENGTH (stack_rects)) { - rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t)); - - if (unlikely (rects == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - rect_count = 0; - for (i = 0; i < traps->num_traps; i++) { - int x1, y1, x2, y2; - - if (antialias == CAIRO_ANTIALIAS_NONE) { - x1 = _cairo_fixed_integer_round_down (traps->traps[i].left.p1.x); - y1 = _cairo_fixed_integer_round_down (traps->traps[i].top); - x2 = _cairo_fixed_integer_round_down (traps->traps[i].right.p1.x); - y2 = _cairo_fixed_integer_round_down (traps->traps[i].bottom); - } else { - x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x); - y1 = _cairo_fixed_integer_part (traps->traps[i].top); - x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x); - y2 = _cairo_fixed_integer_part (traps->traps[i].bottom); - } - - if (x2 > x1 && y2 > y1) { - rects[rect_count].x = x1; - rects[rect_count].y = y1; - rects[rect_count].width = x2 - x1; - rects[rect_count].height = y2 - y1; - rect_count++; - } - } - - - *region = cairo_region_create_rectangles (rects, rect_count); - status = (*region)->status; - - if (rects != stack_rects) - free (rects); - - return status; -} - -cairo_bool_t -_cairo_traps_to_boxes (cairo_traps_t *traps, - cairo_antialias_t antialias, - cairo_boxes_t *boxes) -{ - int i; - - for (i = 0; i < traps->num_traps; i++) { - if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x || - traps->traps[i].right.p1.x != traps->traps[i].right.p2.x) - return FALSE; - } - - _cairo_boxes_init (boxes); - - boxes->num_boxes = traps->num_traps; - boxes->chunks.base = (cairo_box_t *) traps->traps; - boxes->chunks.count = traps->num_traps; - boxes->chunks.size = traps->num_traps; - - if (antialias != CAIRO_ANTIALIAS_NONE) { - for (i = 0; i < traps->num_traps; i++) { - /* Note the traps and boxes alias so we need to take the local copies first. */ - cairo_fixed_t x1 = traps->traps[i].left.p1.x; - cairo_fixed_t x2 = traps->traps[i].right.p1.x; - cairo_fixed_t y1 = traps->traps[i].top; - cairo_fixed_t y2 = traps->traps[i].bottom; - - boxes->chunks.base[i].p1.x = x1; - boxes->chunks.base[i].p1.y = y1; - boxes->chunks.base[i].p2.x = x2; - boxes->chunks.base[i].p2.y = y2; - - if (boxes->is_pixel_aligned) { - boxes->is_pixel_aligned = - _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) && - _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2); - } - } - } else { - boxes->is_pixel_aligned = TRUE; - - for (i = 0; i < traps->num_traps; i++) { - /* Note the traps and boxes alias so we need to take the local copies first. */ - cairo_fixed_t x1 = traps->traps[i].left.p1.x; - cairo_fixed_t x2 = traps->traps[i].right.p1.x; - cairo_fixed_t y1 = traps->traps[i].top; - cairo_fixed_t y2 = traps->traps[i].bottom; - - /* round down here to match Pixman's behavior when using traps. */ - boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1); - boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1); - boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2); - boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2); - } - } - - return TRUE; -} - -/* moves trap points such that they become the actual corners of the trapezoid */ -static void -_sanitize_trap (cairo_trapezoid_t *t) -{ - cairo_trapezoid_t s = *t; - -#define FIX(lr, tb, p) \ - if (t->lr.p.y != t->tb) { \ - 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); \ - t->lr.p.y = s.tb; \ - } - FIX (left, top, p1); - FIX (left, bottom, p2); - FIX (right, top, p1); - FIX (right, bottom, p2); -} - -cairo_private cairo_status_t -_cairo_traps_path (const cairo_traps_t *traps, - cairo_path_fixed_t *path) -{ - int i; - - for (i = 0; i < traps->num_traps; i++) { - cairo_status_t status; - cairo_trapezoid_t trap = traps->traps[i]; - - if (trap.top == trap.bottom) - continue; - - _sanitize_trap (&trap); - - status = _cairo_path_fixed_move_to (path, trap.left.p1.x, trap.top); - if (unlikely (status)) return status; - status = _cairo_path_fixed_line_to (path, trap.right.p1.x, trap.top); - if (unlikely (status)) return status; - status = _cairo_path_fixed_line_to (path, trap.right.p2.x, trap.bottom); - if (unlikely (status)) return status; - status = _cairo_path_fixed_line_to (path, trap.left.p2.x, trap.bottom); - if (unlikely (status)) return status; - status = _cairo_path_fixed_close_path (path); - if (unlikely (status)) return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_debug_print_traps (FILE *file, const cairo_traps_t *traps) -{ - cairo_box_t extents; - int n; - -#if 0 - if (traps->has_limits) { - printf ("%s: limits=(%d, %d, %d, %d)\n", - filename, - traps->limits.p1.x, traps->limits.p1.y, - traps->limits.p2.x, traps->limits.p2.y); - } -#endif - - _cairo_traps_extents (traps, &extents); - fprintf (file, "extents=(%d, %d, %d, %d)\n", - extents.p1.x, extents.p1.y, - extents.p2.x, extents.p2.y); - - for (n = 0; n < traps->num_traps; n++) { - fprintf (file, "%d %d L:(%d, %d), (%d, %d) R:(%d, %d), (%d, %d)\n", - traps->traps[n].top, - traps->traps[n].bottom, - traps->traps[n].left.p1.x, - traps->traps[n].left.p1.y, - traps->traps[n].left.p2.x, - traps->traps[n].left.p2.y, - traps->traps[n].right.p1.x, - traps->traps[n].right.p1.y, - traps->traps[n].right.p2.x, - traps->traps[n].right.p2.y); - } -} - -struct cairo_trap_renderer { - cairo_span_renderer_t base; - cairo_traps_t *traps; -}; - -static cairo_status_t -span_to_traps (void *abstract_renderer, int y, int h, - const cairo_half_open_span_t *spans, unsigned num_spans) -{ - struct cairo_trap_renderer *r = abstract_renderer; - cairo_fixed_t top, bot; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - top = _cairo_fixed_from_int (y); - bot = _cairo_fixed_from_int (y + h); - do { - if (spans[0].coverage) { - cairo_fixed_t x0 = _cairo_fixed_from_int(spans[0].x); - cairo_fixed_t x1 = _cairo_fixed_from_int(spans[1].x); - cairo_line_t left = { { x0, top }, { x0, bot } }, - right = { { x1, top }, { x1, bot } }; - _cairo_traps_add_trap (r->traps, top, bot, &left, &right); - } - spans++; - } while (--num_spans > 1); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -_cairo_rasterise_polygon_to_traps (cairo_polygon_t *polygon, - cairo_fill_rule_t fill_rule, - cairo_antialias_t antialias, - cairo_traps_t *traps) -{ - struct cairo_trap_renderer renderer; - cairo_scan_converter_t *converter; - cairo_int_status_t status; - cairo_rectangle_int_t r; - - TRACE ((stderr, "%s: fill_rule=%d, antialias=%d\n", - __FUNCTION__, fill_rule, antialias)); - assert(antialias == CAIRO_ANTIALIAS_NONE); - - renderer.traps = traps; - renderer.base.render_rows = span_to_traps; - - _cairo_box_round_to_rectangle (&polygon->extents, &r); - converter = _cairo_mono_scan_converter_create (r.x, r.y, - r.x + r.width, - r.y + r.height, - fill_rule); - status = _cairo_mono_scan_converter_add_polygon (converter, polygon); - if (likely (status == CAIRO_INT_STATUS_SUCCESS)) - status = converter->generate (converter, &renderer.base); - converter->destroy (converter); - return status; -} |