/src/cairo/src/cairo-compositor.c
Line | Count | Source (jump to first uncovered line) |
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 | | |
40 | | #include "cairo-compositor-private.h" |
41 | | #include "cairo-damage-private.h" |
42 | | #include "cairo-error-private.h" |
43 | | |
44 | | cairo_int_status_t |
45 | | _cairo_compositor_paint (const cairo_compositor_t *compositor, |
46 | | cairo_surface_t *surface, |
47 | | cairo_operator_t op, |
48 | | const cairo_pattern_t *source, |
49 | | const cairo_clip_t *clip) |
50 | 14 | { |
51 | 14 | cairo_composite_rectangles_t extents; |
52 | 14 | cairo_int_status_t status; |
53 | | |
54 | 14 | TRACE ((stderr, "%s\n", __FUNCTION__)); |
55 | 14 | status = _cairo_composite_rectangles_init_for_paint (&extents, surface, |
56 | 14 | op, source, |
57 | 14 | clip); |
58 | 14 | if (unlikely (status)) |
59 | 0 | return status; |
60 | | |
61 | 14 | do { |
62 | 14 | while (compositor->paint == NULL) |
63 | 0 | compositor = compositor->delegate; |
64 | | |
65 | 14 | status = compositor->paint (compositor, &extents); |
66 | | |
67 | 14 | compositor = compositor->delegate; |
68 | 14 | } while (status == CAIRO_INT_STATUS_UNSUPPORTED); |
69 | | |
70 | 14 | if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) { |
71 | 0 | TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n", |
72 | 0 | __FUNCTION__, |
73 | 0 | extents.unbounded.x, extents.unbounded.y, |
74 | 0 | extents.unbounded.width, extents.unbounded.height)); |
75 | 0 | surface->damage = _cairo_damage_add_rectangle (surface->damage, |
76 | 0 | &extents.unbounded); |
77 | 0 | } |
78 | | |
79 | 14 | _cairo_composite_rectangles_fini (&extents); |
80 | | |
81 | 14 | return status; |
82 | 14 | } |
83 | | |
84 | | cairo_int_status_t |
85 | | _cairo_compositor_mask (const cairo_compositor_t *compositor, |
86 | | cairo_surface_t *surface, |
87 | | cairo_operator_t op, |
88 | | const cairo_pattern_t *source, |
89 | | const cairo_pattern_t *mask, |
90 | | const cairo_clip_t *clip) |
91 | 2 | { |
92 | 2 | cairo_composite_rectangles_t extents; |
93 | 2 | cairo_int_status_t status; |
94 | | |
95 | 2 | TRACE ((stderr, "%s\n", __FUNCTION__)); |
96 | 2 | status = _cairo_composite_rectangles_init_for_mask (&extents, surface, |
97 | 2 | op, source, mask, |
98 | 2 | clip); |
99 | 2 | if (unlikely (status)) |
100 | 0 | return status; |
101 | | |
102 | 4 | do { |
103 | 6 | while (compositor->mask == NULL) |
104 | 2 | compositor = compositor->delegate; |
105 | | |
106 | 4 | status = compositor->mask (compositor, &extents); |
107 | | |
108 | 4 | compositor = compositor->delegate; |
109 | 4 | } while (status == CAIRO_INT_STATUS_UNSUPPORTED); |
110 | | |
111 | 2 | if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) { |
112 | 0 | TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n", |
113 | 0 | __FUNCTION__, |
114 | 0 | extents.unbounded.x, extents.unbounded.y, |
115 | 0 | extents.unbounded.width, extents.unbounded.height)); |
116 | 0 | surface->damage = _cairo_damage_add_rectangle (surface->damage, |
117 | 0 | &extents.unbounded); |
118 | 0 | } |
119 | | |
120 | 2 | _cairo_composite_rectangles_fini (&extents); |
121 | | |
122 | 2 | return status; |
123 | 2 | } |
124 | | |
125 | | static cairo_int_status_t |
126 | | _cairo_compositor_stroke_impl (const cairo_compositor_t *compositor, |
127 | | cairo_surface_t *surface, |
128 | | cairo_operator_t op, |
129 | | const cairo_pattern_t *source, |
130 | | const cairo_path_fixed_t *path, |
131 | | const cairo_stroke_style_t *style, |
132 | | const cairo_matrix_t *ctm, |
133 | | const cairo_matrix_t *ctm_inverse, |
134 | | double tolerance, |
135 | | cairo_antialias_t antialias, |
136 | | const cairo_clip_t *clip) |
137 | 0 | { |
138 | 0 | cairo_composite_rectangles_t extents; |
139 | 0 | cairo_int_status_t status; |
140 | |
|
141 | 0 | TRACE ((stderr, "%s\n", __FUNCTION__)); |
142 | |
|
143 | 0 | if (_cairo_pen_vertices_needed (tolerance, style->line_width/2, ctm) <= 1) |
144 | 0 | return CAIRO_INT_STATUS_NOTHING_TO_DO; |
145 | | |
146 | 0 | status = _cairo_composite_rectangles_init_for_stroke (&extents, surface, |
147 | 0 | op, source, |
148 | 0 | path, style, ctm, |
149 | 0 | clip); |
150 | 0 | if (unlikely (status)) |
151 | 0 | return status; |
152 | | |
153 | 0 | do { |
154 | 0 | while (compositor->stroke == NULL) |
155 | 0 | compositor = compositor->delegate; |
156 | |
|
157 | 0 | status = compositor->stroke (compositor, &extents, |
158 | 0 | path, style, ctm, ctm_inverse, |
159 | 0 | tolerance, antialias); |
160 | |
|
161 | 0 | compositor = compositor->delegate; |
162 | 0 | } while (status == CAIRO_INT_STATUS_UNSUPPORTED); |
163 | |
|
164 | 0 | if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) { |
165 | 0 | TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n", |
166 | 0 | __FUNCTION__, |
167 | 0 | extents.unbounded.x, extents.unbounded.y, |
168 | 0 | extents.unbounded.width, extents.unbounded.height)); |
169 | 0 | surface->damage = _cairo_damage_add_rectangle (surface->damage, |
170 | 0 | &extents.unbounded); |
171 | 0 | } |
172 | |
|
173 | 0 | _cairo_composite_rectangles_fini (&extents); |
174 | |
|
175 | 0 | return status; |
176 | 0 | } |
177 | | |
178 | | cairo_int_status_t |
179 | | _cairo_compositor_stroke (const cairo_compositor_t *compositor, |
180 | | cairo_surface_t *surface, |
181 | | cairo_operator_t op, |
182 | | const cairo_pattern_t *source, |
183 | | const cairo_path_fixed_t *path, |
184 | | const cairo_stroke_style_t *style, |
185 | | const cairo_matrix_t *ctm, |
186 | | const cairo_matrix_t *ctm_inverse, |
187 | | double tolerance, |
188 | | cairo_antialias_t antialias, |
189 | | const cairo_clip_t *clip) |
190 | 0 | { |
191 | 0 | if (!style->is_hairline) |
192 | 0 | return _cairo_compositor_stroke_impl (compositor, surface, |
193 | 0 | op, source, path, |
194 | 0 | style, ctm, ctm_inverse, |
195 | 0 | tolerance, antialias, clip); |
196 | 0 | else { |
197 | 0 | cairo_stroke_style_t hairline_style; |
198 | 0 | cairo_status_t status; |
199 | 0 | cairo_matrix_t identity; |
200 | |
|
201 | 0 | status = _cairo_stroke_style_init_copy (&hairline_style, style); |
202 | 0 | if (unlikely (status)) |
203 | 0 | return status; |
204 | | |
205 | 0 | hairline_style.line_width = 1.0; |
206 | |
|
207 | 0 | cairo_matrix_init_identity (&identity); |
208 | |
|
209 | 0 | status = _cairo_compositor_stroke_impl (compositor, surface, |
210 | 0 | op, source, path, |
211 | 0 | &hairline_style, &identity, &identity, |
212 | 0 | tolerance, antialias, clip); |
213 | |
|
214 | 0 | _cairo_stroke_style_fini (&hairline_style); |
215 | |
|
216 | 0 | return status; |
217 | 0 | } |
218 | 0 | } |
219 | | |
220 | | cairo_int_status_t |
221 | | _cairo_compositor_fill (const cairo_compositor_t *compositor, |
222 | | cairo_surface_t *surface, |
223 | | cairo_operator_t op, |
224 | | const cairo_pattern_t *source, |
225 | | const cairo_path_fixed_t *path, |
226 | | cairo_fill_rule_t fill_rule, |
227 | | double tolerance, |
228 | | cairo_antialias_t antialias, |
229 | | const cairo_clip_t *clip) |
230 | 6 | { |
231 | 6 | cairo_composite_rectangles_t extents; |
232 | 6 | cairo_int_status_t status; |
233 | | |
234 | 6 | TRACE ((stderr, "%s\n", __FUNCTION__)); |
235 | 6 | status = _cairo_composite_rectangles_init_for_fill (&extents, surface, |
236 | 6 | op, source, path, |
237 | 6 | clip); |
238 | 6 | if (unlikely (status)) |
239 | 0 | return status; |
240 | | |
241 | 6 | do { |
242 | 6 | while (compositor->fill == NULL) |
243 | 0 | compositor = compositor->delegate; |
244 | | |
245 | 6 | status = compositor->fill (compositor, &extents, |
246 | 6 | path, fill_rule, tolerance, antialias); |
247 | | |
248 | 6 | compositor = compositor->delegate; |
249 | 6 | } while (status == CAIRO_INT_STATUS_UNSUPPORTED); |
250 | | |
251 | 6 | if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) { |
252 | 0 | TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n", |
253 | 0 | __FUNCTION__, |
254 | 0 | extents.unbounded.x, extents.unbounded.y, |
255 | 0 | extents.unbounded.width, extents.unbounded.height)); |
256 | 0 | surface->damage = _cairo_damage_add_rectangle (surface->damage, |
257 | 0 | &extents.unbounded); |
258 | 0 | } |
259 | | |
260 | 6 | _cairo_composite_rectangles_fini (&extents); |
261 | | |
262 | 6 | return status; |
263 | 6 | } |
264 | | |
265 | | cairo_int_status_t |
266 | | _cairo_compositor_glyphs (const cairo_compositor_t *compositor, |
267 | | cairo_surface_t *surface, |
268 | | cairo_operator_t op, |
269 | | const cairo_pattern_t *source, |
270 | | cairo_glyph_t *glyphs, |
271 | | int num_glyphs, |
272 | | cairo_scaled_font_t *scaled_font, |
273 | | const cairo_clip_t *clip) |
274 | 0 | { |
275 | 0 | cairo_composite_rectangles_t extents; |
276 | 0 | cairo_bool_t overlap; |
277 | 0 | cairo_int_status_t status; |
278 | |
|
279 | 0 | TRACE ((stderr, "%s\n", __FUNCTION__)); |
280 | 0 | status = _cairo_composite_rectangles_init_for_glyphs (&extents, surface, |
281 | 0 | op, source, |
282 | 0 | scaled_font, |
283 | 0 | glyphs, num_glyphs, |
284 | 0 | clip, &overlap); |
285 | 0 | if (unlikely (status)) |
286 | 0 | return status; |
287 | | |
288 | 0 | do { |
289 | 0 | while (compositor->glyphs == NULL) |
290 | 0 | compositor = compositor->delegate; |
291 | |
|
292 | 0 | status = compositor->glyphs (compositor, &extents, |
293 | 0 | scaled_font, glyphs, num_glyphs, overlap); |
294 | |
|
295 | 0 | compositor = compositor->delegate; |
296 | 0 | } while (status == CAIRO_INT_STATUS_UNSUPPORTED); |
297 | |
|
298 | 0 | if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) { |
299 | 0 | TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n", |
300 | 0 | __FUNCTION__, |
301 | 0 | extents.unbounded.x, extents.unbounded.y, |
302 | 0 | extents.unbounded.width, extents.unbounded.height)); |
303 | 0 | surface->damage = _cairo_damage_add_rectangle (surface->damage, |
304 | 0 | &extents.unbounded); |
305 | 0 | } |
306 | |
|
307 | 0 | _cairo_composite_rectangles_fini (&extents); |
308 | |
|
309 | 0 | return status; |
310 | 0 | } |