beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-path-fill.c
blob4000c9c586ee24ae705402ba8cdf1e79bf3a8f3b
1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2002 University of Southern California
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.
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
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/
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.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is University of Southern
32 * California.
34 * Contributor(s):
35 * Carl D. Worth <cworth@cworth.org>
38 #include "cairoint.h"
39 #include "cairo-boxes-private.h"
40 #include "cairo-error-private.h"
41 #include "cairo-path-fixed-private.h"
42 #include "cairo-region-private.h"
43 #include "cairo-traps-private.h"
45 typedef struct cairo_filler {
46 cairo_polygon_t *polygon;
47 double tolerance;
49 cairo_box_t limit;
50 cairo_bool_t has_limits;
52 cairo_point_t current_point;
53 cairo_point_t last_move_to;
54 } cairo_filler_t;
56 static cairo_status_t
57 _cairo_filler_line_to (void *closure,
58 const cairo_point_t *point)
60 cairo_filler_t *filler = closure;
61 cairo_status_t status;
63 status = _cairo_polygon_add_external_edge (filler->polygon,
64 &filler->current_point,
65 point);
67 filler->current_point = *point;
69 return status;
72 static cairo_status_t
73 _cairo_filler_close (void *closure)
75 cairo_filler_t *filler = closure;
77 /* close the subpath */
78 return _cairo_filler_line_to (closure, &filler->last_move_to);
81 static cairo_status_t
82 _cairo_filler_move_to (void *closure,
83 const cairo_point_t *point)
85 cairo_filler_t *filler = closure;
86 cairo_status_t status;
88 /* close current subpath */
89 status = _cairo_filler_close (closure);
90 if (unlikely (status))
91 return status;
93 /* make sure that the closure represents a degenerate path */
94 filler->current_point = *point;
95 filler->last_move_to = *point;
97 return CAIRO_STATUS_SUCCESS;
100 static cairo_status_t
101 _cairo_filler_curve_to (void *closure,
102 const cairo_point_t *p1,
103 const cairo_point_t *p2,
104 const cairo_point_t *p3)
106 cairo_filler_t *filler = closure;
107 cairo_spline_t spline;
109 if (filler->has_limits) {
110 if (! _cairo_spline_intersects (&filler->current_point, p1, p2, p3,
111 &filler->limit))
112 return _cairo_filler_line_to (filler, p3);
115 if (! _cairo_spline_init (&spline,
116 (cairo_spline_add_point_func_t)_cairo_filler_line_to, filler,
117 &filler->current_point, p1, p2, p3))
119 return _cairo_filler_line_to (closure, p3);
122 return _cairo_spline_decompose (&spline, filler->tolerance);
125 cairo_status_t
126 _cairo_path_fixed_fill_to_polygon (const cairo_path_fixed_t *path,
127 double tolerance,
128 cairo_polygon_t *polygon)
130 cairo_filler_t filler;
131 cairo_status_t status;
133 filler.polygon = polygon;
134 filler.tolerance = tolerance;
136 filler.has_limits = FALSE;
137 if (polygon->num_limits) {
138 filler.has_limits = TRUE;
139 filler.limit = polygon->limit;
142 /* make sure that the closure represents a degenerate path */
143 filler.current_point.x = 0;
144 filler.current_point.y = 0;
145 filler.last_move_to = filler.current_point;
147 status = _cairo_path_fixed_interpret (path,
148 _cairo_filler_move_to,
149 _cairo_filler_line_to,
150 _cairo_filler_curve_to,
151 _cairo_filler_close,
152 &filler);
153 if (unlikely (status))
154 return status;
156 return _cairo_filler_close (&filler);
159 typedef struct cairo_filler_rectilinear_aligned {
160 cairo_polygon_t *polygon;
162 cairo_point_t current_point;
163 cairo_point_t last_move_to;
164 } cairo_filler_ra_t;
166 static cairo_status_t
167 _cairo_filler_ra_line_to (void *closure,
168 const cairo_point_t *point)
170 cairo_filler_ra_t *filler = closure;
171 cairo_status_t status;
172 cairo_point_t p;
174 p.x = _cairo_fixed_round_down (point->x);
175 p.y = _cairo_fixed_round_down (point->y);
177 status = _cairo_polygon_add_external_edge (filler->polygon,
178 &filler->current_point,
179 &p);
181 filler->current_point = p;
183 return status;
186 static cairo_status_t
187 _cairo_filler_ra_close (void *closure)
189 cairo_filler_ra_t *filler = closure;
190 return _cairo_filler_ra_line_to (closure, &filler->last_move_to);
193 static cairo_status_t
194 _cairo_filler_ra_move_to (void *closure,
195 const cairo_point_t *point)
197 cairo_filler_ra_t *filler = closure;
198 cairo_status_t status;
199 cairo_point_t p;
201 /* close current subpath */
202 status = _cairo_filler_ra_close (closure);
203 if (unlikely (status))
204 return status;
206 p.x = _cairo_fixed_round_down (point->x);
207 p.y = _cairo_fixed_round_down (point->y);
209 /* make sure that the closure represents a degenerate path */
210 filler->current_point = p;
211 filler->last_move_to = p;
213 return CAIRO_STATUS_SUCCESS;
216 cairo_status_t
217 _cairo_path_fixed_fill_rectilinear_to_polygon (const cairo_path_fixed_t *path,
218 cairo_antialias_t antialias,
219 cairo_polygon_t *polygon)
221 cairo_filler_ra_t filler;
222 cairo_status_t status;
224 if (antialias != CAIRO_ANTIALIAS_NONE)
225 return _cairo_path_fixed_fill_to_polygon (path, 0., polygon);
227 filler.polygon = polygon;
229 /* make sure that the closure represents a degenerate path */
230 filler.current_point.x = 0;
231 filler.current_point.y = 0;
232 filler.last_move_to = filler.current_point;
234 status = _cairo_path_fixed_interpret_flat (path,
235 _cairo_filler_ra_move_to,
236 _cairo_filler_ra_line_to,
237 _cairo_filler_ra_close,
238 &filler,
239 0.);
240 if (unlikely (status))
241 return status;
243 return _cairo_filler_ra_close (&filler);
246 cairo_status_t
247 _cairo_path_fixed_fill_to_traps (const cairo_path_fixed_t *path,
248 cairo_fill_rule_t fill_rule,
249 double tolerance,
250 cairo_traps_t *traps)
252 cairo_polygon_t polygon;
253 cairo_status_t status;
255 if (_cairo_path_fixed_fill_is_empty (path))
256 return CAIRO_STATUS_SUCCESS;
258 _cairo_polygon_init (&polygon, traps->limits, traps->num_limits);
259 status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
260 if (unlikely (status || polygon.num_edges == 0))
261 goto CLEANUP;
263 status = _cairo_bentley_ottmann_tessellate_polygon (traps,
264 &polygon, fill_rule);
266 CLEANUP:
267 _cairo_polygon_fini (&polygon);
268 return status;
271 static cairo_status_t
272 _cairo_path_fixed_fill_rectilinear_tessellate_to_boxes (const cairo_path_fixed_t *path,
273 cairo_fill_rule_t fill_rule,
274 cairo_antialias_t antialias,
275 cairo_boxes_t *boxes)
277 cairo_polygon_t polygon;
278 cairo_status_t status;
280 _cairo_polygon_init (&polygon, boxes->limits, boxes->num_limits);
281 boxes->num_limits = 0;
283 /* tolerance will be ignored as the path is rectilinear */
284 status = _cairo_path_fixed_fill_rectilinear_to_polygon (path, antialias, &polygon);
285 if (likely (status == CAIRO_STATUS_SUCCESS)) {
286 status =
287 _cairo_bentley_ottmann_tessellate_rectilinear_polygon_to_boxes (&polygon,
288 fill_rule,
289 boxes);
292 _cairo_polygon_fini (&polygon);
294 return status;
297 cairo_status_t
298 _cairo_path_fixed_fill_rectilinear_to_boxes (const cairo_path_fixed_t *path,
299 cairo_fill_rule_t fill_rule,
300 cairo_antialias_t antialias,
301 cairo_boxes_t *boxes)
303 cairo_path_fixed_iter_t iter;
304 cairo_status_t status;
305 cairo_box_t box;
307 if (_cairo_path_fixed_is_box (path, &box))
308 return _cairo_boxes_add (boxes, antialias, &box);
310 _cairo_path_fixed_iter_init (&iter, path);
311 while (_cairo_path_fixed_iter_is_fill_box (&iter, &box)) {
312 if (box.p1.y == box.p2.y || box.p1.x == box.p2.x)
313 continue;
315 if (box.p1.y > box.p2.y) {
316 cairo_fixed_t t;
318 t = box.p1.y;
319 box.p1.y = box.p2.y;
320 box.p2.y = t;
322 t = box.p1.x;
323 box.p1.x = box.p2.x;
324 box.p2.x = t;
327 status = _cairo_boxes_add (boxes, antialias, &box);
328 if (unlikely (status))
329 return status;
332 if (_cairo_path_fixed_iter_at_end (&iter))
333 return _cairo_bentley_ottmann_tessellate_boxes (boxes, fill_rule, boxes);
335 /* path is not rectangular, try extracting clipped rectilinear edges */
336 _cairo_boxes_clear (boxes);
337 return _cairo_path_fixed_fill_rectilinear_tessellate_to_boxes (path,
338 fill_rule,
339 antialias,
340 boxes);