Tizen 2.0 Release
[profile/ivi/cairo.git] / src / cairo-surface-offset.c
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 {
52     _cairo_pattern_init_static_copy (pattern, original);
53
54     if (! _cairo_matrix_is_identity (ctm_inverse))
55         _cairo_pattern_transform (pattern, ctm_inverse);
56 }
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 {
65     cairo_status_t status;
66     cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
67     cairo_pattern_union_t source_copy;
68
69     if (unlikely (target->status))
70         return target->status;
71
72     if (_cairo_clip_is_all_clipped (clip))
73         return CAIRO_STATUS_SUCCESS;
74
75     if (x | y) {
76         cairo_matrix_t m;
77
78         dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
79
80         cairo_matrix_init_translate (&m, x, y);
81         _copy_transformed_pattern (&source_copy.base, source, &m);
82         source = &source_copy.base;
83     }
84
85     status = _cairo_surface_paint (target, op, source, dev_clip);
86
87     if (dev_clip != clip)
88         _cairo_clip_destroy (dev_clip);
89
90     return status;
91 }
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 {
101     cairo_status_t status;
102     cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
103     cairo_pattern_union_t source_copy;
104     cairo_pattern_union_t mask_copy;
105
106     if (unlikely (target->status))
107         return target->status;
108
109     if (_cairo_clip_is_all_clipped (clip))
110         return CAIRO_STATUS_SUCCESS;
111
112     if (x | y) {
113         cairo_matrix_t m;
114
115         dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
116
117         cairo_matrix_init_translate (&m, x, y);
118         _copy_transformed_pattern (&source_copy.base, source, &m);
119         _copy_transformed_pattern (&mask_copy.base, mask, &m);
120         source = &source_copy.base;
121         mask = &mask_copy.base;
122     }
123
124     status = _cairo_surface_mask (target, op,
125                                   source, mask,
126                                   dev_clip);
127
128     if (dev_clip != clip)
129         _cairo_clip_destroy (dev_clip);
130
131     return status;
132 }
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 {
147     cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path;
148     cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
149     cairo_matrix_t dev_ctm = *ctm;
150     cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
151     cairo_pattern_union_t source_copy;
152     cairo_status_t status;
153
154     if (unlikely (surface->status))
155         return surface->status;
156
157     if (_cairo_clip_is_all_clipped (clip))
158         return CAIRO_STATUS_SUCCESS;
159
160     if (x | y) {
161         cairo_matrix_t m;
162
163         dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
164
165         status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
166         if (unlikely (status))
167             goto FINISH;
168
169         _cairo_path_fixed_translate (&path_copy,
170                                      _cairo_fixed_from_int (-x),
171                                      _cairo_fixed_from_int (-y));
172         dev_path = &path_copy;
173
174         cairo_matrix_init_translate (&m, -x, -y);
175         cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
176
177         cairo_matrix_init_translate (&m, x, y);
178         _copy_transformed_pattern (&source_copy.base, source, &m);
179         source = &source_copy.base;
180         cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse);
181     }
182
183     status = _cairo_surface_stroke (surface, op, source,
184                                     dev_path, stroke_style,
185                                     &dev_ctm, &dev_ctm_inverse,
186                                     tolerance, antialias,
187                                     dev_clip);
188
189 FINISH:
190     if (dev_path != path)
191         _cairo_path_fixed_fini (dev_path);
192     if (dev_clip != clip)
193         _cairo_clip_destroy (dev_clip);
194
195     return status;
196 }
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 {
209     cairo_status_t status;
210     cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path;
211     cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
212     cairo_pattern_union_t source_copy;
213
214     if (unlikely (surface->status))
215         return surface->status;
216
217     if (_cairo_clip_is_all_clipped (clip))
218         return CAIRO_STATUS_SUCCESS;
219
220     if (x | y) {
221         cairo_matrix_t m;
222
223         dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
224
225         status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
226         if (unlikely (status))
227             goto FINISH;
228
229         _cairo_path_fixed_translate (&path_copy,
230                                      _cairo_fixed_from_int (-x),
231                                      _cairo_fixed_from_int (-y));
232         dev_path = &path_copy;
233
234         cairo_matrix_init_translate (&m, x, y);
235         _copy_transformed_pattern (&source_copy.base, source, &m);
236         source = &source_copy.base;
237     }
238
239     status = _cairo_surface_fill (surface, op, source,
240                                   dev_path, fill_rule,
241                                   tolerance, antialias,
242                                   dev_clip);
243
244 FINISH:
245     if (dev_path != path)
246         _cairo_path_fixed_fini (dev_path);
247     if (dev_clip != clip)
248         _cairo_clip_destroy (dev_clip);
249
250     return status;
251 }
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 {
263     cairo_status_t status;
264     cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
265     cairo_pattern_union_t source_copy;
266     cairo_glyph_t *dev_glyphs;
267     int i;
268
269     if (unlikely (surface->status))
270         return surface->status;
271
272     if (_cairo_clip_is_all_clipped (clip))
273         return CAIRO_STATUS_SUCCESS;
274
275     dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
276     if (dev_glyphs == NULL)
277         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
278
279     memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
280
281     if (x | y) {
282         cairo_matrix_t m;
283
284         dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
285
286         cairo_matrix_init_translate (&m, x, y);
287         _copy_transformed_pattern (&source_copy.base, source, &m);
288         source = &source_copy.base;
289
290         for (i = 0; i < num_glyphs; i++) {
291             dev_glyphs[i].x -= x;
292             dev_glyphs[i].y -= y;
293         }
294     }
295
296     status = _cairo_surface_show_text_glyphs (surface, op, source,
297                                               NULL, 0,
298                                               dev_glyphs, num_glyphs,
299                                               NULL, 0, 0,
300                                               scaled_font,
301                                               dev_clip);
302
303     if (dev_clip != clip)
304         _cairo_clip_destroy (dev_clip);
305     free (dev_glyphs);
306
307     return status;
308 }