beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-shape-mask-compositor.c
blob3117267cccf13303d0c1065b4aa2e28d4c870412
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
4 * Copyright © 2012 Intel Corporation
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 * Chris Wilson <chris@chris-wilson.co.uk>
38 #include "cairoint.h"
40 #include "cairo-compositor-private.h"
41 #include "cairo-clip-private.h"
42 #include "cairo-pattern-private.h"
43 #include "cairo-surface-private.h"
44 #include "cairo-surface-offset-private.h"
46 static cairo_int_status_t
47 _cairo_shape_mask_compositor_stroke (const cairo_compositor_t *_compositor,
48 cairo_composite_rectangles_t *extents,
49 const cairo_path_fixed_t *path,
50 const cairo_stroke_style_t *style,
51 const cairo_matrix_t *ctm,
52 const cairo_matrix_t *ctm_inverse,
53 double tolerance,
54 cairo_antialias_t antialias)
56 cairo_surface_t *mask;
57 cairo_surface_pattern_t pattern;
58 cairo_int_status_t status;
59 cairo_clip_t *clip;
61 if (! extents->is_bounded)
62 return CAIRO_INT_STATUS_UNSUPPORTED;
64 TRACE ((stderr, "%s\n", __FUNCTION__));
65 mask = _cairo_surface_create_scratch (extents->surface,
66 CAIRO_CONTENT_ALPHA,
67 extents->bounded.width,
68 extents->bounded.height,
69 NULL);
70 if (unlikely (mask->status))
71 return mask->status;
73 clip = extents->clip;
74 if (! _cairo_clip_is_region (clip))
75 clip = _cairo_clip_copy_region (clip);
77 if (! mask->is_clear) {
78 status = _cairo_surface_offset_paint (mask,
79 extents->bounded.x,
80 extents->bounded.y,
81 CAIRO_OPERATOR_CLEAR,
82 &_cairo_pattern_clear.base,
83 clip);
84 if (unlikely (status))
85 goto error;
88 status = _cairo_surface_offset_stroke (mask,
89 extents->bounded.x,
90 extents->bounded.y,
91 CAIRO_OPERATOR_ADD,
92 &_cairo_pattern_white.base,
93 path, style, ctm, ctm_inverse,
94 tolerance, antialias,
95 clip);
96 if (unlikely (status))
97 goto error;
99 if (clip != extents->clip) {
100 status = _cairo_clip_combine_with_surface (extents->clip, mask,
101 extents->bounded.x,
102 extents->bounded.y);
103 if (unlikely (status))
104 goto error;
107 _cairo_pattern_init_for_surface (&pattern, mask);
108 cairo_matrix_init_translate (&pattern.base.matrix,
109 -extents->bounded.x,
110 -extents->bounded.y);
111 pattern.base.filter = CAIRO_FILTER_NEAREST;
112 pattern.base.extend = CAIRO_EXTEND_NONE;
113 if (extents->op == CAIRO_OPERATOR_SOURCE) {
114 status = _cairo_surface_mask (extents->surface,
115 CAIRO_OPERATOR_DEST_OUT,
116 &_cairo_pattern_white.base,
117 &pattern.base,
118 clip);
119 if ((status == CAIRO_INT_STATUS_SUCCESS)) {
120 status = _cairo_surface_mask (extents->surface,
121 CAIRO_OPERATOR_ADD,
122 &extents->source_pattern.base,
123 &pattern.base,
124 clip);
126 } else {
127 status = _cairo_surface_mask (extents->surface,
128 extents->op,
129 &extents->source_pattern.base,
130 &pattern.base,
131 clip);
133 _cairo_pattern_fini (&pattern.base);
135 error:
136 cairo_surface_destroy (mask);
137 if (clip != extents->clip)
138 _cairo_clip_destroy (clip);
139 return status;
142 static cairo_int_status_t
143 _cairo_shape_mask_compositor_fill (const cairo_compositor_t *_compositor,
144 cairo_composite_rectangles_t *extents,
145 const cairo_path_fixed_t *path,
146 cairo_fill_rule_t fill_rule,
147 double tolerance,
148 cairo_antialias_t antialias)
150 cairo_surface_t *mask;
151 cairo_surface_pattern_t pattern;
152 cairo_int_status_t status;
153 cairo_clip_t *clip;
155 TRACE ((stderr, "%s\n", __FUNCTION__));
157 if (! extents->is_bounded)
158 return CAIRO_INT_STATUS_UNSUPPORTED;
160 mask = _cairo_surface_create_scratch (extents->surface,
161 CAIRO_CONTENT_ALPHA,
162 extents->bounded.width,
163 extents->bounded.height,
164 NULL);
165 if (unlikely (mask->status))
166 return mask->status;
168 clip = extents->clip;
169 if (! _cairo_clip_is_region (clip))
170 clip = _cairo_clip_copy_region (clip);
172 if (! mask->is_clear) {
173 status = _cairo_surface_offset_paint (mask,
174 extents->bounded.x,
175 extents->bounded.y,
176 CAIRO_OPERATOR_CLEAR,
177 &_cairo_pattern_clear.base,
178 clip);
179 if (unlikely (status))
180 goto error;
183 status = _cairo_surface_offset_fill (mask,
184 extents->bounded.x,
185 extents->bounded.y,
186 CAIRO_OPERATOR_ADD,
187 &_cairo_pattern_white.base,
188 path, fill_rule, tolerance, antialias,
189 clip);
190 if (unlikely (status))
191 goto error;
193 if (clip != extents->clip) {
194 status = _cairo_clip_combine_with_surface (extents->clip, mask,
195 extents->bounded.x,
196 extents->bounded.y);
197 if (unlikely (status))
198 goto error;
201 _cairo_pattern_init_for_surface (&pattern, mask);
202 cairo_matrix_init_translate (&pattern.base.matrix,
203 -extents->bounded.x,
204 -extents->bounded.y);
205 pattern.base.filter = CAIRO_FILTER_NEAREST;
206 pattern.base.extend = CAIRO_EXTEND_NONE;
207 if (extents->op == CAIRO_OPERATOR_SOURCE) {
208 status = _cairo_surface_mask (extents->surface,
209 CAIRO_OPERATOR_DEST_OUT,
210 &_cairo_pattern_white.base,
211 &pattern.base,
212 clip);
213 if ((status == CAIRO_INT_STATUS_SUCCESS)) {
214 status = _cairo_surface_mask (extents->surface,
215 CAIRO_OPERATOR_ADD,
216 &extents->source_pattern.base,
217 &pattern.base,
218 clip);
220 } else {
221 status = _cairo_surface_mask (extents->surface,
222 extents->op,
223 &extents->source_pattern.base,
224 &pattern.base,
225 clip);
227 _cairo_pattern_fini (&pattern.base);
229 error:
230 if (clip != extents->clip)
231 _cairo_clip_destroy (clip);
232 cairo_surface_destroy (mask);
233 return status;
236 static cairo_int_status_t
237 _cairo_shape_mask_compositor_glyphs (const cairo_compositor_t *_compositor,
238 cairo_composite_rectangles_t *extents,
239 cairo_scaled_font_t *scaled_font,
240 cairo_glyph_t *glyphs,
241 int num_glyphs,
242 cairo_bool_t overlap)
244 cairo_surface_t *mask;
245 cairo_surface_pattern_t pattern;
246 cairo_int_status_t status;
247 cairo_clip_t *clip;
249 if (! extents->is_bounded)
250 return CAIRO_INT_STATUS_UNSUPPORTED;
252 TRACE ((stderr, "%s\n", __FUNCTION__));
253 mask = _cairo_surface_create_scratch (extents->surface,
254 CAIRO_CONTENT_ALPHA,
255 extents->bounded.width,
256 extents->bounded.height,
257 NULL);
258 if (unlikely (mask->status))
259 return mask->status;
261 clip = extents->clip;
262 if (! _cairo_clip_is_region (clip))
263 clip = _cairo_clip_copy_region (clip);
265 if (! mask->is_clear) {
266 status = _cairo_surface_offset_paint (mask,
267 extents->bounded.x,
268 extents->bounded.y,
269 CAIRO_OPERATOR_CLEAR,
270 &_cairo_pattern_clear.base,
271 clip);
272 if (unlikely (status))
273 goto error;
276 status = _cairo_surface_offset_glyphs (mask,
277 extents->bounded.x,
278 extents->bounded.y,
279 CAIRO_OPERATOR_ADD,
280 &_cairo_pattern_white.base,
281 scaled_font, glyphs, num_glyphs,
282 clip);
283 if (unlikely (status))
284 goto error;
286 if (clip != extents->clip) {
287 status = _cairo_clip_combine_with_surface (extents->clip, mask,
288 extents->bounded.x,
289 extents->bounded.y);
290 if (unlikely (status))
291 goto error;
294 _cairo_pattern_init_for_surface (&pattern, mask);
295 cairo_matrix_init_translate (&pattern.base.matrix,
296 -extents->bounded.x,
297 -extents->bounded.y);
298 pattern.base.filter = CAIRO_FILTER_NEAREST;
299 pattern.base.extend = CAIRO_EXTEND_NONE;
300 if (extents->op == CAIRO_OPERATOR_SOURCE) {
301 status = _cairo_surface_mask (extents->surface,
302 CAIRO_OPERATOR_DEST_OUT,
303 &_cairo_pattern_white.base,
304 &pattern.base,
305 clip);
306 if ((status == CAIRO_INT_STATUS_SUCCESS)) {
307 status = _cairo_surface_mask (extents->surface,
308 CAIRO_OPERATOR_ADD,
309 &extents->source_pattern.base,
310 &pattern.base,
311 clip);
313 } else {
314 status = _cairo_surface_mask (extents->surface,
315 extents->op,
316 &extents->source_pattern.base,
317 &pattern.base,
318 clip);
320 _cairo_pattern_fini (&pattern.base);
322 error:
323 if (clip != extents->clip)
324 _cairo_clip_destroy (clip);
325 cairo_surface_destroy (mask);
326 return status;
329 void
330 _cairo_shape_mask_compositor_init (cairo_compositor_t *compositor,
331 const cairo_compositor_t *delegate)
333 compositor->delegate = delegate;
335 compositor->paint = NULL;
336 compositor->mask = NULL;
337 compositor->fill = _cairo_shape_mask_compositor_fill;
338 compositor->stroke = _cairo_shape_mask_compositor_stroke;
339 compositor->glyphs = _cairo_shape_mask_compositor_glyphs;