1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2005 Red Hat, Inc
4 * Copyright © 2007 Adrian Johnson
5 * Copyright © 2009 Chris Wilson
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.
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
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/
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.
30 * The Original Code is the cairo graphics library.
32 * The Initial Developer of the Original Code is Red Hat, Inc.
35 * Chris Wilson <chris@chris-wilson.co.uk>
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"
45 /* A collection of routines to facilitate drawing to an alternate surface. */
48 _copy_transformed_pattern (cairo_pattern_t
*pattern
,
49 const cairo_pattern_t
*original
,
50 const cairo_matrix_t
*ctm_inverse
)
52 _cairo_pattern_init_static_copy (pattern
, original
);
54 if (! _cairo_matrix_is_identity (ctm_inverse
))
55 _cairo_pattern_transform (pattern
, ctm_inverse
);
59 _cairo_surface_offset_paint (cairo_surface_t
*target
,
62 const cairo_pattern_t
*source
,
63 const cairo_clip_t
*clip
)
65 cairo_status_t status
;
66 cairo_clip_t
*dev_clip
= (cairo_clip_t
*) clip
;
67 cairo_pattern_union_t source_copy
;
69 if (unlikely (target
->status
))
70 return target
->status
;
72 if (_cairo_clip_is_all_clipped (clip
))
73 return CAIRO_STATUS_SUCCESS
;
78 dev_clip
= _cairo_clip_copy_with_translation (clip
, -x
, -y
);
80 cairo_matrix_init_translate (&m
, x
, y
);
81 _copy_transformed_pattern (&source_copy
.base
, source
, &m
);
82 source
= &source_copy
.base
;
85 status
= _cairo_surface_paint (target
, op
, source
, dev_clip
);
88 _cairo_clip_destroy (dev_clip
);
94 _cairo_surface_offset_mask (cairo_surface_t
*target
,
97 const cairo_pattern_t
*source
,
98 const cairo_pattern_t
*mask
,
99 const cairo_clip_t
*clip
)
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
;
106 if (unlikely (target
->status
))
107 return target
->status
;
109 if (_cairo_clip_is_all_clipped (clip
))
110 return CAIRO_STATUS_SUCCESS
;
115 dev_clip
= _cairo_clip_copy_with_translation (clip
, -x
, -y
);
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
;
124 status
= _cairo_surface_mask (target
, op
,
128 if (dev_clip
!= clip
)
129 _cairo_clip_destroy (dev_clip
);
135 _cairo_surface_offset_stroke (cairo_surface_t
*surface
,
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
,
144 cairo_antialias_t antialias
,
145 const cairo_clip_t
*clip
)
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
;
154 if (unlikely (surface
->status
))
155 return surface
->status
;
157 if (_cairo_clip_is_all_clipped (clip
))
158 return CAIRO_STATUS_SUCCESS
;
163 dev_clip
= _cairo_clip_copy_with_translation (clip
, -x
, -y
);
165 status
= _cairo_path_fixed_init_copy (&path_copy
, dev_path
);
166 if (unlikely (status
))
169 _cairo_path_fixed_translate (&path_copy
,
170 _cairo_fixed_from_int (-x
),
171 _cairo_fixed_from_int (-y
));
172 dev_path
= &path_copy
;
174 cairo_matrix_init_translate (&m
, -x
, -y
);
175 cairo_matrix_multiply (&dev_ctm
, &dev_ctm
, &m
);
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
);
183 status
= _cairo_surface_stroke (surface
, op
, source
,
184 dev_path
, stroke_style
,
185 &dev_ctm
, &dev_ctm_inverse
,
186 tolerance
, antialias
,
190 if (dev_path
!= path
)
191 _cairo_path_fixed_fini (dev_path
);
192 if (dev_clip
!= clip
)
193 _cairo_clip_destroy (dev_clip
);
199 _cairo_surface_offset_fill (cairo_surface_t
*surface
,
202 const cairo_pattern_t
*source
,
203 const cairo_path_fixed_t
*path
,
204 cairo_fill_rule_t fill_rule
,
206 cairo_antialias_t antialias
,
207 const cairo_clip_t
*clip
)
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
;
214 if (unlikely (surface
->status
))
215 return surface
->status
;
217 if (_cairo_clip_is_all_clipped (clip
))
218 return CAIRO_STATUS_SUCCESS
;
223 dev_clip
= _cairo_clip_copy_with_translation (clip
, -x
, -y
);
225 status
= _cairo_path_fixed_init_copy (&path_copy
, dev_path
);
226 if (unlikely (status
))
229 _cairo_path_fixed_translate (&path_copy
,
230 _cairo_fixed_from_int (-x
),
231 _cairo_fixed_from_int (-y
));
232 dev_path
= &path_copy
;
234 cairo_matrix_init_translate (&m
, x
, y
);
235 _copy_transformed_pattern (&source_copy
.base
, source
, &m
);
236 source
= &source_copy
.base
;
239 status
= _cairo_surface_fill (surface
, op
, source
,
241 tolerance
, antialias
,
245 if (dev_path
!= path
)
246 _cairo_path_fixed_fini (dev_path
);
247 if (dev_clip
!= clip
)
248 _cairo_clip_destroy (dev_clip
);
254 _cairo_surface_offset_glyphs (cairo_surface_t
*surface
,
257 const cairo_pattern_t
*source
,
258 cairo_scaled_font_t
*scaled_font
,
259 cairo_glyph_t
*glyphs
,
261 const cairo_clip_t
*clip
)
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
;
269 if (unlikely (surface
->status
))
270 return surface
->status
;
272 if (_cairo_clip_is_all_clipped (clip
))
273 return CAIRO_STATUS_SUCCESS
;
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
);
279 memcpy (dev_glyphs
, glyphs
, sizeof (cairo_glyph_t
) * num_glyphs
);
284 dev_clip
= _cairo_clip_copy_with_translation (clip
, -x
, -y
);
286 cairo_matrix_init_translate (&m
, x
, y
);
287 _copy_transformed_pattern (&source_copy
.base
, source
, &m
);
288 source
= &source_copy
.base
;
290 for (i
= 0; i
< num_glyphs
; i
++) {
291 dev_glyphs
[i
].x
-= x
;
292 dev_glyphs
[i
].y
-= y
;
296 status
= _cairo_surface_show_text_glyphs (surface
, op
, source
,
298 dev_glyphs
, num_glyphs
,
303 if (dev_clip
!= clip
)
304 _cairo_clip_destroy (dev_clip
);