/work/workdir/UnpackedTarball/cairo/src/cairo-surface-offset.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* cairo - a vector graphics library with display and print output |
2 | | * |
3 | | * Copyright © 2005 Red Hat, Inc |
4 | | * Copyright © 2007 Adrian Johnson |
5 | | * Copyright © 2009 Chris Wilson |
6 | | * |
7 | | * This library is free software; you can redistribute it and/or |
8 | | * modify it either under the terms of the GNU Lesser General Public |
9 | | * License version 2.1 as published by the Free Software Foundation |
10 | | * (the "LGPL") or, at your option, under the terms of the Mozilla |
11 | | * Public License Version 1.1 (the "MPL"). If you do not alter this |
12 | | * notice, a recipient may use your version of this file under either |
13 | | * the MPL or the LGPL. |
14 | | * |
15 | | * You should have received a copy of the LGPL along with this library |
16 | | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
17 | | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
18 | | * You should have received a copy of the MPL along with this library |
19 | | * in the file COPYING-MPL-1.1 |
20 | | * |
21 | | * The contents of this file are subject to the Mozilla Public License |
22 | | * Version 1.1 (the "License"); you may not use this file except in |
23 | | * compliance with the License. You may obtain a copy of the License at |
24 | | * http://www.mozilla.org/MPL/ |
25 | | * |
26 | | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
27 | | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
28 | | * the specific language governing rights and limitations. |
29 | | * |
30 | | * The Original Code is the cairo graphics library. |
31 | | * |
32 | | * The Initial Developer of the Original Code is Red Hat, Inc. |
33 | | * |
34 | | * Contributor(s): |
35 | | * Chris Wilson <chris@chris-wilson.co.uk> |
36 | | */ |
37 | | |
38 | | #include "cairoint.h" |
39 | | |
40 | | #include "cairo-clip-inline.h" |
41 | | #include "cairo-error-private.h" |
42 | | #include "cairo-pattern-private.h" |
43 | | #include "cairo-surface-offset-private.h" |
44 | | |
45 | | /* A collection of routines to facilitate drawing to an alternate surface. */ |
46 | | |
47 | | static void |
48 | | _copy_transformed_pattern (cairo_pattern_t *pattern, |
49 | | const cairo_pattern_t *original, |
50 | | const cairo_matrix_t *ctm_inverse) |
51 | 0 | { |
52 | 0 | _cairo_pattern_init_static_copy (pattern, original); |
53 | |
|
54 | 0 | if (! _cairo_matrix_is_identity (ctm_inverse)) |
55 | 0 | _cairo_pattern_transform (pattern, ctm_inverse); |
56 | 0 | } |
57 | | |
58 | | cairo_status_t |
59 | | _cairo_surface_offset_paint (cairo_surface_t *target, |
60 | | int x, int y, |
61 | | cairo_operator_t op, |
62 | | const cairo_pattern_t *source, |
63 | | const cairo_clip_t *clip) |
64 | 0 | { |
65 | 0 | cairo_status_t status; |
66 | 0 | cairo_clip_t *dev_clip = (cairo_clip_t *) clip; |
67 | 0 | cairo_pattern_union_t source_copy; |
68 | |
|
69 | 0 | if (unlikely (target->status)) |
70 | 0 | return target->status; |
71 | | |
72 | 0 | if (_cairo_clip_is_all_clipped (clip)) |
73 | 0 | return CAIRO_STATUS_SUCCESS; |
74 | | |
75 | 0 | if (x | y) { |
76 | 0 | cairo_matrix_t m; |
77 | |
|
78 | 0 | dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y); |
79 | |
|
80 | 0 | cairo_matrix_init_translate (&m, x, y); |
81 | 0 | _copy_transformed_pattern (&source_copy.base, source, &m); |
82 | 0 | source = &source_copy.base; |
83 | 0 | } |
84 | |
|
85 | 0 | status = _cairo_surface_paint (target, op, source, dev_clip); |
86 | |
|
87 | 0 | if (dev_clip != clip) |
88 | 0 | _cairo_clip_destroy (dev_clip); |
89 | |
|
90 | 0 | return status; |
91 | 0 | } |
92 | | |
93 | | cairo_status_t |
94 | | _cairo_surface_offset_mask (cairo_surface_t *target, |
95 | | int x, int y, |
96 | | cairo_operator_t op, |
97 | | const cairo_pattern_t *source, |
98 | | const cairo_pattern_t *mask, |
99 | | const cairo_clip_t *clip) |
100 | 0 | { |
101 | 0 | cairo_status_t status; |
102 | 0 | cairo_clip_t *dev_clip = (cairo_clip_t *) clip; |
103 | 0 | cairo_pattern_union_t source_copy; |
104 | 0 | cairo_pattern_union_t mask_copy; |
105 | |
|
106 | 0 | if (unlikely (target->status)) |
107 | 0 | return target->status; |
108 | | |
109 | 0 | if (_cairo_clip_is_all_clipped (clip)) |
110 | 0 | return CAIRO_STATUS_SUCCESS; |
111 | | |
112 | 0 | if (x | y) { |
113 | 0 | cairo_matrix_t m; |
114 | |
|
115 | 0 | dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y); |
116 | |
|
117 | 0 | cairo_matrix_init_translate (&m, x, y); |
118 | 0 | _copy_transformed_pattern (&source_copy.base, source, &m); |
119 | 0 | _copy_transformed_pattern (&mask_copy.base, mask, &m); |
120 | 0 | source = &source_copy.base; |
121 | 0 | mask = &mask_copy.base; |
122 | 0 | } |
123 | |
|
124 | 0 | status = _cairo_surface_mask (target, op, |
125 | 0 | source, mask, |
126 | 0 | dev_clip); |
127 | |
|
128 | 0 | if (dev_clip != clip) |
129 | 0 | _cairo_clip_destroy (dev_clip); |
130 | |
|
131 | 0 | return status; |
132 | 0 | } |
133 | | |
134 | | cairo_status_t |
135 | | _cairo_surface_offset_stroke (cairo_surface_t *surface, |
136 | | int x, int y, |
137 | | cairo_operator_t op, |
138 | | const cairo_pattern_t *source, |
139 | | const cairo_path_fixed_t *path, |
140 | | const cairo_stroke_style_t*stroke_style, |
141 | | const cairo_matrix_t *ctm, |
142 | | const cairo_matrix_t *ctm_inverse, |
143 | | double tolerance, |
144 | | cairo_antialias_t antialias, |
145 | | const cairo_clip_t *clip) |
146 | 16 | { |
147 | 16 | cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path; |
148 | 16 | cairo_clip_t *dev_clip = (cairo_clip_t *) clip; |
149 | 16 | cairo_matrix_t dev_ctm = *ctm; |
150 | 16 | cairo_matrix_t dev_ctm_inverse = *ctm_inverse; |
151 | 16 | cairo_pattern_union_t source_copy; |
152 | 16 | cairo_status_t status; |
153 | | |
154 | 16 | if (unlikely (surface->status)) |
155 | 0 | return surface->status; |
156 | | |
157 | 16 | if (_cairo_clip_is_all_clipped (clip)) |
158 | 16 | return CAIRO_STATUS_SUCCESS; |
159 | | |
160 | 0 | if (x | y) { |
161 | 0 | cairo_matrix_t m; |
162 | |
|
163 | 0 | dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y); |
164 | |
|
165 | 0 | status = _cairo_path_fixed_init_copy (&path_copy, dev_path); |
166 | 0 | if (unlikely (status)) |
167 | 0 | goto FINISH; |
168 | | |
169 | 0 | _cairo_path_fixed_translate (&path_copy, |
170 | 0 | _cairo_fixed_from_int (-x), |
171 | 0 | _cairo_fixed_from_int (-y)); |
172 | 0 | dev_path = &path_copy; |
173 | |
|
174 | 0 | cairo_matrix_init_translate (&m, -x, -y); |
175 | 0 | cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m); |
176 | |
|
177 | 0 | cairo_matrix_init_translate (&m, x, y); |
178 | 0 | _copy_transformed_pattern (&source_copy.base, source, &m); |
179 | 0 | source = &source_copy.base; |
180 | 0 | cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse); |
181 | 0 | } |
182 | | |
183 | 0 | status = _cairo_surface_stroke (surface, op, source, |
184 | 0 | dev_path, stroke_style, |
185 | 0 | &dev_ctm, &dev_ctm_inverse, |
186 | 0 | tolerance, antialias, |
187 | 0 | dev_clip); |
188 | |
|
189 | 0 | FINISH: |
190 | 0 | if (dev_path != path) |
191 | 0 | _cairo_path_fixed_fini (dev_path); |
192 | 0 | if (dev_clip != clip) |
193 | 0 | _cairo_clip_destroy (dev_clip); |
194 | |
|
195 | 0 | return status; |
196 | 0 | } |
197 | | |
198 | | cairo_status_t |
199 | | _cairo_surface_offset_fill (cairo_surface_t *surface, |
200 | | int x, int y, |
201 | | cairo_operator_t op, |
202 | | const cairo_pattern_t*source, |
203 | | const cairo_path_fixed_t *path, |
204 | | cairo_fill_rule_t fill_rule, |
205 | | double tolerance, |
206 | | cairo_antialias_t antialias, |
207 | | const cairo_clip_t *clip) |
208 | 0 | { |
209 | 0 | cairo_status_t status; |
210 | 0 | cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path; |
211 | 0 | cairo_clip_t *dev_clip = (cairo_clip_t *) clip; |
212 | 0 | cairo_pattern_union_t source_copy; |
213 | |
|
214 | 0 | if (unlikely (surface->status)) |
215 | 0 | return surface->status; |
216 | | |
217 | 0 | if (_cairo_clip_is_all_clipped (clip)) |
218 | 0 | return CAIRO_STATUS_SUCCESS; |
219 | | |
220 | 0 | if (x | y) { |
221 | 0 | cairo_matrix_t m; |
222 | |
|
223 | 0 | dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y); |
224 | |
|
225 | 0 | status = _cairo_path_fixed_init_copy (&path_copy, dev_path); |
226 | 0 | if (unlikely (status)) |
227 | 0 | goto FINISH; |
228 | | |
229 | 0 | _cairo_path_fixed_translate (&path_copy, |
230 | 0 | _cairo_fixed_from_int (-x), |
231 | 0 | _cairo_fixed_from_int (-y)); |
232 | 0 | dev_path = &path_copy; |
233 | |
|
234 | 0 | cairo_matrix_init_translate (&m, x, y); |
235 | 0 | _copy_transformed_pattern (&source_copy.base, source, &m); |
236 | 0 | source = &source_copy.base; |
237 | 0 | } |
238 | | |
239 | 0 | status = _cairo_surface_fill (surface, op, source, |
240 | 0 | dev_path, fill_rule, |
241 | 0 | tolerance, antialias, |
242 | 0 | dev_clip); |
243 | |
|
244 | 0 | FINISH: |
245 | 0 | if (dev_path != path) |
246 | 0 | _cairo_path_fixed_fini (dev_path); |
247 | 0 | if (dev_clip != clip) |
248 | 0 | _cairo_clip_destroy (dev_clip); |
249 | |
|
250 | 0 | return status; |
251 | 0 | } |
252 | | |
253 | | cairo_status_t |
254 | | _cairo_surface_offset_glyphs (cairo_surface_t *surface, |
255 | | int x, int y, |
256 | | cairo_operator_t op, |
257 | | const cairo_pattern_t *source, |
258 | | cairo_scaled_font_t *scaled_font, |
259 | | cairo_glyph_t *glyphs, |
260 | | int num_glyphs, |
261 | | const cairo_clip_t *clip) |
262 | 0 | { |
263 | 0 | cairo_status_t status; |
264 | 0 | cairo_clip_t *dev_clip = (cairo_clip_t *) clip; |
265 | 0 | cairo_pattern_union_t source_copy; |
266 | 0 | cairo_glyph_t *dev_glyphs; |
267 | 0 | int i; |
268 | |
|
269 | 0 | if (unlikely (surface->status)) |
270 | 0 | return surface->status; |
271 | | |
272 | 0 | if (_cairo_clip_is_all_clipped (clip)) |
273 | 0 | return CAIRO_STATUS_SUCCESS; |
274 | | |
275 | 0 | dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); |
276 | 0 | if (dev_glyphs == NULL) |
277 | 0 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
278 | | |
279 | 0 | memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs); |
280 | |
|
281 | 0 | if (x | y) { |
282 | 0 | cairo_matrix_t m; |
283 | |
|
284 | 0 | dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y); |
285 | |
|
286 | 0 | cairo_matrix_init_translate (&m, x, y); |
287 | 0 | _copy_transformed_pattern (&source_copy.base, source, &m); |
288 | 0 | source = &source_copy.base; |
289 | |
|
290 | 0 | for (i = 0; i < num_glyphs; i++) { |
291 | 0 | dev_glyphs[i].x -= x; |
292 | 0 | dev_glyphs[i].y -= y; |
293 | 0 | } |
294 | 0 | } |
295 | |
|
296 | 0 | status = _cairo_surface_show_text_glyphs (surface, op, source, |
297 | 0 | NULL, 0, |
298 | 0 | dev_glyphs, num_glyphs, |
299 | 0 | NULL, 0, 0, |
300 | 0 | scaled_font, |
301 | 0 | dev_clip); |
302 | |
|
303 | 0 | if (dev_clip != clip) |
304 | 0 | _cairo_clip_destroy (dev_clip); |
305 | 0 | free (dev_glyphs); |
306 | |
|
307 | 0 | return status; |
308 | 0 | } |