1
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2011 Intel Corporation
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 University of Southern
32
 * California.
33
 *
34
 * Contributor(s):
35
 *	Chris Wilson <chris@chris-wilson.co.uk>
36
 */
37

            
38
#include "cairoint.h"
39
#include "cairo-clip-inline.h"
40
#include "cairo-clip-private.h"
41
#include "cairo-error-private.h"
42
#include "cairo-freed-pool-private.h"
43
#include "cairo-gstate-private.h"
44
#include "cairo-path-fixed-private.h"
45
#include "cairo-pattern-private.h"
46
#include "cairo-composite-rectangles-private.h"
47
#include "cairo-region-private.h"
48

            
49
static cairo_bool_t
50
2757
can_convert_to_polygon (const cairo_clip_t *clip)
51
{
52
2757
    cairo_clip_path_t *clip_path = clip->path;
53
2757
    cairo_antialias_t antialias = clip_path->antialias;
54

            
55
3036
    while ((clip_path = clip_path->prev) != NULL) {
56
285
	if (clip_path->antialias != antialias)
57
6
	    return FALSE;
58
    }
59

            
60
2751
    return TRUE;
61
}
62

            
63
cairo_int_status_t
64
2835
_cairo_clip_get_polygon (const cairo_clip_t *clip,
65
			 cairo_polygon_t *polygon,
66
			 cairo_fill_rule_t *fill_rule,
67
			 cairo_antialias_t *antialias)
68
{
69
    cairo_status_t status;
70
    cairo_clip_path_t *clip_path;
71

            
72
2835
    if (_cairo_clip_is_all_clipped (clip)) {
73
	_cairo_polygon_init (polygon, NULL, 0);
74
	return CAIRO_INT_STATUS_SUCCESS;
75
    }
76

            
77
    /* If there is no clip, we need an infinite polygon */
78
2835
    assert (clip && (clip->path || clip->num_boxes));
79

            
80
2835
    if (clip->path == NULL) {
81
78
	*fill_rule = CAIRO_FILL_RULE_WINDING;
82
78
	*antialias = CAIRO_ANTIALIAS_DEFAULT;
83
78
	return _cairo_polygon_init_box_array (polygon,
84
78
					      clip->boxes,
85
78
					      clip->num_boxes);
86
    }
87

            
88
    /* check that residual is all of the same type/tolerance */
89
2757
    if (! can_convert_to_polygon (clip))
90
6
	return CAIRO_INT_STATUS_UNSUPPORTED;
91

            
92
2751
    if (clip->num_boxes < 2)
93
2691
	_cairo_polygon_init_with_clip (polygon, clip);
94
    else
95
60
	_cairo_polygon_init_with_clip (polygon, NULL);
96

            
97
2751
    clip_path = clip->path;
98
2751
    *fill_rule = clip_path->fill_rule;
99
2751
    *antialias = clip_path->antialias;
100

            
101
2751
    status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
102
						clip_path->tolerance,
103
						polygon);
104
2751
    if (unlikely (status))
105
	goto err;
106

            
107
2751
    if (clip->num_boxes > 1) {
108
60
	status = _cairo_polygon_intersect_with_boxes (polygon, fill_rule,
109
60
						      clip->boxes, clip->num_boxes);
110
60
	if (unlikely (status))
111
	    goto err;
112
    }
113

            
114
2751
    polygon->limits = NULL;
115
2751
    polygon->num_limits = 0;
116

            
117
3030
    while ((clip_path = clip_path->prev) != NULL) {
118
	cairo_polygon_t next;
119

            
120
279
	_cairo_polygon_init (&next, NULL, 0);
121
279
	status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
122
						    clip_path->tolerance,
123
						    &next);
124
279
	if (likely (status == CAIRO_STATUS_SUCCESS))
125
279
		status = _cairo_polygon_intersect (polygon, *fill_rule,
126
279
						   &next, clip_path->fill_rule);
127
279
	_cairo_polygon_fini (&next);
128
279
	if (unlikely (status))
129
	    goto err;
130

            
131
279
	*fill_rule = CAIRO_FILL_RULE_WINDING;
132
    }
133

            
134
2751
    return CAIRO_STATUS_SUCCESS;
135

            
136
err:
137
    _cairo_polygon_fini (polygon);
138
    return status;
139
}
140

            
141
cairo_bool_t
142
_cairo_clip_is_polygon (const cairo_clip_t *clip)
143
{
144
    if (_cairo_clip_is_all_clipped (clip))
145
	return TRUE;
146

            
147
    /* If there is no clip, we need an infinite polygon */
148
    if (clip == NULL)
149
	return FALSE;
150

            
151
    if (clip->path == NULL)
152
	return TRUE;
153

            
154
    /* check that residual is all of the same type/tolerance */
155
    return can_convert_to_polygon (clip);
156
}