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