2009-12-07 Rolf Bjarne Kvinge <RKvinge@novell.com>
[moon.git] / cairo / src / cairo-path-fill.c
blob1cef20e4aaa606c7b65e4ca47c88a5ef40afc894
1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2002 University of Southern California
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is University of Southern
31 * California.
33 * Contributor(s):
34 * Carl D. Worth <cworth@cworth.org>
37 #include "cairoint.h"
38 #include "cairo-path-fixed-private.h"
40 typedef struct cairo_filler {
41 double tolerance;
42 cairo_traps_t *traps;
44 cairo_point_t current_point;
46 cairo_polygon_t polygon;
47 } cairo_filler_t;
49 static void
50 _cairo_filler_init (cairo_filler_t *filler, double tolerance, cairo_traps_t *traps);
52 static void
53 _cairo_filler_fini (cairo_filler_t *filler);
55 static cairo_status_t
56 _cairo_filler_move_to (void *closure, cairo_point_t *point);
58 static cairo_status_t
59 _cairo_filler_line_to (void *closure, cairo_point_t *point);
61 static cairo_status_t
62 _cairo_filler_curve_to (void *closure,
63 cairo_point_t *b,
64 cairo_point_t *c,
65 cairo_point_t *d);
67 static cairo_status_t
68 _cairo_filler_close_path (void *closure);
70 static void
71 _cairo_filler_init (cairo_filler_t *filler, double tolerance, cairo_traps_t *traps)
73 filler->tolerance = tolerance;
74 filler->traps = traps;
76 filler->current_point.x = 0;
77 filler->current_point.y = 0;
79 _cairo_polygon_init (&filler->polygon);
82 static void
83 _cairo_filler_fini (cairo_filler_t *filler)
85 _cairo_polygon_fini (&filler->polygon);
88 static cairo_status_t
89 _cairo_filler_move_to (void *closure, cairo_point_t *point)
91 cairo_filler_t *filler = closure;
92 cairo_polygon_t *polygon = &filler->polygon;
94 _cairo_polygon_close (polygon);
95 _cairo_polygon_move_to (polygon, point);
97 filler->current_point = *point;
99 return _cairo_polygon_status (&filler->polygon);
102 static cairo_status_t
103 _cairo_filler_line_to (void *closure, cairo_point_t *point)
105 cairo_filler_t *filler = closure;
106 cairo_polygon_t *polygon = &filler->polygon;
108 _cairo_polygon_line_to (polygon, point);
110 filler->current_point = *point;
112 return _cairo_polygon_status (&filler->polygon);
115 static cairo_status_t
116 _cairo_filler_curve_to (void *closure,
117 cairo_point_t *b,
118 cairo_point_t *c,
119 cairo_point_t *d)
121 int i;
122 cairo_status_t status = CAIRO_STATUS_SUCCESS;
123 cairo_filler_t *filler = closure;
124 cairo_polygon_t *polygon = &filler->polygon;
125 cairo_spline_t spline;
127 status = _cairo_spline_init (&spline, &filler->current_point, b, c, d);
129 if (status == CAIRO_INT_STATUS_DEGENERATE)
130 return CAIRO_STATUS_SUCCESS;
132 status = _cairo_spline_decompose (&spline, filler->tolerance);
133 if (status)
134 goto CLEANUP_SPLINE;
136 for (i = 1; i < spline.num_points; i++)
137 _cairo_polygon_line_to (polygon, &spline.points[i]);
139 CLEANUP_SPLINE:
140 _cairo_spline_fini (&spline);
142 filler->current_point = *d;
144 return status;
147 static cairo_status_t
148 _cairo_filler_close_path (void *closure)
150 cairo_filler_t *filler = closure;
151 cairo_polygon_t *polygon = &filler->polygon;
153 _cairo_polygon_close (polygon);
155 return _cairo_polygon_status (polygon);
158 static cairo_int_status_t
159 _cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path,
160 cairo_traps_t *traps);
162 cairo_status_t
163 _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
164 cairo_fill_rule_t fill_rule,
165 double tolerance,
166 cairo_traps_t *traps)
168 cairo_status_t status = CAIRO_STATUS_SUCCESS;
169 cairo_filler_t filler;
171 /* Before we do anything else, we use a special-case filler for
172 * a device-axis aligned rectangle if possible. */
173 status = _cairo_path_fixed_fill_rectangle (path, traps);
174 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
175 return status;
177 _cairo_filler_init (&filler, tolerance, traps);
179 status = _cairo_path_fixed_interpret (path,
180 CAIRO_DIRECTION_FORWARD,
181 _cairo_filler_move_to,
182 _cairo_filler_line_to,
183 _cairo_filler_curve_to,
184 _cairo_filler_close_path,
185 &filler);
186 if (status)
187 goto BAIL;
189 _cairo_polygon_close (&filler.polygon);
190 status = _cairo_polygon_status (&filler.polygon);
191 if (status)
192 goto BAIL;
194 status = _cairo_bentley_ottmann_tessellate_polygon (filler.traps,
195 &filler.polygon,
196 fill_rule);
197 if (status)
198 goto BAIL;
200 BAIL:
201 _cairo_filler_fini (&filler);
203 return status;
206 /* This special-case filler supports only a path that describes a
207 * device-axis aligned rectangle. It exists to avoid the overhead of
208 * the general tessellator when drawing very common rectangles.
210 * If the path described anything but a device-axis aligned rectangle,
211 * this function will return %CAIRO_INT_STATUS_UNSUPPORTED.
213 static cairo_int_status_t
214 _cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path,
215 cairo_traps_t *traps)
217 if (_cairo_path_fixed_is_box (path, NULL)) {
218 cairo_point_t *p = path->buf_head.base.points;
219 cairo_point_t *top_left, *bot_right;
221 top_left = &p[0];
222 bot_right = &p[2];
223 if (top_left->x > bot_right->x || top_left->y > bot_right->y) {
224 int n;
226 /* not a simple cairo_rectangle() */
227 for (n = 0; n < 4; n++) {
228 if (p[n].x <= top_left->x && p[n].y <= top_left->y)
229 top_left = &p[n];
230 if (p[n].x >= bot_right->x && p[n].y >= bot_right->y)
231 bot_right = &p[n];
235 return _cairo_traps_tessellate_rectangle (traps, top_left, bot_right);
238 return CAIRO_INT_STATUS_UNSUPPORTED;