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_similar_scratch (extents->surface,
67
extents->bounded.width,
68
extents->bounded.height);
69
if (unlikely (mask->status))
73
if (! _cairo_clip_is_region (clip))
74
clip = _cairo_clip_copy_region (clip);
76
if (! mask->is_clear) {
77
status = _cairo_surface_offset_paint (mask,
81
&_cairo_pattern_clear.base,
83
if (unlikely (status))
87
status = _cairo_surface_offset_stroke (mask,
91
&_cairo_pattern_white.base,
92
path, style, ctm, ctm_inverse,
95
if (unlikely (status))
98
if (clip != extents->clip) {
99
status = _cairo_clip_combine_with_surface (extents->clip, mask,
102
if (unlikely (status))
106
_cairo_pattern_init_for_surface (&pattern, mask);
107
cairo_matrix_init_translate (&pattern.base.matrix,
109
-extents->bounded.y);
110
pattern.base.filter = CAIRO_FILTER_NEAREST;
111
pattern.base.extend = CAIRO_EXTEND_NONE;
112
if (extents->op == CAIRO_OPERATOR_SOURCE) {
113
status = _cairo_surface_mask (extents->surface,
114
CAIRO_OPERATOR_DEST_OUT,
115
&_cairo_pattern_white.base,
118
if ((status == CAIRO_INT_STATUS_SUCCESS)) {
119
status = _cairo_surface_mask (extents->surface,
121
&extents->source_pattern.base,
126
status = _cairo_surface_mask (extents->surface,
128
&extents->source_pattern.base,
132
_cairo_pattern_fini (&pattern.base);
135
cairo_surface_destroy (mask);
136
if (clip != extents->clip)
137
_cairo_clip_destroy (clip);
141
static cairo_int_status_t
142
_cairo_shape_mask_compositor_fill (const cairo_compositor_t *_compositor,
143
cairo_composite_rectangles_t *extents,
144
const cairo_path_fixed_t *path,
145
cairo_fill_rule_t fill_rule,
147
cairo_antialias_t antialias)
149
cairo_surface_t *mask;
150
cairo_surface_pattern_t pattern;
151
cairo_int_status_t status;
154
TRACE ((stderr, "%s\n", __FUNCTION__));
156
if (! extents->is_bounded)
157
return CAIRO_INT_STATUS_UNSUPPORTED;
159
mask = _cairo_surface_create_similar_scratch (extents->surface,
161
extents->bounded.width,
162
extents->bounded.height);
163
if (unlikely (mask->status))
166
clip = extents->clip;
167
if (! _cairo_clip_is_region (clip))
168
clip = _cairo_clip_copy_region (clip);
170
if (! mask->is_clear) {
171
status = _cairo_surface_offset_paint (mask,
174
CAIRO_OPERATOR_CLEAR,
175
&_cairo_pattern_clear.base,
177
if (unlikely (status))
181
status = _cairo_surface_offset_fill (mask,
185
&_cairo_pattern_white.base,
186
path, fill_rule, tolerance, antialias,
188
if (unlikely (status))
191
if (clip != extents->clip) {
192
status = _cairo_clip_combine_with_surface (extents->clip, mask,
195
if (unlikely (status))
199
_cairo_pattern_init_for_surface (&pattern, mask);
200
cairo_matrix_init_translate (&pattern.base.matrix,
202
-extents->bounded.y);
203
pattern.base.filter = CAIRO_FILTER_NEAREST;
204
pattern.base.extend = CAIRO_EXTEND_NONE;
205
if (extents->op == CAIRO_OPERATOR_SOURCE) {
206
status = _cairo_surface_mask (extents->surface,
207
CAIRO_OPERATOR_DEST_OUT,
208
&_cairo_pattern_white.base,
211
if ((status == CAIRO_INT_STATUS_SUCCESS)) {
212
status = _cairo_surface_mask (extents->surface,
214
&extents->source_pattern.base,
219
status = _cairo_surface_mask (extents->surface,
221
&extents->source_pattern.base,
225
_cairo_pattern_fini (&pattern.base);
228
if (clip != extents->clip)
229
_cairo_clip_destroy (clip);
230
cairo_surface_destroy (mask);
234
static cairo_int_status_t
235
_cairo_shape_mask_compositor_glyphs (const cairo_compositor_t *_compositor,
236
cairo_composite_rectangles_t *extents,
237
cairo_scaled_font_t *scaled_font,
238
cairo_glyph_t *glyphs,
240
cairo_bool_t overlap)
242
cairo_surface_t *mask;
243
cairo_surface_pattern_t pattern;
244
cairo_int_status_t status;
247
if (! extents->is_bounded)
248
return CAIRO_INT_STATUS_UNSUPPORTED;
250
TRACE ((stderr, "%s\n", __FUNCTION__));
251
mask = _cairo_surface_create_similar_scratch (extents->surface,
253
extents->bounded.width,
254
extents->bounded.height);
255
if (unlikely (mask->status))
258
clip = extents->clip;
259
if (! _cairo_clip_is_region (clip))
260
clip = _cairo_clip_copy_region (clip);
262
if (! mask->is_clear) {
263
status = _cairo_surface_offset_paint (mask,
266
CAIRO_OPERATOR_CLEAR,
267
&_cairo_pattern_clear.base,
269
if (unlikely (status))
273
status = _cairo_surface_offset_glyphs (mask,
277
&_cairo_pattern_white.base,
278
scaled_font, glyphs, num_glyphs,
280
if (unlikely (status))
283
if (clip != extents->clip) {
284
status = _cairo_clip_combine_with_surface (extents->clip, mask,
287
if (unlikely (status))
291
_cairo_pattern_init_for_surface (&pattern, mask);
292
cairo_matrix_init_translate (&pattern.base.matrix,
294
-extents->bounded.y);
295
pattern.base.filter = CAIRO_FILTER_NEAREST;
296
pattern.base.extend = CAIRO_EXTEND_NONE;
297
if (extents->op == CAIRO_OPERATOR_SOURCE) {
298
status = _cairo_surface_mask (extents->surface,
299
CAIRO_OPERATOR_DEST_OUT,
300
&_cairo_pattern_white.base,
303
if ((status == CAIRO_INT_STATUS_SUCCESS)) {
304
status = _cairo_surface_mask (extents->surface,
306
&extents->source_pattern.base,
311
status = _cairo_surface_mask (extents->surface,
313
&extents->source_pattern.base,
317
_cairo_pattern_fini (&pattern.base);
320
if (clip != extents->clip)
321
_cairo_clip_destroy (clip);
322
cairo_surface_destroy (mask);
327
_cairo_shape_mask_compositor_init (cairo_compositor_t *compositor,
328
const cairo_compositor_t *delegate)
330
compositor->delegate = delegate;
332
compositor->paint = NULL;
333
compositor->mask = NULL;
334
compositor->fill = _cairo_shape_mask_compositor_fill;
335
compositor->stroke = _cairo_shape_mask_compositor_stroke;
336
compositor->glyphs = _cairo_shape_mask_compositor_glyphs;