Line data Source code
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-error-private.h"
41 : #include "cairo-surface-offset-private.h"
42 :
43 : /* A collection of routines to facilitate drawing to an alternate surface. */
44 :
45 : static void
46 0 : _copy_transformed_pattern (cairo_pattern_t *pattern,
47 : const cairo_pattern_t *original,
48 : const cairo_matrix_t *ctm_inverse)
49 : {
50 0 : _cairo_pattern_init_static_copy (pattern, original);
51 :
52 0 : if (! _cairo_matrix_is_identity (ctm_inverse))
53 0 : _cairo_pattern_transform (pattern, ctm_inverse);
54 0 : }
55 :
56 : cairo_status_t
57 0 : _cairo_surface_offset_paint (cairo_surface_t *target,
58 : int x, int y,
59 : cairo_operator_t op,
60 : const cairo_pattern_t *source,
61 : cairo_clip_t *clip)
62 : {
63 : cairo_status_t status;
64 0 : cairo_clip_t clip_copy, *dev_clip = clip;
65 : cairo_pattern_union_t source_copy;
66 :
67 0 : if (unlikely (target->status))
68 0 : return target->status;
69 :
70 0 : if (clip && clip->all_clipped)
71 0 : return CAIRO_STATUS_SUCCESS;
72 :
73 0 : if (x | y) {
74 : cairo_matrix_t m;
75 :
76 0 : if (clip != NULL) {
77 0 : cairo_matrix_init_translate (&m, -x, -y);
78 0 : status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
79 0 : if (unlikely (status))
80 0 : goto FINISH;
81 :
82 0 : dev_clip = &clip_copy;
83 : }
84 :
85 0 : cairo_matrix_init_translate (&m, x, y);
86 0 : _copy_transformed_pattern (&source_copy.base, source, &m);
87 0 : source = &source_copy.base;
88 : }
89 :
90 0 : status = _cairo_surface_paint (target, op, source, dev_clip);
91 :
92 : FINISH:
93 0 : if (dev_clip != clip)
94 0 : _cairo_clip_reset (dev_clip);
95 :
96 0 : return status;
97 : }
98 :
99 : cairo_status_t
100 0 : _cairo_surface_offset_mask (cairo_surface_t *target,
101 : int x, int y,
102 : cairo_operator_t op,
103 : const cairo_pattern_t *source,
104 : const cairo_pattern_t *mask,
105 : cairo_clip_t *clip)
106 : {
107 : cairo_status_t status;
108 0 : cairo_clip_t clip_copy, *dev_clip = clip;
109 : cairo_pattern_union_t source_copy;
110 : cairo_pattern_union_t mask_copy;
111 :
112 0 : if (unlikely (target->status))
113 0 : return target->status;
114 :
115 0 : if (clip && clip->all_clipped)
116 0 : return CAIRO_STATUS_SUCCESS;
117 :
118 0 : if (x | y) {
119 : cairo_matrix_t m;
120 :
121 0 : if (clip != NULL) {
122 0 : cairo_matrix_init_translate (&m, -x, -y);
123 0 : status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
124 0 : if (unlikely (status))
125 0 : goto FINISH;
126 :
127 0 : dev_clip = &clip_copy;
128 : }
129 :
130 0 : cairo_matrix_init_translate (&m, x, y);
131 0 : _copy_transformed_pattern (&source_copy.base, source, &m);
132 0 : _copy_transformed_pattern (&mask_copy.base, mask, &m);
133 0 : source = &source_copy.base;
134 0 : mask = &mask_copy.base;
135 : }
136 :
137 0 : status = _cairo_surface_mask (target, op,
138 : source, mask,
139 : dev_clip);
140 :
141 : FINISH:
142 0 : if (dev_clip != clip)
143 0 : _cairo_clip_reset (dev_clip);
144 :
145 0 : return status;
146 : }
147 :
148 : cairo_status_t
149 0 : _cairo_surface_offset_stroke (cairo_surface_t *surface,
150 : int x, int y,
151 : cairo_operator_t op,
152 : const cairo_pattern_t *source,
153 : cairo_path_fixed_t *path,
154 : const cairo_stroke_style_t*stroke_style,
155 : const cairo_matrix_t *ctm,
156 : const cairo_matrix_t *ctm_inverse,
157 : double tolerance,
158 : cairo_antialias_t antialias,
159 : cairo_clip_t *clip)
160 : {
161 0 : cairo_path_fixed_t path_copy, *dev_path = path;
162 0 : cairo_clip_t clip_copy, *dev_clip = clip;
163 0 : cairo_matrix_t dev_ctm = *ctm;
164 0 : cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
165 : cairo_pattern_union_t source_copy;
166 : cairo_status_t status;
167 :
168 0 : if (unlikely (surface->status))
169 0 : return surface->status;
170 :
171 0 : if (clip && clip->all_clipped)
172 0 : return CAIRO_STATUS_SUCCESS;
173 :
174 0 : if (x | y) {
175 : cairo_matrix_t m;
176 :
177 0 : status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
178 0 : if (unlikely (status))
179 0 : goto FINISH;
180 :
181 0 : _cairo_path_fixed_translate (&path_copy,
182 : _cairo_fixed_from_int (-x),
183 : _cairo_fixed_from_int (-y));
184 0 : dev_path = &path_copy;
185 :
186 0 : cairo_matrix_init_translate (&m, -x, -y);
187 0 : cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
188 0 : if (clip != NULL) {
189 0 : status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
190 0 : if (unlikely (status))
191 0 : goto FINISH;
192 :
193 0 : dev_clip = &clip_copy;
194 : }
195 :
196 0 : cairo_matrix_init_translate (&m, x, y);
197 0 : _copy_transformed_pattern (&source_copy.base, source, &m);
198 0 : source = &source_copy.base;
199 0 : cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse);
200 : }
201 :
202 0 : status = _cairo_surface_stroke (surface, op, source,
203 : dev_path, stroke_style,
204 : &dev_ctm, &dev_ctm_inverse,
205 : tolerance, antialias,
206 : dev_clip);
207 :
208 : FINISH:
209 0 : if (dev_path != path)
210 0 : _cairo_path_fixed_fini (dev_path);
211 0 : if (dev_clip != clip)
212 0 : _cairo_clip_reset (dev_clip);
213 :
214 0 : return status;
215 : }
216 :
217 : cairo_status_t
218 0 : _cairo_surface_offset_fill (cairo_surface_t *surface,
219 : int x, int y,
220 : cairo_operator_t op,
221 : const cairo_pattern_t*source,
222 : cairo_path_fixed_t *path,
223 : cairo_fill_rule_t fill_rule,
224 : double tolerance,
225 : cairo_antialias_t antialias,
226 : cairo_clip_t *clip)
227 : {
228 : cairo_status_t status;
229 0 : cairo_path_fixed_t path_copy, *dev_path = path;
230 0 : cairo_clip_t clip_copy, *dev_clip = clip;
231 : cairo_pattern_union_t source_copy;
232 :
233 0 : if (unlikely (surface->status))
234 0 : return surface->status;
235 :
236 0 : if (clip && clip->all_clipped)
237 0 : return CAIRO_STATUS_SUCCESS;
238 :
239 0 : if (x | y) {
240 : cairo_matrix_t m;
241 :
242 0 : status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
243 0 : if (unlikely (status))
244 0 : goto FINISH;
245 :
246 0 : _cairo_path_fixed_translate (&path_copy,
247 : _cairo_fixed_from_int (-x),
248 : _cairo_fixed_from_int (-y));
249 0 : dev_path = &path_copy;
250 :
251 0 : if (clip != NULL) {
252 0 : cairo_matrix_init_translate (&m, -x, -y);
253 0 : status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
254 0 : if (unlikely (status))
255 0 : goto FINISH;
256 :
257 0 : dev_clip = &clip_copy;
258 : }
259 :
260 0 : cairo_matrix_init_translate (&m, x, y);
261 0 : _copy_transformed_pattern (&source_copy.base, source, &m);
262 0 : source = &source_copy.base;
263 : }
264 :
265 0 : status = _cairo_surface_fill (surface, op, source,
266 : dev_path, fill_rule,
267 : tolerance, antialias,
268 : dev_clip);
269 :
270 : FINISH:
271 0 : if (dev_path != path)
272 0 : _cairo_path_fixed_fini (dev_path);
273 0 : if (dev_clip != clip)
274 0 : _cairo_clip_reset (dev_clip);
275 :
276 0 : return status;
277 : }
278 :
279 : cairo_status_t
280 0 : _cairo_surface_offset_glyphs (cairo_surface_t *surface,
281 : int x, int y,
282 : cairo_operator_t op,
283 : const cairo_pattern_t *source,
284 : cairo_scaled_font_t *scaled_font,
285 : cairo_glyph_t *glyphs,
286 : int num_glyphs,
287 : cairo_clip_t *clip)
288 : {
289 : cairo_status_t status;
290 0 : cairo_clip_t clip_copy, *dev_clip = clip;
291 : cairo_pattern_union_t source_copy;
292 : cairo_glyph_t *dev_glyphs;
293 : int i;
294 :
295 0 : if (unlikely (surface->status))
296 0 : return surface->status;
297 :
298 0 : if (clip && clip->all_clipped)
299 0 : return CAIRO_STATUS_SUCCESS;
300 :
301 0 : dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
302 0 : if (dev_glyphs == NULL)
303 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
304 :
305 0 : memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
306 :
307 0 : if (x | y) {
308 : cairo_matrix_t m;
309 :
310 0 : if (clip != NULL) {
311 0 : cairo_matrix_init_translate (&m, -x, -y);
312 0 : status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
313 0 : if (unlikely (status))
314 0 : goto FINISH;
315 :
316 0 : dev_clip = &clip_copy;
317 : }
318 :
319 0 : cairo_matrix_init_translate (&m, x, y);
320 0 : _copy_transformed_pattern (&source_copy.base, source, &m);
321 0 : source = &source_copy.base;
322 :
323 0 : for (i = 0; i < num_glyphs; i++) {
324 0 : dev_glyphs[i].x -= x;
325 0 : dev_glyphs[i].y -= y;
326 : }
327 : }
328 :
329 0 : status = _cairo_surface_show_text_glyphs (surface, op, source,
330 : NULL, 0,
331 : dev_glyphs, num_glyphs,
332 : NULL, 0, 0,
333 : scaled_font,
334 : dev_clip);
335 :
336 : FINISH:
337 0 : if (dev_clip != clip)
338 0 : _cairo_clip_reset (dev_clip);
339 0 : free (dev_glyphs);
340 :
341 0 : return status;
342 : }
|