File: | root/firefox-clang/gfx/cairo/cairo/src/cairo-analysis-surface.c |
Warning: | line 386, column 2 Value stored to 'unused' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ |
2 | /* |
3 | * Copyright © 2006 Keith Packard |
4 | * Copyright © 2007 Adrian Johnson |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it either under the terms of the GNU Lesser General Public |
8 | * License version 2.1 as published by the Free Software Foundation |
9 | * (the "LGPL") or, at your option, under the terms of the Mozilla |
10 | * Public License Version 1.1 (the "MPL"). If you do not alter this |
11 | * notice, a recipient may use your version of this file under either |
12 | * the MPL or the LGPL. |
13 | * |
14 | * You should have received a copy of the LGPL along with this library |
15 | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
16 | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
17 | * You should have received a copy of the MPL along with this library |
18 | * in the file COPYING-MPL-1.1 |
19 | * |
20 | * The contents of this file are subject to the Mozilla Public License |
21 | * Version 1.1 (the "License"); you may not use this file except in |
22 | * compliance with the License. You may obtain a copy of the License at |
23 | * http://www.mozilla.org/MPL/ |
24 | * |
25 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
26 | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
27 | * the specific language governing rights and limitations. |
28 | * |
29 | * The Original Code is the cairo graphics library. |
30 | * |
31 | * The Initial Developer of the Original Code is Keith Packard |
32 | * |
33 | * Contributor(s): |
34 | * Keith Packard <keithp@keithp.com> |
35 | * Adrian Johnson <ajohnson@redneon.com> |
36 | */ |
37 | |
38 | #include "cairoint.h" |
39 | |
40 | #include "cairo-analysis-surface-private.h" |
41 | #include "cairo-box-inline.h" |
42 | #include "cairo-default-context-private.h" |
43 | #include "cairo-error-private.h" |
44 | #include "cairo-paginated-private.h" |
45 | #include "cairo-recording-surface-inline.h" |
46 | #include "cairo-surface-snapshot-inline.h" |
47 | #include "cairo-surface-subsurface-inline.h" |
48 | #include "cairo-region-private.h" |
49 | |
50 | typedef struct { |
51 | cairo_surface_t base; |
52 | |
53 | cairo_surface_t *target; |
54 | |
55 | cairo_bool_t first_op; |
56 | cairo_bool_t has_supported; |
57 | cairo_bool_t has_unsupported; |
58 | |
59 | cairo_region_t supported_region; |
60 | cairo_region_t fallback_region; |
61 | cairo_box_t page_bbox; |
62 | |
63 | cairo_bool_t create_region_ids; |
64 | unsigned source_region_id; |
65 | unsigned mask_region_id; |
66 | |
67 | cairo_bool_t has_ctm; |
68 | cairo_matrix_t ctm; |
69 | |
70 | } cairo_analysis_surface_t; |
71 | |
72 | cairo_int_status_t |
73 | _cairo_analysis_surface_merge_status (cairo_int_status_t status_a, |
74 | cairo_int_status_t status_b) |
75 | { |
76 | /* fatal errors should be checked and propagated at source */ |
77 | assert (! _cairo_int_status_is_error (status_a))((void) sizeof ((! ((status_a) != CAIRO_INT_STATUS_SUCCESS && (status_a) < CAIRO_INT_STATUS_LAST_STATUS)) ? 1 : 0), __extension__ ({ if (! ((status_a) != CAIRO_INT_STATUS_SUCCESS && ( status_a) < CAIRO_INT_STATUS_LAST_STATUS)) ; else __assert_fail ("! _cairo_int_status_is_error (status_a)", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-analysis-surface.c" , 77, __extension__ __PRETTY_FUNCTION__); })); |
78 | assert (! _cairo_int_status_is_error (status_b))((void) sizeof ((! ((status_b) != CAIRO_INT_STATUS_SUCCESS && (status_b) < CAIRO_INT_STATUS_LAST_STATUS)) ? 1 : 0), __extension__ ({ if (! ((status_b) != CAIRO_INT_STATUS_SUCCESS && ( status_b) < CAIRO_INT_STATUS_LAST_STATUS)) ; else __assert_fail ("! _cairo_int_status_is_error (status_b)", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-analysis-surface.c" , 78, __extension__ __PRETTY_FUNCTION__); })); |
79 | |
80 | /* return the most important status */ |
81 | if (status_a == CAIRO_INT_STATUS_UNSUPPORTED || |
82 | status_b == CAIRO_INT_STATUS_UNSUPPORTED) |
83 | return CAIRO_INT_STATUS_UNSUPPORTED; |
84 | |
85 | if (status_a == CAIRO_INT_STATUS_IMAGE_FALLBACK || |
86 | status_b == CAIRO_INT_STATUS_IMAGE_FALLBACK) |
87 | return CAIRO_INT_STATUS_IMAGE_FALLBACK; |
88 | |
89 | if (status_a == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN || |
90 | status_b == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) |
91 | return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; |
92 | |
93 | if (status_a == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY || |
94 | status_b == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY) |
95 | return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; |
96 | |
97 | /* at this point we have checked all the valid internal codes, so... */ |
98 | assert (status_a == CAIRO_INT_STATUS_SUCCESS &&((void) sizeof ((status_a == CAIRO_INT_STATUS_SUCCESS && status_b == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0), __extension__ ({ if (status_a == CAIRO_INT_STATUS_SUCCESS && status_b == CAIRO_INT_STATUS_SUCCESS) ; else __assert_fail ("status_a == CAIRO_INT_STATUS_SUCCESS && status_b == CAIRO_INT_STATUS_SUCCESS" , "/root/firefox-clang/gfx/cairo/cairo/src/cairo-analysis-surface.c" , 99, __extension__ __PRETTY_FUNCTION__); })) |
99 | status_b == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status_a == CAIRO_INT_STATUS_SUCCESS && status_b == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0), __extension__ ({ if (status_a == CAIRO_INT_STATUS_SUCCESS && status_b == CAIRO_INT_STATUS_SUCCESS) ; else __assert_fail ("status_a == CAIRO_INT_STATUS_SUCCESS && status_b == CAIRO_INT_STATUS_SUCCESS" , "/root/firefox-clang/gfx/cairo/cairo/src/cairo-analysis-surface.c" , 99, __extension__ __PRETTY_FUNCTION__); })); |
100 | |
101 | return CAIRO_INT_STATUS_SUCCESS; |
102 | } |
103 | |
104 | struct proxy { |
105 | cairo_surface_t base; |
106 | cairo_surface_t *target; |
107 | }; |
108 | |
109 | static cairo_status_t |
110 | proxy_finish (void *abstract_surface) |
111 | { |
112 | return CAIRO_STATUS_SUCCESS; |
113 | } |
114 | |
115 | static const cairo_surface_backend_t proxy_backend = { |
116 | CAIRO_INTERNAL_SURFACE_TYPE_NULL, |
117 | proxy_finish, |
118 | }; |
119 | |
120 | static cairo_surface_t * |
121 | attach_proxy (cairo_surface_t *source, |
122 | cairo_surface_t *target) |
123 | { |
124 | struct proxy *proxy; |
125 | |
126 | proxy = _cairo_malloc (sizeof (*proxy))((sizeof (*proxy)) != 0 ? malloc(sizeof (*proxy)) : ((void*)0 )); |
127 | if (unlikely (proxy == NULL)(__builtin_expect (!!(proxy == ((void*)0)), 0))) |
128 | return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); |
129 | |
130 | _cairo_surface_init (&proxy->base, &proxy_backend, NULL((void*)0), target->content, target->is_vector); |
131 | |
132 | proxy->target = target; |
133 | _cairo_surface_attach_snapshot (source, &proxy->base, NULL((void*)0)); |
134 | |
135 | return &proxy->base; |
136 | } |
137 | |
138 | static void |
139 | detach_proxy (cairo_surface_t *proxy) |
140 | { |
141 | cairo_surface_finish_moz_cairo_surface_finish (proxy); |
142 | cairo_surface_destroy_moz_cairo_surface_destroy (proxy); |
143 | } |
144 | |
145 | static cairo_int_status_t |
146 | _add_operation (cairo_analysis_surface_t *surface, |
147 | cairo_rectangle_int_t *rect, |
148 | cairo_int_status_t backend_status) |
149 | { |
150 | cairo_int_status_t status; |
151 | cairo_box_t bbox; |
152 | |
153 | if (rect->width == 0 || rect->height == 0) { |
154 | /* Even though the operation is not visible we must be careful |
155 | * to not allow unsupported operations to be replayed to the |
156 | * backend during CAIRO_PAGINATED_MODE_RENDER */ |
157 | if (backend_status == CAIRO_INT_STATUS_SUCCESS || |
158 | backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY || |
159 | backend_status == CAIRO_INT_STATUS_NOTHING_TO_DO) |
160 | { |
161 | return CAIRO_INT_STATUS_SUCCESS; |
162 | } |
163 | else |
164 | { |
165 | return CAIRO_INT_STATUS_IMAGE_FALLBACK; |
166 | } |
167 | } |
168 | |
169 | _cairo_box_from_rectangle (&bbox, rect); |
170 | |
171 | if (surface->has_ctm) { |
172 | int tx, ty; |
173 | |
174 | if (_cairo_matrix_is_integer_translation (&surface->ctm, &tx, &ty)) { |
175 | rect->x += tx; |
176 | rect->y += ty; |
177 | |
178 | tx = _cairo_fixed_from_int (tx); |
179 | bbox.p1.x += tx; |
180 | bbox.p2.x += tx; |
181 | |
182 | ty = _cairo_fixed_from_int (ty); |
183 | bbox.p1.y += ty; |
184 | bbox.p2.y += ty; |
185 | } else { |
186 | _cairo_matrix_transform_bounding_box_fixed (&surface->ctm, |
187 | &bbox, NULL((void*)0)); |
188 | |
189 | if (bbox.p1.x == bbox.p2.x || bbox.p1.y == bbox.p2.y) { |
190 | /* Even though the operation is not visible we must be |
191 | * careful to not allow unsupported operations to be |
192 | * replayed to the backend during |
193 | * CAIRO_PAGINATED_MODE_RENDER */ |
194 | if (backend_status == CAIRO_INT_STATUS_SUCCESS || |
195 | backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY || |
196 | backend_status == CAIRO_INT_STATUS_NOTHING_TO_DO) |
197 | { |
198 | return CAIRO_INT_STATUS_SUCCESS; |
199 | } |
200 | else |
201 | { |
202 | return CAIRO_INT_STATUS_IMAGE_FALLBACK; |
203 | } |
204 | } |
205 | |
206 | _cairo_box_round_to_rectangle (&bbox, rect); |
207 | } |
208 | } |
209 | |
210 | if (surface->first_op) { |
211 | surface->first_op = FALSE0; |
212 | surface->page_bbox = bbox; |
213 | } else |
214 | _cairo_box_add_box(&surface->page_bbox, &bbox); |
215 | |
216 | /* If the operation is completely enclosed within the fallback |
217 | * region there is no benefit in emitting a native operation as |
218 | * the fallback image will be painted on top. |
219 | */ |
220 | if (cairo_region_contains_rectangle_moz_cairo_region_contains_rectangle (&surface->fallback_region, rect) == CAIRO_REGION_OVERLAP_IN) |
221 | return CAIRO_INT_STATUS_IMAGE_FALLBACK; |
222 | |
223 | if (backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY) { |
224 | /* A status of CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY indicates |
225 | * that the backend only supports this operation if the |
226 | * transparency removed. If the extents of this operation does |
227 | * not intersect any other native operation, the operation is |
228 | * natively supported and the backend will blend the |
229 | * transparency into the white background. |
230 | */ |
231 | if (cairo_region_contains_rectangle_moz_cairo_region_contains_rectangle (&surface->supported_region, rect) == CAIRO_REGION_OVERLAP_OUT) |
232 | backend_status = CAIRO_INT_STATUS_SUCCESS; |
233 | } |
234 | |
235 | if (backend_status == CAIRO_INT_STATUS_SUCCESS) { |
236 | /* Add the operation to the supported region. Operations in |
237 | * this region will be emitted as native operations. |
238 | */ |
239 | surface->has_supported = TRUE1; |
240 | return cairo_region_union_rectangle_moz_cairo_region_union_rectangle (&surface->supported_region, rect); |
241 | } |
242 | |
243 | /* Add the operation to the unsupported region. This region will |
244 | * be painted as an image after all native operations have been |
245 | * emitted. |
246 | */ |
247 | surface->has_unsupported = TRUE1; |
248 | status = cairo_region_union_rectangle_moz_cairo_region_union_rectangle (&surface->fallback_region, rect); |
249 | |
250 | /* The status CAIRO_INT_STATUS_IMAGE_FALLBACK is used to indicate |
251 | * unsupported operations to the recording surface as using |
252 | * CAIRO_INT_STATUS_UNSUPPORTED would cause cairo-surface to |
253 | * invoke the cairo-surface-fallback path then return |
254 | * CAIRO_STATUS_SUCCESS. |
255 | */ |
256 | if (status == CAIRO_INT_STATUS_SUCCESS) |
257 | return CAIRO_INT_STATUS_IMAGE_FALLBACK; |
258 | else |
259 | return status; |
260 | } |
261 | |
262 | static cairo_int_status_t |
263 | _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, |
264 | const cairo_pattern_t *pattern, |
265 | cairo_rectangle_int_t *extents, |
266 | unsigned int *regions_id, |
267 | cairo_analysis_source_t source_type) |
268 | { |
269 | const cairo_surface_pattern_t *surface_pattern; |
270 | cairo_analysis_surface_t *tmp; |
271 | cairo_surface_t *source, *proxy; |
272 | cairo_matrix_t p2d; |
273 | cairo_int_status_t status; |
274 | cairo_int_status_t analysis_status = CAIRO_INT_STATUS_SUCCESS; |
275 | cairo_bool_t surface_is_unbounded; |
276 | cairo_bool_t unused; |
277 | cairo_bool_t replay_all; |
278 | |
279 | assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)((void) sizeof ((pattern->type == CAIRO_PATTERN_TYPE_SURFACE ) ? 1 : 0), __extension__ ({ if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE ) ; else __assert_fail ("pattern->type == CAIRO_PATTERN_TYPE_SURFACE" , "/root/firefox-clang/gfx/cairo/cairo/src/cairo-analysis-surface.c" , 279, __extension__ __PRETTY_FUNCTION__); })); |
280 | surface_pattern = (const cairo_surface_pattern_t *) pattern; |
281 | assert (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)((void) sizeof ((surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING ) ? 1 : 0), __extension__ ({ if (surface_pattern->surface-> type == CAIRO_SURFACE_TYPE_RECORDING) ; else __assert_fail ("surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING" , "/root/firefox-clang/gfx/cairo/cairo/src/cairo-analysis-surface.c" , 281, __extension__ __PRETTY_FUNCTION__); })); |
282 | source = surface_pattern->surface; |
283 | |
284 | proxy = _cairo_surface_has_snapshot (source, &proxy_backend); |
285 | if (proxy != NULL((void*)0)) { |
286 | /* nothing untoward found so far */ |
287 | return CAIRO_STATUS_SUCCESS; |
288 | } |
289 | |
290 | tmp = (cairo_analysis_surface_t *) |
291 | _cairo_analysis_surface_create (surface->target, surface->create_region_ids); |
292 | if (unlikely (tmp->base.status)(__builtin_expect (!!(tmp->base.status), 0))) { |
293 | status = tmp->base.status; |
294 | goto cleanup1; |
295 | } |
296 | proxy = attach_proxy (source, &tmp->base); |
297 | |
298 | p2d = pattern->matrix; |
299 | status = cairo_matrix_invert_moz_cairo_matrix_invert (&p2d); |
300 | assert (status == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0) , __extension__ ({ if (status == CAIRO_INT_STATUS_SUCCESS) ; else __assert_fail ("status == CAIRO_INT_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-analysis-surface.c" , 300, __extension__ __PRETTY_FUNCTION__); })); |
301 | _cairo_analysis_surface_set_ctm (&tmp->base, &p2d); |
302 | |
303 | source = _cairo_surface_get_source (source, NULL((void*)0)); |
304 | surface_is_unbounded = (pattern->extend == CAIRO_EXTEND_REPEAT |
305 | || pattern->extend == CAIRO_EXTEND_REFLECT); |
306 | |
307 | if (surface->create_region_ids) { |
308 | status = _cairo_recording_surface_region_array_attach (source, regions_id); |
309 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
310 | goto cleanup2; |
311 | } |
312 | |
313 | replay_all = FALSE0; |
314 | if (surface->target->backend->analyze_recording_surface) { |
315 | status = surface->target->backend->analyze_recording_surface ( |
316 | surface->target, |
317 | surface_pattern, |
318 | surface->create_region_ids ? *regions_id : 0, |
319 | source_type, |
320 | TRUE1); |
321 | if (status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { |
322 | /* Ensure all commands are replayed even if previously |
323 | * replayed and assigned to a region.*/ |
324 | replay_all = TRUE1; |
325 | status = CAIRO_INT_STATUS_SUCCESS; |
326 | } |
327 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
328 | goto cleanup3; |
329 | } |
330 | |
331 | if (surface->create_region_ids) { |
332 | status = _cairo_recording_surface_replay_and_create_regions (source, |
333 | *regions_id, |
334 | &pattern->matrix, |
335 | &tmp->base, |
336 | surface_is_unbounded, |
337 | replay_all); |
338 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
339 | goto cleanup3; |
340 | } else { |
341 | status = _cairo_recording_surface_replay_with_transform (source, |
342 | &pattern->matrix, |
343 | &tmp->base, |
344 | surface_is_unbounded, |
345 | replay_all); |
346 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
347 | goto cleanup3; |
348 | } |
349 | |
350 | if (surface->target->backend->analyze_recording_surface) { |
351 | status = surface->target->backend->analyze_recording_surface ( |
352 | surface->target, |
353 | surface_pattern, |
354 | surface->create_region_ids ? *regions_id : 0, |
355 | source_type, |
356 | FALSE0); |
357 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
358 | goto cleanup3; |
359 | } |
360 | |
361 | /* black background or mime data fills entire extents */ |
362 | if (!(source->content & CAIRO_CONTENT_ALPHA) || _cairo_surface_has_mime_image (source)) { |
363 | cairo_rectangle_int_t rect; |
364 | |
365 | if (_cairo_surface_get_extents (source, &rect)) { |
366 | cairo_box_t bbox; |
367 | |
368 | _cairo_box_from_rectangle (&bbox, &rect); |
369 | _cairo_matrix_transform_bounding_box_fixed (&p2d, &bbox, NULL((void*)0)); |
370 | _cairo_box_round_to_rectangle (&bbox, &rect); |
371 | status = _add_operation (tmp, &rect, CAIRO_INT_STATUS_SUCCESS); |
372 | if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) |
373 | status = CAIRO_INT_STATUS_SUCCESS; |
374 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
375 | goto cleanup3; |
376 | } |
377 | } |
378 | |
379 | if (tmp->has_supported) { |
380 | surface->has_supported = TRUE1; |
381 | unused = cairo_region_union_moz_cairo_region_union (&surface->supported_region, &tmp->supported_region); |
382 | } |
383 | |
384 | if (tmp->has_unsupported) { |
385 | surface->has_unsupported = TRUE1; |
386 | unused = cairo_region_union_moz_cairo_region_union (&surface->fallback_region, &tmp->fallback_region); |
Value stored to 'unused' is never read | |
387 | } |
388 | |
389 | analysis_status = tmp->has_unsupported ? CAIRO_INT_STATUS_IMAGE_FALLBACK : CAIRO_INT_STATUS_SUCCESS; |
390 | if (pattern->extend != CAIRO_EXTEND_NONE) { |
391 | _cairo_unbounded_rectangle_init (extents); |
392 | } else { |
393 | status = cairo_matrix_invert_moz_cairo_matrix_invert (&tmp->ctm); |
394 | _cairo_matrix_transform_bounding_box_fixed (&tmp->ctm, |
395 | &tmp->page_bbox, NULL((void*)0)); |
396 | _cairo_box_round_to_rectangle (&tmp->page_bbox, extents); |
397 | } |
398 | |
399 | cleanup3: |
400 | if (surface->create_region_ids && unlikely (status)(__builtin_expect (!!(status), 0))) { |
401 | _cairo_recording_surface_region_array_remove (source, *regions_id); |
402 | } |
403 | cleanup2: |
404 | detach_proxy (proxy); |
405 | cleanup1: |
406 | cairo_surface_destroy_moz_cairo_surface_destroy (&tmp->base); |
407 | |
408 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
409 | return status; |
410 | else |
411 | return analysis_status; |
412 | } |
413 | |
414 | static cairo_status_t |
415 | _cairo_analysis_surface_finish (void *abstract_surface) |
416 | { |
417 | cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; |
418 | |
419 | _cairo_region_fini (&surface->supported_region); |
420 | _cairo_region_fini (&surface->fallback_region); |
421 | |
422 | cairo_surface_destroy_moz_cairo_surface_destroy (surface->target); |
423 | |
424 | return CAIRO_STATUS_SUCCESS; |
425 | } |
426 | |
427 | static cairo_bool_t |
428 | _cairo_analysis_surface_get_extents (void *abstract_surface, |
429 | cairo_rectangle_int_t *rectangle) |
430 | { |
431 | cairo_analysis_surface_t *surface = abstract_surface; |
432 | |
433 | return _cairo_surface_get_extents (surface->target, rectangle); |
434 | } |
435 | |
436 | static void |
437 | _rectangle_intersect_clip (cairo_rectangle_int_t *extents, const cairo_clip_t *clip) |
438 | { |
439 | if (clip != NULL((void*)0)) |
440 | _cairo_rectangle_intersect (extents, _cairo_clip_get_extents (clip)); |
441 | } |
442 | |
443 | static void |
444 | _cairo_analysis_surface_operation_extents (cairo_analysis_surface_t *surface, |
445 | cairo_operator_t op, |
446 | const cairo_pattern_t *source, |
447 | const cairo_clip_t *clip, |
448 | cairo_rectangle_int_t *extents) |
449 | { |
450 | cairo_bool_t is_empty; |
451 | |
452 | is_empty = _cairo_surface_get_extents (&surface->base, extents); |
453 | |
454 | if (_cairo_operator_bounded_by_source (op)) { |
455 | cairo_rectangle_int_t source_extents; |
456 | |
457 | _cairo_pattern_get_extents (source, &source_extents, surface->target->is_vector); |
458 | _cairo_rectangle_intersect (extents, &source_extents); |
459 | } |
460 | |
461 | _rectangle_intersect_clip (extents, clip); |
462 | } |
463 | |
464 | static cairo_int_status_t |
465 | _cairo_analysis_surface_paint (void *abstract_surface, |
466 | cairo_operator_t op, |
467 | const cairo_pattern_t *source, |
468 | const cairo_clip_t *clip) |
469 | { |
470 | cairo_analysis_surface_t *surface = abstract_surface; |
471 | cairo_int_status_t backend_status; |
472 | cairo_rectangle_int_t extents; |
473 | |
474 | surface->source_region_id = 0; |
475 | surface->mask_region_id = 0; |
476 | if (surface->target->backend->paint == NULL((void*)0)) { |
477 | backend_status = CAIRO_INT_STATUS_UNSUPPORTED; |
478 | } else { |
479 | backend_status = |
480 | surface->target->backend->paint (surface->target, |
481 | op, source, clip); |
482 | if (_cairo_int_status_is_error (backend_status)((backend_status) != CAIRO_INT_STATUS_SUCCESS && (backend_status ) < CAIRO_INT_STATUS_LAST_STATUS)) |
483 | return backend_status; |
484 | } |
485 | |
486 | _cairo_analysis_surface_operation_extents (surface, |
487 | op, source, clip, |
488 | &extents); |
489 | if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { |
490 | cairo_rectangle_int_t rec_extents; |
491 | backend_status = _analyze_recording_surface_pattern (surface, |
492 | source, |
493 | &rec_extents, |
494 | &surface->source_region_id, |
495 | CAIRO_ANALYSIS_SOURCE_PAINT); |
496 | _cairo_rectangle_intersect (&extents, &rec_extents); |
497 | } |
498 | |
499 | return _add_operation (surface, &extents, backend_status); |
500 | } |
501 | |
502 | static cairo_int_status_t |
503 | _cairo_analysis_surface_mask (void *abstract_surface, |
504 | cairo_operator_t op, |
505 | const cairo_pattern_t *source, |
506 | const cairo_pattern_t *mask, |
507 | const cairo_clip_t *clip) |
508 | { |
509 | cairo_analysis_surface_t *surface = abstract_surface; |
510 | cairo_int_status_t backend_status; |
511 | cairo_rectangle_int_t extents; |
512 | |
513 | surface->source_region_id = 0; |
514 | surface->mask_region_id = 0; |
515 | if (surface->target->backend->mask == NULL((void*)0)) { |
516 | backend_status = CAIRO_INT_STATUS_UNSUPPORTED; |
517 | } else { |
518 | backend_status = |
519 | surface->target->backend->mask (surface->target, |
520 | op, source, mask, clip); |
521 | if (_cairo_int_status_is_error (backend_status)((backend_status) != CAIRO_INT_STATUS_SUCCESS && (backend_status ) < CAIRO_INT_STATUS_LAST_STATUS)) |
522 | return backend_status; |
523 | } |
524 | |
525 | _cairo_analysis_surface_operation_extents (surface, |
526 | op, source, clip, |
527 | &extents); |
528 | if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { |
529 | cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS; |
530 | cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS; |
531 | cairo_rectangle_int_t rec_extents; |
532 | |
533 | if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { |
534 | cairo_surface_t *src_surface = ((cairo_surface_pattern_t *)source)->surface; |
535 | src_surface = _cairo_surface_get_source (src_surface, NULL((void*)0)); |
536 | if (_cairo_surface_is_recording (src_surface)) { |
537 | backend_source_status = |
538 | _analyze_recording_surface_pattern (surface, |
539 | source, |
540 | &rec_extents, |
541 | &surface->source_region_id, |
542 | CAIRO_ANALYSIS_SOURCE_MASK); |
543 | if (_cairo_int_status_is_error (backend_source_status)((backend_source_status) != CAIRO_INT_STATUS_SUCCESS && (backend_source_status) < CAIRO_INT_STATUS_LAST_STATUS)) |
544 | return backend_source_status; |
545 | |
546 | _cairo_rectangle_intersect (&extents, &rec_extents); |
547 | } |
548 | } |
549 | |
550 | if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) { |
551 | cairo_surface_t *mask_surface = ((cairo_surface_pattern_t *)mask)->surface; |
552 | mask_surface = _cairo_surface_get_source (mask_surface, NULL((void*)0)); |
553 | if (_cairo_surface_is_recording (mask_surface)) { |
554 | backend_mask_status = |
555 | _analyze_recording_surface_pattern (surface, |
556 | mask, |
557 | &rec_extents, |
558 | &surface->mask_region_id, |
559 | CAIRO_ANALYSIS_MASK_MASK); |
560 | if (_cairo_int_status_is_error (backend_mask_status)((backend_mask_status) != CAIRO_INT_STATUS_SUCCESS && (backend_mask_status) < CAIRO_INT_STATUS_LAST_STATUS)) |
561 | return backend_mask_status; |
562 | |
563 | _cairo_rectangle_intersect (&extents, &rec_extents); |
564 | } |
565 | } |
566 | |
567 | backend_status = |
568 | _cairo_analysis_surface_merge_status (backend_source_status, |
569 | backend_mask_status); |
570 | } |
571 | |
572 | if (_cairo_operator_bounded_by_mask (op)) { |
573 | cairo_rectangle_int_t mask_extents; |
574 | |
575 | _cairo_pattern_get_extents (mask, &mask_extents, surface->target->is_vector); |
576 | _cairo_rectangle_intersect (&extents, &mask_extents); |
577 | } |
578 | |
579 | return _add_operation (surface, &extents, backend_status); |
580 | } |
581 | |
582 | static cairo_int_status_t |
583 | _cairo_analysis_surface_stroke (void *abstract_surface, |
584 | cairo_operator_t op, |
585 | const cairo_pattern_t *source, |
586 | const cairo_path_fixed_t *path, |
587 | const cairo_stroke_style_t *style, |
588 | const cairo_matrix_t *ctm, |
589 | const cairo_matrix_t *ctm_inverse, |
590 | double tolerance, |
591 | cairo_antialias_t antialias, |
592 | const cairo_clip_t *clip) |
593 | { |
594 | cairo_analysis_surface_t *surface = abstract_surface; |
595 | cairo_int_status_t backend_status; |
596 | cairo_rectangle_int_t extents; |
597 | |
598 | surface->source_region_id = 0; |
599 | surface->mask_region_id = 0; |
600 | if (surface->target->backend->stroke == NULL((void*)0)) { |
601 | backend_status = CAIRO_INT_STATUS_UNSUPPORTED; |
602 | } else { |
603 | backend_status = |
604 | surface->target->backend->stroke (surface->target, op, |
605 | source, path, style, |
606 | ctm, ctm_inverse, |
607 | tolerance, antialias, |
608 | clip); |
609 | if (_cairo_int_status_is_error (backend_status)((backend_status) != CAIRO_INT_STATUS_SUCCESS && (backend_status ) < CAIRO_INT_STATUS_LAST_STATUS)) |
610 | return backend_status; |
611 | } |
612 | |
613 | _cairo_analysis_surface_operation_extents (surface, |
614 | op, source, clip, |
615 | &extents); |
616 | if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { |
617 | cairo_rectangle_int_t rec_extents; |
618 | backend_status = _analyze_recording_surface_pattern (surface, |
619 | source, |
620 | &rec_extents, |
621 | &surface->source_region_id, |
622 | CAIRO_ANALYSIS_SOURCE_STROKE); |
623 | _cairo_rectangle_intersect (&extents, &rec_extents); |
624 | } |
625 | |
626 | if (_cairo_operator_bounded_by_mask (op)) { |
627 | cairo_rectangle_int_t mask_extents; |
628 | cairo_int_status_t status; |
629 | |
630 | status = _cairo_path_fixed_stroke_extents (path, style, |
631 | ctm, ctm_inverse, |
632 | tolerance, |
633 | &mask_extents); |
634 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
635 | return status; |
636 | |
637 | _cairo_rectangle_intersect (&extents, &mask_extents); |
638 | } |
639 | |
640 | return _add_operation (surface, &extents, backend_status); |
641 | } |
642 | |
643 | static cairo_int_status_t |
644 | _cairo_analysis_surface_fill (void *abstract_surface, |
645 | cairo_operator_t op, |
646 | const cairo_pattern_t *source, |
647 | const cairo_path_fixed_t *path, |
648 | cairo_fill_rule_t fill_rule, |
649 | double tolerance, |
650 | cairo_antialias_t antialias, |
651 | const cairo_clip_t *clip) |
652 | { |
653 | cairo_analysis_surface_t *surface = abstract_surface; |
654 | cairo_int_status_t backend_status; |
655 | cairo_rectangle_int_t extents; |
656 | |
657 | if (surface->target->backend->fill == NULL((void*)0)) { |
658 | backend_status = CAIRO_INT_STATUS_UNSUPPORTED; |
659 | } else { |
660 | backend_status = |
661 | surface->target->backend->fill (surface->target, op, |
662 | source, path, fill_rule, |
663 | tolerance, antialias, |
664 | clip); |
665 | if (_cairo_int_status_is_error (backend_status)((backend_status) != CAIRO_INT_STATUS_SUCCESS && (backend_status ) < CAIRO_INT_STATUS_LAST_STATUS)) |
666 | return backend_status; |
667 | } |
668 | |
669 | _cairo_analysis_surface_operation_extents (surface, |
670 | op, source, clip, |
671 | &extents); |
672 | if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { |
673 | cairo_rectangle_int_t rec_extents; |
674 | backend_status = _analyze_recording_surface_pattern (surface, |
675 | source, |
676 | &rec_extents, |
677 | &surface->source_region_id, |
678 | CAIRO_ANALYSIS_SOURCE_FILL); |
679 | _cairo_rectangle_intersect (&extents, &rec_extents); |
680 | } |
681 | |
682 | if (_cairo_operator_bounded_by_mask (op)) { |
683 | cairo_rectangle_int_t mask_extents; |
684 | |
685 | _cairo_path_fixed_fill_extents (path, fill_rule, tolerance, |
686 | &mask_extents); |
687 | |
688 | _cairo_rectangle_intersect (&extents, &mask_extents); |
689 | } |
690 | |
691 | return _add_operation (surface, &extents, backend_status); |
692 | } |
693 | |
694 | static cairo_int_status_t |
695 | _cairo_analysis_surface_show_glyphs (void *abstract_surface, |
696 | cairo_operator_t op, |
697 | const cairo_pattern_t *source, |
698 | cairo_glyph_t *glyphs, |
699 | int num_glyphs, |
700 | cairo_scaled_font_t *scaled_font, |
701 | const cairo_clip_t *clip) |
702 | { |
703 | cairo_analysis_surface_t *surface = abstract_surface; |
704 | cairo_int_status_t status, backend_status; |
705 | cairo_rectangle_int_t extents, glyph_extents; |
706 | |
707 | surface->source_region_id = 0; |
708 | surface->mask_region_id = 0; |
709 | |
710 | /* Adapted from _cairo_surface_show_glyphs */ |
711 | if (surface->target->backend->show_glyphs != NULL((void*)0)) { |
712 | backend_status = |
713 | surface->target->backend->show_glyphs (surface->target, op, |
714 | source, |
715 | glyphs, num_glyphs, |
716 | scaled_font, |
717 | clip); |
718 | if (_cairo_int_status_is_error (backend_status)((backend_status) != CAIRO_INT_STATUS_SUCCESS && (backend_status ) < CAIRO_INT_STATUS_LAST_STATUS)) |
719 | return backend_status; |
720 | } |
721 | else if (surface->target->backend->show_text_glyphs != NULL((void*)0)) |
722 | { |
723 | backend_status = |
724 | surface->target->backend->show_text_glyphs (surface->target, op, |
725 | source, |
726 | NULL((void*)0), 0, |
727 | glyphs, num_glyphs, |
728 | NULL((void*)0), 0, |
729 | FALSE0, |
730 | scaled_font, |
731 | clip); |
732 | if (_cairo_int_status_is_error (backend_status)((backend_status) != CAIRO_INT_STATUS_SUCCESS && (backend_status ) < CAIRO_INT_STATUS_LAST_STATUS)) |
733 | return backend_status; |
734 | } |
735 | else |
736 | { |
737 | backend_status = CAIRO_INT_STATUS_UNSUPPORTED; |
738 | } |
739 | |
740 | _cairo_analysis_surface_operation_extents (surface, |
741 | op, source, clip, |
742 | &extents); |
743 | if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { |
744 | cairo_rectangle_int_t rec_extents; |
745 | backend_status = _analyze_recording_surface_pattern (surface, |
746 | source, |
747 | &rec_extents, |
748 | &surface->source_region_id, |
749 | CAIRO_ANALYSIS_SOURCE_SHOW_GLYPHS); |
750 | _cairo_rectangle_intersect (&extents, &rec_extents); |
751 | } |
752 | |
753 | if (_cairo_operator_bounded_by_mask (op)) { |
754 | status = _cairo_scaled_font_glyph_device_extents (scaled_font, |
755 | glyphs, |
756 | num_glyphs, |
757 | &glyph_extents, |
758 | NULL((void*)0)); |
759 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
760 | return status; |
761 | |
762 | _cairo_rectangle_intersect (&extents, &glyph_extents); |
763 | } |
764 | |
765 | return _add_operation (surface, &extents, backend_status); |
766 | } |
767 | |
768 | static cairo_bool_t |
769 | _cairo_analysis_surface_has_show_text_glyphs (void *abstract_surface) |
770 | { |
771 | cairo_analysis_surface_t *surface = abstract_surface; |
772 | |
773 | return cairo_surface_has_show_text_glyphs_moz_cairo_surface_has_show_text_glyphs (surface->target); |
774 | } |
775 | |
776 | static cairo_int_status_t |
777 | _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, |
778 | cairo_operator_t op, |
779 | const cairo_pattern_t *source, |
780 | const char *utf8, |
781 | int utf8_len, |
782 | cairo_glyph_t *glyphs, |
783 | int num_glyphs, |
784 | const cairo_text_cluster_t *clusters, |
785 | int num_clusters, |
786 | cairo_text_cluster_flags_t cluster_flags, |
787 | cairo_scaled_font_t *scaled_font, |
788 | const cairo_clip_t *clip) |
789 | { |
790 | cairo_analysis_surface_t *surface = abstract_surface; |
791 | cairo_int_status_t status, backend_status; |
792 | cairo_rectangle_int_t extents, glyph_extents; |
793 | |
794 | surface->source_region_id = 0; |
795 | surface->mask_region_id = 0; |
796 | |
797 | /* Adapted from _cairo_surface_show_glyphs */ |
798 | backend_status = CAIRO_INT_STATUS_UNSUPPORTED; |
799 | if (surface->target->backend->show_text_glyphs != NULL((void*)0)) { |
800 | backend_status = |
801 | surface->target->backend->show_text_glyphs (surface->target, op, |
802 | source, |
803 | utf8, utf8_len, |
804 | glyphs, num_glyphs, |
805 | clusters, num_clusters, |
806 | cluster_flags, |
807 | scaled_font, |
808 | clip); |
809 | if (_cairo_int_status_is_error (backend_status)((backend_status) != CAIRO_INT_STATUS_SUCCESS && (backend_status ) < CAIRO_INT_STATUS_LAST_STATUS)) |
810 | return backend_status; |
811 | } |
812 | if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && |
813 | surface->target->backend->show_glyphs != NULL((void*)0)) |
814 | { |
815 | backend_status = |
816 | surface->target->backend->show_glyphs (surface->target, op, |
817 | source, |
818 | glyphs, num_glyphs, |
819 | scaled_font, |
820 | clip); |
821 | if (_cairo_int_status_is_error (backend_status)((backend_status) != CAIRO_INT_STATUS_SUCCESS && (backend_status ) < CAIRO_INT_STATUS_LAST_STATUS)) |
822 | return backend_status; |
823 | } |
824 | |
825 | _cairo_analysis_surface_operation_extents (surface, |
826 | op, source, clip, |
827 | &extents); |
828 | if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { |
829 | cairo_rectangle_int_t rec_extents; |
830 | _analyze_recording_surface_pattern (surface, |
831 | source, |
832 | &rec_extents, |
833 | &surface->source_region_id, |
834 | CAIRO_ANALYSIS_SOURCE_SHOW_GLYPHS); |
835 | _cairo_rectangle_intersect (&extents, &rec_extents); |
836 | } |
837 | |
838 | if (_cairo_operator_bounded_by_mask (op)) { |
839 | status = _cairo_scaled_font_glyph_device_extents (scaled_font, |
840 | glyphs, |
841 | num_glyphs, |
842 | &glyph_extents, |
843 | NULL((void*)0)); |
844 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
845 | return status; |
846 | |
847 | _cairo_rectangle_intersect (&extents, &glyph_extents); |
848 | } |
849 | |
850 | return _add_operation (surface, &extents, backend_status); |
851 | } |
852 | |
853 | static cairo_int_status_t |
854 | _cairo_analysis_surface_tag (void *abstract_surface, |
855 | cairo_bool_t begin, |
856 | const char *tag_name, |
857 | const char *attributes) |
858 | { |
859 | cairo_analysis_surface_t *surface = abstract_surface; |
860 | cairo_int_status_t backend_status; |
861 | |
862 | surface->source_region_id = 0; |
863 | surface->mask_region_id = 0; |
864 | backend_status = CAIRO_INT_STATUS_SUCCESS; |
865 | if (surface->target->backend->tag != NULL((void*)0)) { |
866 | backend_status = |
867 | surface->target->backend->tag (surface->target, |
868 | begin, |
869 | tag_name, |
870 | attributes); |
871 | if (backend_status == CAIRO_INT_STATUS_SUCCESS) |
872 | surface->has_supported = TRUE1; |
873 | } |
874 | |
875 | return backend_status; |
876 | } |
877 | |
878 | static cairo_bool_t |
879 | _cairo_analysis_surface_supports_color_glyph (void *abstract_surface, |
880 | cairo_scaled_font_t *scaled_font, |
881 | unsigned long glyph_index) |
882 | { |
883 | return TRUE1; |
884 | } |
885 | |
886 | static cairo_int_status_t |
887 | _cairo_analysis_surface_command_id (void *abstract_surface, |
888 | unsigned int recording_id, |
889 | unsigned int command_id) |
890 | { |
891 | cairo_analysis_surface_t *surface = abstract_surface; |
892 | cairo_int_status_t backend_status; |
893 | |
894 | backend_status = CAIRO_INT_STATUS_SUCCESS; |
895 | if (surface->target->backend->command_id != NULL((void*)0)) { |
896 | backend_status = |
897 | surface->target->backend->command_id (surface->target, |
898 | recording_id, |
899 | command_id); |
900 | } |
901 | |
902 | return backend_status; |
903 | } |
904 | |
905 | static const cairo_surface_backend_t cairo_analysis_surface_backend = { |
906 | CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS, |
907 | |
908 | _cairo_analysis_surface_finish, |
909 | NULL((void*)0), |
910 | |
911 | NULL((void*)0), /* create_similar */ |
912 | NULL((void*)0), /* create_similar_image */ |
913 | NULL((void*)0), /* map_to_image */ |
914 | NULL((void*)0), /* unmap */ |
915 | |
916 | NULL((void*)0), /* source */ |
917 | NULL((void*)0), /* acquire_source_image */ |
918 | NULL((void*)0), /* release_source_image */ |
919 | NULL((void*)0), /* snapshot */ |
920 | |
921 | NULL((void*)0), /* copy_page */ |
922 | NULL((void*)0), /* show_page */ |
923 | |
924 | _cairo_analysis_surface_get_extents, |
925 | NULL((void*)0), /* get_font_options */ |
926 | |
927 | NULL((void*)0), /* flush */ |
928 | NULL((void*)0), /* mark_dirty_rectangle */ |
929 | |
930 | _cairo_analysis_surface_paint, |
931 | _cairo_analysis_surface_mask, |
932 | _cairo_analysis_surface_stroke, |
933 | _cairo_analysis_surface_fill, |
934 | NULL((void*)0), /* fill_stroke */ |
935 | _cairo_analysis_surface_show_glyphs, |
936 | _cairo_analysis_surface_has_show_text_glyphs, |
937 | _cairo_analysis_surface_show_text_glyphs, |
938 | NULL((void*)0), /* get_supported_mime_types */ |
939 | _cairo_analysis_surface_tag, |
940 | _cairo_analysis_surface_supports_color_glyph, |
941 | NULL((void*)0), /* analyze_recording_surface */ |
942 | _cairo_analysis_surface_command_id, |
943 | }; |
944 | |
945 | cairo_surface_t * |
946 | _cairo_analysis_surface_create (cairo_surface_t *target, |
947 | cairo_bool_t create_region_ids) |
948 | { |
949 | cairo_analysis_surface_t *surface; |
950 | cairo_status_t status; |
951 | |
952 | status = target->status; |
953 | if (unlikely (status)(__builtin_expect (!!(status), 0))) |
954 | return _cairo_surface_create_in_error (status); |
955 | |
956 | surface = _cairo_malloc (sizeof (cairo_analysis_surface_t))((sizeof (cairo_analysis_surface_t)) != 0 ? malloc(sizeof (cairo_analysis_surface_t )) : ((void*)0)); |
957 | if (unlikely (surface == NULL)(__builtin_expect (!!(surface == ((void*)0)), 0))) |
958 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
959 | |
960 | /* I believe the content type here is truly arbitrary. I'm quite |
961 | * sure nothing will ever use this value. */ |
962 | _cairo_surface_init (&surface->base, |
963 | &cairo_analysis_surface_backend, |
964 | NULL((void*)0), /* device */ |
965 | CAIRO_CONTENT_COLOR_ALPHA, |
966 | target->is_vector); |
967 | |
968 | cairo_matrix_init_identity_moz_cairo_matrix_init_identity (&surface->ctm); |
969 | surface->has_ctm = FALSE0; |
970 | |
971 | surface->target = cairo_surface_reference_moz_cairo_surface_reference (target); |
972 | surface->first_op = TRUE1; |
973 | surface->has_supported = FALSE0; |
974 | surface->has_unsupported = FALSE0; |
975 | |
976 | surface->create_region_ids = create_region_ids; |
977 | surface->source_region_id = 0; |
978 | surface->mask_region_id = 0; |
979 | |
980 | _cairo_region_init (&surface->supported_region); |
981 | _cairo_region_init (&surface->fallback_region); |
982 | |
983 | surface->page_bbox.p1.x = 0; |
984 | surface->page_bbox.p1.y = 0; |
985 | surface->page_bbox.p2.x = 0; |
986 | surface->page_bbox.p2.y = 0; |
987 | |
988 | return &surface->base; |
989 | } |
990 | |
991 | void |
992 | _cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface, |
993 | const cairo_matrix_t *ctm) |
994 | { |
995 | cairo_analysis_surface_t *surface; |
996 | |
997 | if (abstract_surface->status) |
998 | return; |
999 | |
1000 | surface = (cairo_analysis_surface_t *) abstract_surface; |
1001 | |
1002 | surface->ctm = *ctm; |
1003 | surface->has_ctm = ! _cairo_matrix_is_identity (&surface->ctm); |
1004 | } |
1005 | |
1006 | void |
1007 | _cairo_analysis_surface_get_ctm (cairo_surface_t *abstract_surface, |
1008 | cairo_matrix_t *ctm) |
1009 | { |
1010 | cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; |
1011 | |
1012 | *ctm = surface->ctm; |
1013 | } |
1014 | |
1015 | |
1016 | cairo_region_t * |
1017 | _cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface) |
1018 | { |
1019 | cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; |
1020 | |
1021 | return &surface->supported_region; |
1022 | } |
1023 | |
1024 | cairo_region_t * |
1025 | _cairo_analysis_surface_get_unsupported (cairo_surface_t *abstract_surface) |
1026 | { |
1027 | cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; |
1028 | |
1029 | return &surface->fallback_region; |
1030 | } |
1031 | |
1032 | cairo_bool_t |
1033 | _cairo_analysis_surface_has_supported (cairo_surface_t *abstract_surface) |
1034 | { |
1035 | cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; |
1036 | |
1037 | return surface->has_supported; |
1038 | } |
1039 | |
1040 | cairo_bool_t |
1041 | _cairo_analysis_surface_has_unsupported (cairo_surface_t *abstract_surface) |
1042 | { |
1043 | cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; |
1044 | |
1045 | return surface->has_unsupported; |
1046 | } |
1047 | |
1048 | void |
1049 | _cairo_analysis_surface_get_bounding_box (cairo_surface_t *abstract_surface, |
1050 | cairo_box_t *bbox) |
1051 | { |
1052 | cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; |
1053 | |
1054 | *bbox = surface->page_bbox; |
1055 | } |
1056 | |
1057 | unsigned int |
1058 | _cairo_analysis_surface_get_source_region_id (cairo_surface_t *abstract_surface) |
1059 | { |
1060 | cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; |
1061 | |
1062 | return surface->source_region_id; |
1063 | } |
1064 | |
1065 | unsigned int |
1066 | _cairo_analysis_surface_get_mask_region_id (cairo_surface_t *abstract_surface) |
1067 | { |
1068 | cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; |
1069 | |
1070 | return surface->mask_region_id; |
1071 | } |
1072 | |
1073 | |
1074 | /* null surface type: a surface that does nothing (has no side effects, yay!) */ |
1075 | |
1076 | static cairo_int_status_t |
1077 | _paint_return_success (void *surface, |
1078 | cairo_operator_t op, |
1079 | const cairo_pattern_t *source, |
1080 | const cairo_clip_t *clip) |
1081 | { |
1082 | if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { |
1083 | cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; |
1084 | if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) |
1085 | return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; |
1086 | } |
1087 | |
1088 | return CAIRO_INT_STATUS_SUCCESS; |
1089 | } |
1090 | |
1091 | static cairo_int_status_t |
1092 | _mask_return_success (void *surface, |
1093 | cairo_operator_t op, |
1094 | const cairo_pattern_t *source, |
1095 | const cairo_pattern_t *mask, |
1096 | const cairo_clip_t *clip) |
1097 | { |
1098 | if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { |
1099 | cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; |
1100 | if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) |
1101 | return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; |
1102 | } |
1103 | |
1104 | if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) { |
1105 | cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask; |
1106 | if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) |
1107 | return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; |
1108 | } |
1109 | |
1110 | return CAIRO_INT_STATUS_SUCCESS; |
1111 | } |
1112 | |
1113 | static cairo_int_status_t |
1114 | _stroke_return_success (void *surface, |
1115 | cairo_operator_t op, |
1116 | const cairo_pattern_t *source, |
1117 | const cairo_path_fixed_t *path, |
1118 | const cairo_stroke_style_t *style, |
1119 | const cairo_matrix_t *ctm, |
1120 | const cairo_matrix_t *ctm_inverse, |
1121 | double tolerance, |
1122 | cairo_antialias_t antialias, |
1123 | const cairo_clip_t *clip) |
1124 | { |
1125 | if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { |
1126 | cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; |
1127 | if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) |
1128 | return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; |
1129 | } |
1130 | |
1131 | return CAIRO_INT_STATUS_SUCCESS; |
1132 | } |
1133 | |
1134 | static cairo_int_status_t |
1135 | _fill_return_success (void *surface, |
1136 | cairo_operator_t op, |
1137 | const cairo_pattern_t *source, |
1138 | const cairo_path_fixed_t *path, |
1139 | cairo_fill_rule_t fill_rule, |
1140 | double tolerance, |
1141 | cairo_antialias_t antialias, |
1142 | const cairo_clip_t *clip) |
1143 | { |
1144 | if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { |
1145 | cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; |
1146 | if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) |
1147 | return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; |
1148 | } |
1149 | |
1150 | return CAIRO_INT_STATUS_SUCCESS; |
1151 | } |
1152 | |
1153 | static cairo_int_status_t |
1154 | _show_glyphs_return_success (void *surface, |
1155 | cairo_operator_t op, |
1156 | const cairo_pattern_t *source, |
1157 | cairo_glyph_t *glyphs, |
1158 | int num_glyphs, |
1159 | cairo_scaled_font_t *scaled_font, |
1160 | const cairo_clip_t *clip) |
1161 | { |
1162 | if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { |
1163 | cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; |
1164 | if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) |
1165 | return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; |
1166 | } |
1167 | |
1168 | return CAIRO_INT_STATUS_SUCCESS; |
1169 | } |
1170 | |
1171 | static const cairo_surface_backend_t cairo_null_surface_backend = { |
1172 | CAIRO_INTERNAL_SURFACE_TYPE_NULL, |
1173 | NULL((void*)0), /* finish */ |
1174 | |
1175 | NULL((void*)0), /* only accessed through the surface functions */ |
1176 | |
1177 | NULL((void*)0), /* create_similar */ |
1178 | NULL((void*)0), /* create similar image */ |
1179 | NULL((void*)0), /* map to image */ |
1180 | NULL((void*)0), /* unmap image*/ |
1181 | |
1182 | NULL((void*)0), /* source */ |
1183 | NULL((void*)0), /* acquire_source_image */ |
1184 | NULL((void*)0), /* release_source_image */ |
1185 | NULL((void*)0), /* snapshot */ |
1186 | |
1187 | NULL((void*)0), /* copy_page */ |
1188 | NULL((void*)0), /* show_page */ |
1189 | |
1190 | NULL((void*)0), /* get_extents */ |
1191 | NULL((void*)0), /* get_font_options */ |
1192 | |
1193 | NULL((void*)0), /* flush */ |
1194 | NULL((void*)0), /* mark_dirty_rectangle */ |
1195 | |
1196 | _paint_return_success, /* paint */ |
1197 | _mask_return_success, /* mask */ |
1198 | _stroke_return_success, /* stroke */ |
1199 | _fill_return_success, /* fill */ |
1200 | NULL((void*)0), /* fill_stroke */ |
1201 | _show_glyphs_return_success, /* show_glyphs */ |
1202 | NULL((void*)0), /* has_show_text_glyphs */ |
1203 | NULL((void*)0), /* show_text_glyphs */ |
1204 | NULL((void*)0), /* get_supported_mime_types */ |
1205 | NULL((void*)0), /* tag */ |
1206 | NULL((void*)0), /* supports_color_glyph */ |
1207 | NULL((void*)0), /* analyze_recording_surface */ |
1208 | NULL((void*)0), /* command_id*/ |
1209 | }; |
1210 | |
1211 | cairo_surface_t * |
1212 | _cairo_null_surface_create (cairo_content_t content) |
1213 | { |
1214 | cairo_surface_t *surface; |
1215 | |
1216 | surface = _cairo_malloc (sizeof (cairo_surface_t))((sizeof (cairo_surface_t)) != 0 ? malloc(sizeof (cairo_surface_t )) : ((void*)0)); |
1217 | if (unlikely (surface == NULL)(__builtin_expect (!!(surface == ((void*)0)), 0))) { |
1218 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
1219 | } |
1220 | |
1221 | _cairo_surface_init (surface, |
1222 | &cairo_null_surface_backend, |
1223 | NULL((void*)0), /* device */ |
1224 | content, |
1225 | TRUE1); /* is_vector */ |
1226 | |
1227 | return surface; |
1228 | } |