1 /* cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 Intel Corporation
4  *
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.
12  *
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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16  * You should have received a copy of the MPL along with this library
17  * in the file COPYING-MPL-1.1
18  *
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/
23  *
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.
27  *
28  * The Original Code is the cairo graphics library.
29  *
30  * The Initial Developer of the Original Code is Red Hat, Inc.
31  *
32  * Contributor(s):
33  *      Chris Wilson <chris@chris-wilson.co.uk>
34  */
35 
36 #include "cairoint.h"
37 
38 #include "cairo-error-private.h"
39 #include "cairo-composite-rectangles-private.h"
40 
41 /* A collection of routines to facilitate writing compositors. */
42 
43 static inline cairo_bool_t
_cairo_composite_rectangles_init(cairo_composite_rectangles_t * extents,const cairo_rectangle_int_t * surface_extents,cairo_operator_t op,const cairo_pattern_t * source,cairo_clip_t * clip)44 _cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents,
45 				  const cairo_rectangle_int_t *surface_extents,
46 				  cairo_operator_t op,
47 				  const cairo_pattern_t *source,
48 				  cairo_clip_t *clip)
49 {
50     extents->unbounded = *surface_extents;
51 
52     if (clip != NULL) {
53 	const cairo_rectangle_int_t *clip_extents;
54 
55 	clip_extents = _cairo_clip_get_extents (clip);
56 	if (clip_extents == NULL)
57 	    return FALSE;
58 
59 	if (! _cairo_rectangle_intersect (&extents->unbounded, clip_extents))
60 	    return FALSE;
61     }
62 
63     extents->bounded = extents->unbounded;
64     extents->is_bounded = _cairo_operator_bounded_by_either (op);
65 
66     _cairo_pattern_get_extents (source, &extents->source);
67     if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) {
68 	if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source))
69 	    return FALSE;
70     }
71 
72     return TRUE;
73 }
74 
75 cairo_int_status_t
_cairo_composite_rectangles_init_for_paint(cairo_composite_rectangles_t * extents,const cairo_rectangle_int_t * surface_extents,cairo_operator_t op,const cairo_pattern_t * source,cairo_clip_t * clip)76 _cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
77 					    const cairo_rectangle_int_t *surface_extents,
78 					    cairo_operator_t		 op,
79 					    const cairo_pattern_t	*source,
80 					    cairo_clip_t		*clip)
81 {
82     if (! _cairo_composite_rectangles_init (extents,
83 					    surface_extents,
84 					    op, source, clip))
85     {
86 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
87     }
88 
89     extents->mask = extents->bounded;
90     return CAIRO_STATUS_SUCCESS;
91 }
92 
93 static cairo_int_status_t
_cairo_composite_rectangles_intersect(cairo_composite_rectangles_t * extents)94 _cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents)
95 {
96     cairo_bool_t ret;
97 
98     ret = _cairo_rectangle_intersect (&extents->bounded, &extents->mask);
99     if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
100 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
101 
102     return CAIRO_STATUS_SUCCESS;
103 }
104 
105 cairo_int_status_t
_cairo_composite_rectangles_init_for_mask(cairo_composite_rectangles_t * extents,const cairo_rectangle_int_t * surface_extents,cairo_operator_t op,const cairo_pattern_t * source,const cairo_pattern_t * mask,cairo_clip_t * clip)106 _cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
107 					   const cairo_rectangle_int_t *surface_extents,
108 					   cairo_operator_t		 op,
109 					   const cairo_pattern_t	*source,
110 					   const cairo_pattern_t	*mask,
111 					   cairo_clip_t			*clip)
112 {
113     if (! _cairo_composite_rectangles_init (extents,
114 					    surface_extents,
115 					    op, source, clip))
116     {
117 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
118     }
119 
120     _cairo_pattern_get_extents (mask, &extents->mask);
121 
122     return _cairo_composite_rectangles_intersect (extents);
123 }
124 
125 cairo_int_status_t
_cairo_composite_rectangles_init_for_stroke(cairo_composite_rectangles_t * extents,const cairo_rectangle_int_t * surface_extents,cairo_operator_t op,const cairo_pattern_t * source,cairo_path_fixed_t * path,const cairo_stroke_style_t * style,const cairo_matrix_t * ctm,cairo_clip_t * clip)126 _cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
127 					     const cairo_rectangle_int_t *surface_extents,
128 					     cairo_operator_t		 op,
129 					     const cairo_pattern_t	*source,
130 					     cairo_path_fixed_t		*path,
131 					     const cairo_stroke_style_t	*style,
132 					     const cairo_matrix_t	*ctm,
133 					     cairo_clip_t		*clip)
134 {
135     if (! _cairo_composite_rectangles_init (extents,
136 					    surface_extents,
137 					    op, source, clip))
138     {
139 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
140     }
141 
142     _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &extents->mask);
143 
144     return _cairo_composite_rectangles_intersect (extents);
145 }
146 
147 cairo_int_status_t
_cairo_composite_rectangles_init_for_fill(cairo_composite_rectangles_t * extents,const cairo_rectangle_int_t * surface_extents,cairo_operator_t op,const cairo_pattern_t * source,cairo_path_fixed_t * path,cairo_clip_t * clip)148 _cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
149 					   const cairo_rectangle_int_t *surface_extents,
150 					   cairo_operator_t		 op,
151 					   const cairo_pattern_t	*source,
152 					   cairo_path_fixed_t		*path,
153 					   cairo_clip_t			*clip)
154 {
155     if (! _cairo_composite_rectangles_init (extents,
156 					    surface_extents,
157 					    op, source, clip))
158     {
159 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
160     }
161 
162     _cairo_path_fixed_approximate_fill_extents (path, &extents->mask);
163 
164     return _cairo_composite_rectangles_intersect (extents);
165 }
166 
167 cairo_int_status_t
_cairo_composite_rectangles_init_for_glyphs(cairo_composite_rectangles_t * extents,const cairo_rectangle_int_t * surface_extents,cairo_operator_t op,const cairo_pattern_t * source,cairo_scaled_font_t * scaled_font,cairo_glyph_t * glyphs,int num_glyphs,cairo_clip_t * clip,cairo_bool_t * overlap)168 _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
169 					     const cairo_rectangle_int_t *surface_extents,
170 					     cairo_operator_t		 op,
171 					     const cairo_pattern_t	*source,
172 					     cairo_scaled_font_t	*scaled_font,
173 					     cairo_glyph_t		*glyphs,
174 					     int			 num_glyphs,
175 					     cairo_clip_t		*clip,
176 					     cairo_bool_t		*overlap)
177 {
178     cairo_status_t status;
179 
180     if (! _cairo_composite_rectangles_init (extents,
181 					    surface_extents,
182 					    op, source, clip))
183     {
184 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
185     }
186 
187     status = _cairo_scaled_font_glyph_device_extents (scaled_font,
188 						      glyphs, num_glyphs,
189 						      &extents->mask,
190 						      overlap);
191     if (unlikely (status))
192 	return status;
193 
194     return _cairo_composite_rectangles_intersect (extents);
195 }
196