Bug Summary

File:root/firefox-clang/gfx/cairo/cairo/src/cairo-analysis-surface.c
Warning:line 386, column 2
Value stored to 'unused' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_c_gfx_cairo_cairo_src0.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D HAVE_FT_LOAD_SFNT_TABLE -D PACKAGE_VERSION="moz" -D PACKAGE_BUGREPORT="http://bugzilla.mozilla.org/" -D CAIRO_HAS_PTHREAD -D _GNU_SOURCE -D MOZ_TREE_PIXMAN -D SIZEOF_VOID_P=__SIZEOF_POINTER__ -D SIZEOF_INT=__SIZEOF_INT__ -D SIZEOF_LONG=__SIZEOF_LONG__ -D SIZEOF_LONG_LONG=__SIZEOF_LONG_LONG__ -D HAVE_UINT64_T -D HAVE_CXX11_ATOMIC_PRIMITIVES -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/gfx/cairo/cairo/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/freetype2 -I /usr/include/libpng16 -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-enum-compare -Wno-int-to-pointer-cast -Wno-int-conversion -Wno-incompatible-pointer-types -Wno-sign-compare -Wno-type-limits -Wno-missing-field-initializers -Wno-conversion -Wno-narrowing -Wno-switch -Wno-unused -Wno-unused-variable -Wno-error=uninitialized -Wno-absolute-value -Wno-deprecated-register -Wno-incompatible-pointer-types -Wno-macro-redefined -Wno-shift-negative-value -Wno-tautological-compare -Wno-tautological-constant-out-of-range-compare -Wno-unreachable-code -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-26-231904-1820671-1 -x c Unified_c_gfx_cairo_cairo_src0.c
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
50typedef 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
72cairo_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
104struct proxy {
105 cairo_surface_t base;
106 cairo_surface_t *target;
107};
108
109static cairo_status_t
110proxy_finish (void *abstract_surface)
111{
112 return CAIRO_STATUS_SUCCESS;
113}
114
115static const cairo_surface_backend_t proxy_backend = {
116 CAIRO_INTERNAL_SURFACE_TYPE_NULL,
117 proxy_finish,
118};
119
120static cairo_surface_t *
121attach_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
138static void
139detach_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
145static 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
262static 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
414static 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
427static 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
436static 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
443static 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
464static 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
502static 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
582static 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
643static 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
694static 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
768static 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
776static 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
853static 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
878static 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
886static 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
905static 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
945cairo_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
991void
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
1006void
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
1016cairo_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
1024cairo_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
1032cairo_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
1040cairo_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
1048void
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
1057unsigned 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
1065unsigned 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
1076static 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
1091static 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
1113static 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
1134static 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
1153static 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
1171static 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
1211cairo_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}