summaryrefslogtreecommitdiff
path: root/Build/source/libs/cairo/cairo-1.14.2/src/cairo-traps.c
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2015-12-28 11:39:07 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2015-12-28 11:39:07 +0000
commit28d16176960e908983aaa3926faddc374209de78 (patch)
tree3ad556334d7beeed199f153a3d75d5cd751f5943 /Build/source/libs/cairo/cairo-1.14.2/src/cairo-traps.c
parentd2839bee530ce6b3a1639eb29947aa8ec07cf469 (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.c1123
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;
-}