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
35 * Chris Wilson <chris@chris-wilson.co.uk>
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
,
54 cairo_antialias_t antialias
)
56 cairo_surface_t
*mask
;
57 cairo_surface_pattern_t pattern
;
58 cairo_int_status_t status
;
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
,
67 extents
->bounded
.width
,
68 extents
->bounded
.height
,
70 if (unlikely (mask
->status
))
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
,
82 &_cairo_pattern_clear
.base
,
84 if (unlikely (status
))
88 status
= _cairo_surface_offset_stroke (mask
,
92 &_cairo_pattern_white
.base
,
93 path
, style
, ctm
, ctm_inverse
,
96 if (unlikely (status
))
99 if (clip
!= extents
->clip
) {
100 status
= _cairo_clip_combine_with_surface (extents
->clip
, mask
,
103 if (unlikely (status
))
107 _cairo_pattern_init_for_surface (&pattern
, mask
);
108 cairo_matrix_init_translate (&pattern
.base
.matrix
,
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
,
119 if ((status
== CAIRO_INT_STATUS_SUCCESS
)) {
120 status
= _cairo_surface_mask (extents
->surface
,
122 &extents
->source_pattern
.base
,
127 status
= _cairo_surface_mask (extents
->surface
,
129 &extents
->source_pattern
.base
,
133 _cairo_pattern_fini (&pattern
.base
);
136 cairo_surface_destroy (mask
);
137 if (clip
!= extents
->clip
)
138 _cairo_clip_destroy (clip
);
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
,
148 cairo_antialias_t antialias
)
150 cairo_surface_t
*mask
;
151 cairo_surface_pattern_t pattern
;
152 cairo_int_status_t status
;
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
,
162 extents
->bounded
.width
,
163 extents
->bounded
.height
,
165 if (unlikely (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
,
176 CAIRO_OPERATOR_CLEAR
,
177 &_cairo_pattern_clear
.base
,
179 if (unlikely (status
))
183 status
= _cairo_surface_offset_fill (mask
,
187 &_cairo_pattern_white
.base
,
188 path
, fill_rule
, tolerance
, antialias
,
190 if (unlikely (status
))
193 if (clip
!= extents
->clip
) {
194 status
= _cairo_clip_combine_with_surface (extents
->clip
, mask
,
197 if (unlikely (status
))
201 _cairo_pattern_init_for_surface (&pattern
, mask
);
202 cairo_matrix_init_translate (&pattern
.base
.matrix
,
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
,
213 if ((status
== CAIRO_INT_STATUS_SUCCESS
)) {
214 status
= _cairo_surface_mask (extents
->surface
,
216 &extents
->source_pattern
.base
,
221 status
= _cairo_surface_mask (extents
->surface
,
223 &extents
->source_pattern
.base
,
227 _cairo_pattern_fini (&pattern
.base
);
230 if (clip
!= extents
->clip
)
231 _cairo_clip_destroy (clip
);
232 cairo_surface_destroy (mask
);
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
,
242 cairo_bool_t overlap
)
244 cairo_surface_t
*mask
;
245 cairo_surface_pattern_t pattern
;
246 cairo_int_status_t status
;
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
,
255 extents
->bounded
.width
,
256 extents
->bounded
.height
,
258 if (unlikely (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
,
269 CAIRO_OPERATOR_CLEAR
,
270 &_cairo_pattern_clear
.base
,
272 if (unlikely (status
))
276 status
= _cairo_surface_offset_glyphs (mask
,
280 &_cairo_pattern_white
.base
,
281 scaled_font
, glyphs
, num_glyphs
,
283 if (unlikely (status
))
286 if (clip
!= extents
->clip
) {
287 status
= _cairo_clip_combine_with_surface (extents
->clip
, mask
,
290 if (unlikely (status
))
294 _cairo_pattern_init_for_surface (&pattern
, mask
);
295 cairo_matrix_init_translate (&pattern
.base
.matrix
,
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
,
306 if ((status
== CAIRO_INT_STATUS_SUCCESS
)) {
307 status
= _cairo_surface_mask (extents
->surface
,
309 &extents
->source_pattern
.base
,
314 status
= _cairo_surface_mask (extents
->surface
,
316 &extents
->source_pattern
.base
,
320 _cairo_pattern_fini (&pattern
.base
);
323 if (clip
!= extents
->clip
)
324 _cairo_clip_destroy (clip
);
325 cairo_surface_destroy (mask
);
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
;