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
34 * Carl D. Worth <cworth@cworth.org>
38 #include "cairo-path-fixed-private.h"
40 typedef struct cairo_filler
{
44 cairo_point_t current_point
;
46 cairo_polygon_t polygon
;
50 _cairo_filler_init (cairo_filler_t
*filler
, double tolerance
, cairo_traps_t
*traps
);
53 _cairo_filler_fini (cairo_filler_t
*filler
);
56 _cairo_filler_move_to (void *closure
, cairo_point_t
*point
);
59 _cairo_filler_line_to (void *closure
, cairo_point_t
*point
);
62 _cairo_filler_curve_to (void *closure
,
68 _cairo_filler_close_path (void *closure
);
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
);
83 _cairo_filler_fini (cairo_filler_t
*filler
)
85 _cairo_polygon_fini (&filler
->polygon
);
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
,
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
);
136 for (i
= 1; i
< spline
.num_points
; i
++)
137 _cairo_polygon_line_to (polygon
, &spline
.points
[i
]);
140 _cairo_spline_fini (&spline
);
142 filler
->current_point
= *d
;
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
);
163 _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t
*path
,
164 cairo_fill_rule_t fill_rule
,
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
)
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
,
189 _cairo_polygon_close (&filler
.polygon
);
190 status
= _cairo_polygon_status (&filler
.polygon
);
194 status
= _cairo_bentley_ottmann_tessellate_polygon (filler
.traps
,
201 _cairo_filler_fini (&filler
);
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
;
223 if (top_left
->x
> bot_right
->x
|| top_left
->y
> bot_right
->y
) {
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
)
230 if (p
[n
].x
>= bot_right
->x
&& p
[n
].y
>= bot_right
->y
)
235 return _cairo_traps_tessellate_rectangle (traps
, top_left
, bot_right
);
238 return CAIRO_INT_STATUS_UNSUPPORTED
;