/work/workdir/UnpackedTarball/cairo/src/cairo-clip-surface.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ |
2 | | /* cairo - a vector graphics library with display and print output |
3 | | * |
4 | | * Copyright © 2002 University of Southern California |
5 | | * Copyright © 2005 Red Hat, Inc. |
6 | | * Copyright © 2009 Chris Wilson |
7 | | * |
8 | | * This library is free software; you can redistribute it and/or |
9 | | * modify it either under the terms of the GNU Lesser General Public |
10 | | * License version 2.1 as published by the Free Software Foundation |
11 | | * (the "LGPL") or, at your option, under the terms of the Mozilla |
12 | | * Public License Version 1.1 (the "MPL"). If you do not alter this |
13 | | * notice, a recipient may use your version of this file under either |
14 | | * the MPL or the LGPL. |
15 | | * |
16 | | * You should have received a copy of the LGPL along with this library |
17 | | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
19 | | * You should have received a copy of the MPL along with this library |
20 | | * in the file COPYING-MPL-1.1 |
21 | | * |
22 | | * The contents of this file are subject to the Mozilla Public License |
23 | | * Version 1.1 (the "License"); you may not use this file except in |
24 | | * compliance with the License. You may obtain a copy of the License at |
25 | | * http://www.mozilla.org/MPL/ |
26 | | * |
27 | | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
28 | | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
29 | | * the specific language governing rights and limitations. |
30 | | * |
31 | | * The Original Code is the cairo graphics library. |
32 | | * |
33 | | * The Initial Developer of the Original Code is University of Southern |
34 | | * California. |
35 | | * |
36 | | * Contributor(s): |
37 | | * Carl D. Worth <cworth@cworth.org> |
38 | | * Kristian Høgsberg <krh@redhat.com> |
39 | | * Chris Wilson <chris@chris-wilson.co.uk> |
40 | | */ |
41 | | |
42 | | #include "cairoint.h" |
43 | | #include "cairo-clip-private.h" |
44 | | #include "cairo-error-private.h" |
45 | | #include "cairo-freed-pool-private.h" |
46 | | #include "cairo-gstate-private.h" |
47 | | #include "cairo-path-fixed-private.h" |
48 | | #include "cairo-pattern-private.h" |
49 | | #include "cairo-composite-rectangles-private.h" |
50 | | #include "cairo-region-private.h" |
51 | | |
52 | | cairo_status_t |
53 | | _cairo_clip_combine_with_surface (const cairo_clip_t *clip, |
54 | | cairo_surface_t *dst, |
55 | | int dst_x, int dst_y) |
56 | 0 | { |
57 | 0 | cairo_clip_path_t *copy_path; |
58 | 0 | cairo_clip_path_t *clip_path; |
59 | 0 | cairo_clip_t *copy; |
60 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
61 | |
|
62 | 0 | copy = _cairo_clip_copy_with_translation (clip, -dst_x, -dst_y); |
63 | 0 | copy_path = copy->path; |
64 | 0 | copy->path = NULL; |
65 | |
|
66 | 0 | if (copy->boxes) { |
67 | 0 | status = _cairo_surface_paint (dst, |
68 | 0 | CAIRO_OPERATOR_IN, |
69 | 0 | &_cairo_pattern_white.base, |
70 | 0 | copy); |
71 | 0 | } |
72 | |
|
73 | 0 | clip = NULL; |
74 | 0 | if (_cairo_clip_is_region (copy)) |
75 | 0 | clip = copy; |
76 | 0 | clip_path = copy_path; |
77 | 0 | while (status == CAIRO_STATUS_SUCCESS && clip_path) { |
78 | 0 | status = _cairo_surface_fill (dst, |
79 | 0 | CAIRO_OPERATOR_IN, |
80 | 0 | &_cairo_pattern_white.base, |
81 | 0 | &clip_path->path, |
82 | 0 | clip_path->fill_rule, |
83 | 0 | clip_path->tolerance, |
84 | 0 | clip_path->antialias, |
85 | 0 | clip); |
86 | 0 | clip_path = clip_path->prev; |
87 | 0 | } |
88 | |
|
89 | 0 | copy->path = copy_path; |
90 | 0 | _cairo_clip_destroy (copy); |
91 | 0 | return status; |
92 | 0 | } |
93 | | |
94 | | static cairo_status_t |
95 | | _cairo_path_fixed_add_box (cairo_path_fixed_t *path, |
96 | | const cairo_box_t *box, |
97 | | cairo_fixed_t fx, |
98 | | cairo_fixed_t fy) |
99 | 0 | { |
100 | 0 | cairo_status_t status; |
101 | |
|
102 | 0 | status = _cairo_path_fixed_move_to (path, box->p1.x + fx, box->p1.y + fy); |
103 | 0 | if (unlikely (status)) |
104 | 0 | return status; |
105 | | |
106 | 0 | status = _cairo_path_fixed_line_to (path, box->p2.x + fx, box->p1.y + fy); |
107 | 0 | if (unlikely (status)) |
108 | 0 | return status; |
109 | | |
110 | 0 | status = _cairo_path_fixed_line_to (path, box->p2.x + fx, box->p2.y + fy); |
111 | 0 | if (unlikely (status)) |
112 | 0 | return status; |
113 | | |
114 | 0 | status = _cairo_path_fixed_line_to (path, box->p1.x + fx, box->p2.y + fy); |
115 | 0 | if (unlikely (status)) |
116 | 0 | return status; |
117 | | |
118 | 0 | return _cairo_path_fixed_close_path (path); |
119 | 0 | } |
120 | | |
121 | | cairo_surface_t * |
122 | | _cairo_clip_get_surface (const cairo_clip_t *clip, |
123 | | cairo_surface_t *target, |
124 | | int *tx, int *ty) |
125 | 0 | { |
126 | 0 | cairo_surface_t *surface; |
127 | 0 | cairo_status_t status; |
128 | 0 | cairo_clip_t *copy, *region; |
129 | 0 | cairo_clip_path_t *copy_path, *clip_path; |
130 | |
|
131 | 0 | if (clip->num_boxes) { |
132 | 0 | cairo_path_fixed_t path; |
133 | 0 | int i; |
134 | |
|
135 | 0 | surface = _cairo_surface_create_scratch (target, |
136 | 0 | CAIRO_CONTENT_ALPHA, |
137 | 0 | clip->extents.width, |
138 | 0 | clip->extents.height, |
139 | 0 | CAIRO_COLOR_TRANSPARENT); |
140 | 0 | if (unlikely (surface->status)) |
141 | 0 | return surface; |
142 | | |
143 | 0 | _cairo_path_fixed_init (&path); |
144 | 0 | status = CAIRO_STATUS_SUCCESS; |
145 | 0 | for (i = 0; status == CAIRO_STATUS_SUCCESS && i < clip->num_boxes; i++) { |
146 | 0 | status = _cairo_path_fixed_add_box (&path, &clip->boxes[i], |
147 | 0 | -_cairo_fixed_from_int (clip->extents.x), |
148 | 0 | -_cairo_fixed_from_int (clip->extents.y)); |
149 | 0 | } |
150 | 0 | if (status == CAIRO_STATUS_SUCCESS) |
151 | 0 | status = _cairo_surface_fill (surface, |
152 | 0 | CAIRO_OPERATOR_ADD, |
153 | 0 | &_cairo_pattern_white.base, |
154 | 0 | &path, |
155 | 0 | CAIRO_FILL_RULE_WINDING, |
156 | 0 | 1., |
157 | 0 | CAIRO_ANTIALIAS_DEFAULT, |
158 | 0 | NULL); |
159 | 0 | _cairo_path_fixed_fini (&path); |
160 | 0 | if (unlikely (status)) { |
161 | 0 | cairo_surface_destroy (surface); |
162 | 0 | return _cairo_surface_create_in_error (status); |
163 | 0 | } |
164 | 0 | } else { |
165 | 0 | surface = _cairo_surface_create_scratch (target, |
166 | 0 | CAIRO_CONTENT_ALPHA, |
167 | 0 | clip->extents.width, |
168 | 0 | clip->extents.height, |
169 | 0 | CAIRO_COLOR_WHITE); |
170 | 0 | if (unlikely (surface->status)) |
171 | 0 | return surface; |
172 | 0 | } |
173 | | |
174 | 0 | copy = _cairo_clip_copy_with_translation (clip, |
175 | 0 | -clip->extents.x, |
176 | 0 | -clip->extents.y); |
177 | 0 | copy_path = copy->path; |
178 | 0 | copy->path = NULL; |
179 | |
|
180 | 0 | region = copy; |
181 | 0 | if (! _cairo_clip_is_region (copy)) |
182 | 0 | region = _cairo_clip_copy_region (copy); |
183 | |
|
184 | 0 | status = CAIRO_STATUS_SUCCESS; |
185 | 0 | clip_path = copy_path; |
186 | 0 | while (status == CAIRO_STATUS_SUCCESS && clip_path) { |
187 | 0 | status = _cairo_surface_fill (surface, |
188 | 0 | CAIRO_OPERATOR_IN, |
189 | 0 | &_cairo_pattern_white.base, |
190 | 0 | &clip_path->path, |
191 | 0 | clip_path->fill_rule, |
192 | 0 | clip_path->tolerance, |
193 | 0 | clip_path->antialias, |
194 | 0 | region); |
195 | 0 | clip_path = clip_path->prev; |
196 | 0 | } |
197 | |
|
198 | 0 | copy->path = copy_path; |
199 | 0 | _cairo_clip_destroy (copy); |
200 | 0 | if (region != copy) |
201 | 0 | _cairo_clip_destroy (region); |
202 | |
|
203 | 0 | if (unlikely (status)) { |
204 | 0 | cairo_surface_destroy (surface); |
205 | 0 | return _cairo_surface_create_in_error (status); |
206 | 0 | } |
207 | | |
208 | 0 | *tx = clip->extents.x; |
209 | 0 | *ty = clip->extents.y; |
210 | 0 | return surface; |
211 | 0 | } |
212 | | |
213 | | cairo_surface_t * |
214 | | _cairo_clip_get_image (const cairo_clip_t *clip, |
215 | | cairo_surface_t *target, |
216 | | const cairo_rectangle_int_t *extents) |
217 | 0 | { |
218 | 0 | cairo_surface_t *surface; |
219 | 0 | cairo_status_t status; |
220 | |
|
221 | 0 | surface = cairo_surface_create_similar_image (target, |
222 | 0 | CAIRO_FORMAT_A8, |
223 | 0 | extents->width, |
224 | 0 | extents->height); |
225 | 0 | if (unlikely (surface->status)) |
226 | 0 | return surface; |
227 | | |
228 | 0 | status = _cairo_surface_paint (surface, CAIRO_OPERATOR_SOURCE, |
229 | 0 | &_cairo_pattern_white.base, NULL); |
230 | 0 | if (likely (status == CAIRO_STATUS_SUCCESS)) |
231 | 0 | status = _cairo_clip_combine_with_surface (clip, surface, |
232 | 0 | extents->x, extents->y); |
233 | |
|
234 | 0 | if (unlikely (status)) { |
235 | 0 | cairo_surface_destroy (surface); |
236 | 0 | surface = _cairo_surface_create_in_error (status); |
237 | 0 | } |
238 | |
|
239 | 0 | return surface; |
240 | 0 | } |