Bug Summary

File:root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c
Warning:line 8177, column 5
4th function call argument is an uninitialized value

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 cairo-pdf-surface.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 /root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c
1/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2/* cairo - a vector graphics library with display and print output
3 *
4 * Copyright © 2004 Red Hat, Inc
5 * Copyright © 2006 Red Hat, Inc
6 * Copyright © 2007, 2008 Adrian Johnson
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it either under the terms of the GNU Lesser General Public
10 * License version 2.1 as published by the Free Software Foundation
11 * (the "LGPL") or, at your option, under the terms of the Mozilla
12 * Public License Version 1.1 (the "MPL"). If you do not alter this
13 * notice, a recipient may use your version of this file under either
14 * the MPL or the LGPL.
15 *
16 * You should have received a copy of the LGPL along with this library
17 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19 * You should have received a copy of the MPL along with this library
20 * in the file COPYING-MPL-1.1
21 *
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License at
25 * http://www.mozilla.org/MPL/
26 *
27 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29 * the specific language governing rights and limitations.
30 *
31 * The Original Code is the cairo graphics library.
32 *
33 * The Initial Developer of the Original Code is University of Southern
34 * California.
35 *
36 * Contributor(s):
37 * Kristian Høgsberg <krh@redhat.com>
38 * Carl Worth <cworth@cworth.org>
39 * Adrian Johnson <ajohnson@redneon.com>
40 */
41
42#define _DEFAULT_SOURCE1 /* for snprintf() */
43#include "cairoint.h"
44
45#include "cairo-pdf.h"
46#include "cairo-pdf-surface-private.h"
47#include "cairo-pdf-operators-private.h"
48#include "cairo-pdf-shading-private.h"
49
50#include "cairo-array-private.h"
51#include "cairo-analysis-surface-private.h"
52#include "cairo-composite-rectangles-private.h"
53#include "cairo-default-context-private.h"
54#include "cairo-error-private.h"
55#include "cairo-image-surface-inline.h"
56#include "cairo-image-info-private.h"
57#include "cairo-recording-surface-inline.h"
58#include "cairo-recording-surface-private.h"
59#include "cairo-output-stream-private.h"
60#include "cairo-paginated-private.h"
61#include "cairo-scaled-font-subsets-private.h"
62#include "cairo-surface-clipper-private.h"
63#include "cairo-surface-snapshot-inline.h"
64#include "cairo-surface-subsurface-private.h"
65#include "cairo-type3-glyph-surface-private.h"
66
67#include <zlib.h>
68
69/*
70 * Page Structure of the Generated PDF:
71 *
72 * Each page requiring fallbacks images contains a knockout group at
73 * the top level. The first operation of the knockout group paints a
74 * group containing all the supported drawing operations. Fallback
75 * images (if any) are painted in the knockout group. This ensures
76 * that fallback images do not composite with any content under the
77 * fallback images.
78 *
79 * Streams:
80 *
81 * This PDF surface has three types of streams:
82 * - PDF Stream
83 * - Content Stream
84 * - Group Stream
85 * - Object stream
86 *
87 * Calling _cairo_output_stream_printf (surface->output, ...) will
88 * write to the currently open stream.
89 *
90 * PDF Stream:
91 * A PDF Stream may be opened and closed with the following functions:
92 * _cairo_pdf_surface_open stream ()
93 * _cairo_pdf_surface_close_stream ()
94 *
95 * PDF Streams are written directly to the PDF file. They are used for
96 * fonts, images and patterns.
97 *
98 * Content Stream:
99 * The Content Stream is opened and closed with the following functions:
100 * _cairo_pdf_surface_open_content_stream ()
101 * _cairo_pdf_surface_close_content_stream ()
102 *
103 * The Content Stream contains the text and graphics operators.
104 *
105 * Group Stream:
106 * A Group Stream may be opened and closed with the following functions:
107 * _cairo_pdf_surface_open_group ()
108 * _cairo_pdf_surface_close_group ()
109 *
110 * A Group Stream is a Form XObject. It is used for short sequences
111 * of operators. As the content is very short the group is stored in
112 * memory until it is closed. This allows some optimization such as
113 * including the Resource dictionary and stream length inside the
114 * XObject instead of using an indirect object.
115 *
116 * Object Stream (PDF 1.5)
117 * An Object Stream may be opened and closed with the following functions:
118 * _cairo_pdf_surface_open_object_stream ()
119 * _cairo_pdf_surface_close_object_stream ()
120 *
121 * An Object Stream contains one or more objects compressed into a stream.
122 * Only non stream objects are permitted. When emitting objects intended for
123 * the Object Stream, enclose the emit object operation with
124 * _cairo_pdf_surface_object_begin()/_cairo_pdf_surface_object_end().
125 */
126
127/**
128 * SECTION:cairo-pdf
129 * @Title: PDF Surfaces
130 * @Short_Description: Rendering PDF documents
131 * @See_Also: #cairo_surface_t
132 *
133 * The PDF surface is used to render cairo graphics to Adobe
134 * PDF files and is a multi-page vector surface backend.
135 *
136 * The following mime types are supported on source patterns:
137 * %CAIRO_MIME_TYPE_JPEG, %CAIRO_MIME_TYPE_JP2,
138 * %CAIRO_MIME_TYPE_UNIQUE_ID, %CAIRO_MIME_TYPE_JBIG2,
139 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL, %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
140 * %CAIRO_MIME_TYPE_CCITT_FAX, %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS.
141 *
142 * # JBIG2 Images #
143 * JBIG2 data in PDF must be in the embedded format as described in
144 * ISO/IEC 11544. Image specific JBIG2 data must be in
145 * %CAIRO_MIME_TYPE_JBIG2. Any global segments in the JBIG2 data
146 * (segments with page association field set to 0) must be in
147 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data may be shared by
148 * multiple images. All images sharing the same global data must set
149 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID to a unique identifier. At least
150 * one of the images must provide the global data using
151 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data will only be
152 * embedded once and shared by all JBIG2 images with the same
153 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
154 *
155 * # CCITT Fax Images # {#ccitt}
156 * The %CAIRO_MIME_TYPE_CCITT_FAX mime data requires a number of decoding
157 * parameters These parameters are specified using %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS.
158 *
159 * %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS mime data must contain a string of the form
160 * "param1=value1 param2=value2 ...".
161 *
162 * @Columns: [required] An integer specifying the width of the image in pixels.
163 *
164 * @Rows: [required] An integer specifying the height of the image in scan lines.
165 *
166 * @K: [optional] An integer identifying the encoding scheme used. < 0
167 * is 2 dimensional Group 4, = 0 is Group3 1 dimensional, > 0 is mixed 1
168 * and 2 dimensional encoding. Default is 0.
169 *
170 * @EndOfLine: [optional] If true end-of-line bit patterns are present. Default is false.
171 *
172 * @EncodedByteAlign: [optional] If true the end of line is padded
173 * with 0 bits so the next line begins on a byte boundary. Default is false.
174 *
175 * @EndOfBlock: [optional] If true the data contains an end-of-block pattern. Default is true.
176 *
177 * @BlackIs1: [optional] If true 1 bits are black pixels. Default is false.
178 *
179 * @DamagedRowsBeforeError: [optional] An integer specifying the
180 * number of damages rows tolerated before an error occurs. Default is 0.
181 *
182 * Boolean values may be "true" or "false", or 1 or 0.
183 *
184 * These parameters are the same as the CCITTFaxDecode parameters in the
185 * [PostScript Language Reference](https://www.adobe.com/products/postscript/pdfs/PLRM.pdf)
186 * and [Portable Document Format (PDF)](https://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf).
187 * Refer to these documents for further details.
188 *
189 * An example %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS string is:
190 *
191 * <programlisting>
192 * "Columns=10230 Rows=40000 K=1 EndOfLine=true EncodedByteAlign=1 BlackIs1=false"
193 * </programlisting>
194 *
195 **/
196
197static cairo_bool_t
198_cairo_pdf_surface_get_extents (void *abstract_surface,
199 cairo_rectangle_int_t *rectangle);
200
201/**
202 * CAIRO_HAS_PDF_SURFACE:
203 *
204 * Defined if the PDF surface backend is available.
205 * This macro can be used to conditionally compile backend-specific code.
206 *
207 * Since: 1.2
208 **/
209
210static const cairo_pdf_version_t _cairo_pdf_versions[] =
211{
212 CAIRO_PDF_VERSION_1_4,
213 CAIRO_PDF_VERSION_1_5,
214 CAIRO_PDF_VERSION_1_6,
215 CAIRO_PDF_VERSION_1_7
216};
217
218#define CAIRO_PDF_VERSION_LAST((int) (sizeof (_cairo_pdf_versions) / sizeof (_cairo_pdf_versions
[0])))
ARRAY_LENGTH (_cairo_pdf_versions)((int) (sizeof (_cairo_pdf_versions) / sizeof (_cairo_pdf_versions
[0])))
219
220static const char * _cairo_pdf_version_strings[CAIRO_PDF_VERSION_LAST((int) (sizeof (_cairo_pdf_versions) / sizeof (_cairo_pdf_versions
[0])))
] =
221{
222 "PDF 1.4",
223 "PDF 1.5",
224 "PDF 1.6",
225 "PDF 1.7"
226};
227
228static const char *_cairo_pdf_supported_mime_types[] =
229{
230 CAIRO_MIME_TYPE_JPEG"image/jpeg",
231 CAIRO_MIME_TYPE_JP2"image/jp2",
232 CAIRO_MIME_TYPE_UNIQUE_ID"application/x-cairo.uuid",
233 CAIRO_MIME_TYPE_JBIG2"application/x-cairo.jbig2",
234 CAIRO_MIME_TYPE_JBIG2_GLOBAL"application/x-cairo.jbig2-global",
235 CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID"application/x-cairo.jbig2-global-id",
236 CAIRO_MIME_TYPE_CCITT_FAX"image/g3fax",
237 CAIRO_MIME_TYPE_CCITT_FAX_PARAMS"application/x-cairo.ccitt.params",
238 NULL((void*)0)
239};
240
241/* PDF cross-reference stream types */
242typedef enum {
243 PDF_OBJECT_FREE = 0,
244 PDF_OBJECT_UNCOMPRESSED = 1,
245 PDF_OBJECT_COMPRESSED = 2,
246} cairo_pdf_object_type_t;
247
248typedef struct _cairo_pdf_object {
249 cairo_pdf_object_type_t type;
250 union {
251 long long offset; /* type == PDF_OBJECT_UNCOMPRESSED */
252 struct compressed_obj { /* type == PDF_OBJECT_COMPRESSED */
253 cairo_pdf_resource_t xref_stream;
254 int index;
255 } compressed_obj;
256 } u;
257} cairo_pdf_object_t;
258
259typedef struct _cairo_xref_stream_object {
260 cairo_pdf_resource_t resource;
261 long long offset;
262} cairo_xref_stream_object_t;
263
264typedef struct _cairo_pdf_font {
265 unsigned int font_id;
266 unsigned int subset_id;
267 cairo_pdf_resource_t subset_resource;
268} cairo_pdf_font_t;
269
270typedef struct _cairo_pdf_rgb_linear_function {
271 cairo_pdf_resource_t resource;
272 double color1[3];
273 double color2[3];
274} cairo_pdf_rgb_linear_function_t;
275
276typedef struct _cairo_pdf_alpha_linear_function {
277 cairo_pdf_resource_t resource;
278 double alpha1;
279 double alpha2;
280} cairo_pdf_alpha_linear_function_t;
281
282static void
283_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface,
284 cairo_bool_t clear_doc_surfaces);
285
286static void
287_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
288
289static cairo_int_status_t
290_cairo_pdf_surface_add_font (unsigned int font_id,
291 unsigned int subset_id,
292 void *closure);
293
294static void
295_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
296
297static cairo_int_status_t
298_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
299 cairo_pdf_resource_t *resource,
300 cairo_bool_t compressed,
301 const char *fmt,
302 ...) CAIRO_PRINTF_FORMAT(4, 5)__attribute__((__format__(__printf__, 4, 5)));
303static cairo_int_status_t
304_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface);
305
306static cairo_int_status_t
307_cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface,
308 cairo_pdf_source_surface_t *source,
309 cairo_bool_t test,
310 cairo_bool_t *is_image);
311
312static cairo_int_status_t
313_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
314
315static cairo_int_status_t
316_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
317
318static cairo_int_status_t
319_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface,
320 cairo_pdf_resource_t catalog);
321
322static long long
323_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
324
325static cairo_int_status_t
326_cairo_pdf_surface_write_xref_stream (cairo_pdf_surface_t *surface,
327 cairo_pdf_resource_t xref_res,
328 cairo_pdf_resource_t root_res,
329 cairo_pdf_resource_t info_res,
330 long long *xref_offset);
331
332static cairo_int_status_t
333_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface,
334 cairo_bool_t finish);
335
336static cairo_int_status_t
337_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
338
339static cairo_bool_t
340_cairo_pdf_source_surface_equal (const void *key_a, const void *key_b);
341
342static cairo_bool_t
343_cairo_pdf_color_glyph_equal (const void *key_a, const void *key_b);
344
345static const cairo_surface_backend_t cairo_pdf_surface_backend;
346static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
347
348cairo_pdf_resource_t
349_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
350{
351 cairo_pdf_resource_t resource;
352 cairo_int_status_t status;
353 cairo_pdf_object_t object;
354
355 /* Default to Uncompressed. If this object is used with
356 * _cairo_pdf_surface_object_begin() and Object Streams are
357 * enabled it will be changed to Compressed. */
358 object.type = PDF_OBJECT_UNCOMPRESSED;
359 object.u.offset = _cairo_output_stream_get_position (surface->output);
360
361 status = _cairo_array_append (&surface->objects, &object);
362 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
363 resource.id = 0;
364 return resource;
365 }
366
367 resource = surface->next_available_resource;
368 surface->next_available_resource.id++;
369
370 return resource;
371}
372
373void
374_cairo_pdf_surface_update_object (cairo_pdf_surface_t *surface,
375 cairo_pdf_resource_t resource)
376{
377 cairo_pdf_object_t *object;
378
379 object = _cairo_array_index (&surface->objects, resource.id - 1);
380 object->u.offset = _cairo_output_stream_get_position (surface->output);
381}
382
383static void
384_cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
385 double width,
386 double height)
387{
388 surface->width = width;
389 surface->height = height;
390 surface->surface_extents.x = 0;
391 surface->surface_extents.y = 0;
392 surface->surface_extents.width = ceil (surface->width);
393 surface->surface_extents.height = ceil (surface->height);
394}
395
396static cairo_bool_t
397_path_covers_bbox (cairo_pdf_surface_t *surface,
398 cairo_path_fixed_t *path)
399{
400 cairo_box_t box;
401
402 return _cairo_path_fixed_is_box (path, &box) &&
403 box.p1.x <= 0 &&
404 box.p1.y <= 0 &&
405 box.p2.x >= _cairo_fixed_from_double (surface->width) &&
406 box.p2.y >= _cairo_fixed_from_double (surface->height);
407}
408
409static cairo_status_t
410_cairo_pdf_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
411 cairo_path_fixed_t *path,
412 cairo_fill_rule_t fill_rule,
413 double tolerance,
414 cairo_antialias_t antialias)
415{
416 cairo_pdf_surface_t *surface = cairo_container_of (clipper,({ const __typeof__ (((cairo_pdf_surface_t *) 0)->clipper)
*mptr__ = (clipper); (cairo_pdf_surface_t *) ((char *) mptr__
- __builtin_offsetof(cairo_pdf_surface_t, clipper)); })
417 cairo_pdf_surface_t,({ const __typeof__ (((cairo_pdf_surface_t *) 0)->clipper)
*mptr__ = (clipper); (cairo_pdf_surface_t *) ((char *) mptr__
- __builtin_offsetof(cairo_pdf_surface_t, clipper)); })
418 clipper)({ const __typeof__ (((cairo_pdf_surface_t *) 0)->clipper)
*mptr__ = (clipper); (cairo_pdf_surface_t *) ((char *) mptr__
- __builtin_offsetof(cairo_pdf_surface_t, clipper)); })
;
419 cairo_int_status_t status;
420
421 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
422 if (unlikely (status)(__builtin_expect (!!(status), 0)))
423 return status;
424
425 if (path == NULL((void*)0)) {
426 _cairo_output_stream_printf (surface->output, "Q q\n");
427
428 surface->current_pattern_is_solid_color = FALSE0;
429 surface->current_operator = CAIRO_OPERATOR_OVER;
430 _cairo_pdf_operators_reset (&surface->pdf_operators);
431
432 return CAIRO_STATUS_SUCCESS;
433 }
434
435 if (_path_covers_bbox (surface, path))
436 return CAIRO_STATUS_SUCCESS;
437
438 return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
439}
440
441static cairo_surface_t *
442_cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
443 double width,
444 double height)
445{
446 cairo_pdf_surface_t *surface;
447 cairo_status_t status, status_ignored;
448
449 surface = _cairo_malloc (sizeof (cairo_pdf_surface_t))((sizeof (cairo_pdf_surface_t)) != 0 ? malloc(sizeof (cairo_pdf_surface_t
)) : ((void*)0))
;
450 if (unlikely (surface == NULL)(__builtin_expect (!!(surface == ((void*)0)), 0))) {
451 /* destroy stream on behalf of caller */
452 status = _cairo_output_stream_destroy (output);
453 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
454 }
455
456 _cairo_surface_init (&surface->base,
457 &cairo_pdf_surface_backend,
458 NULL((void*)0), /* device */
459 CAIRO_CONTENT_COLOR_ALPHA,
460 TRUE1); /* is_vector */
461
462 surface->output = output;
463 surface->width = width;
464 surface->height = height;
465 cairo_matrix_init_moz_cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, 1, 0, 0);
466 surface->in_xobject = FALSE0;
467 surface->surface_extents.x = 0;
468 surface->surface_extents.y = 0;
469 surface->surface_extents.width = ceil (surface->width);
470 surface->surface_extents.height = ceil (surface->height);
471 surface->surface_bounded = TRUE1;
472
473 _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
474 _cairo_array_init (&surface->pages, sizeof (cairo_pdf_page_info_t));
475 _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
476 _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
477 _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
478 _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
479 _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t));
480
481 _cairo_array_init (&surface->page_patterns, sizeof (cairo_pdf_pattern_t));
482 _cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t));
483 _cairo_array_init (&surface->doc_surfaces, sizeof (cairo_pdf_source_surface_t));
484 _cairo_array_init (&surface->jbig2_global, sizeof (cairo_pdf_jbig2_global_t));
485 surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal);
486 if (unlikely (surface->all_surfaces == NULL)(__builtin_expect (!!(surface->all_surfaces == ((void*)0))
, 0))
) {
487 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
488 goto BAIL0;
489 }
490
491 surface->color_glyphs = _cairo_hash_table_create (_cairo_pdf_color_glyph_equal);
492 if (unlikely (surface->color_glyphs == NULL)(__builtin_expect (!!(surface->color_glyphs == ((void*)0))
, 0))
) {
493 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
494 goto BAIL1;
495 }
496
497 surface->duplicate_surface_number = 0;
498
499 _cairo_pdf_group_resources_init (&surface->resources);
500
501 surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
502 if (! surface->font_subsets) {
503 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
504 goto BAIL2;
505 }
506
507 _cairo_scaled_font_subsets_enable_latin_subset (surface->font_subsets, TRUE1);
508
509 surface->next_available_resource.id = 1;
510 surface->pages_resource = _cairo_pdf_surface_new_object (surface);
511 if (surface->pages_resource.id == 0) {
512 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
513 goto BAIL3;
514 }
515
516 surface->struct_tree_root.id = 0;
517 surface->pdf_version = CAIRO_PDF_VERSION_1_7;
518 surface->compress_streams = TRUE1;
519 surface->pdf_stream.active = FALSE0;
520 surface->pdf_stream.old_output = NULL((void*)0);
521 surface->group_stream.active = FALSE0;
522 surface->group_stream.stream = NULL((void*)0);
523 surface->group_stream.mem_stream = NULL((void*)0);
524 surface->object_stream.active = FALSE0;
525 surface->object_stream.stream = NULL((void*)0);
526 _cairo_array_init (&surface->object_stream.objects, sizeof (cairo_xref_stream_object_t));
527
528 surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
529 surface->type3_replay = FALSE0;
530
531 surface->force_fallbacks = FALSE0;
532 surface->select_pattern_gstate_saved = FALSE0;
533 surface->current_pattern_is_solid_color = FALSE0;
534 surface->current_operator = CAIRO_OPERATOR_OVER;
535 surface->reset_gs_required = FALSE0;
536 surface->header_emitted = FALSE0;
537
538 _cairo_surface_clipper_init (&surface->clipper,
539 _cairo_pdf_surface_clipper_intersect_clip_path);
540
541 _cairo_pdf_operators_init (&surface->pdf_operators,
542 surface->output,
543 &surface->cairo_to_pdf,
544 surface->font_subsets,
545 FALSE0);
546 _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
547 _cairo_pdf_surface_add_font,
548 surface);
549 _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators, TRUE1);
550
551 status = _cairo_pdf_interchange_init (surface);
552 if (unlikely (status)(__builtin_expect (!!(status), 0)))
553 goto BAIL3;
554
555 surface->page_parent_tree = -1;
556 _cairo_array_init (&surface->page_annots, sizeof (cairo_pdf_resource_t));
557 surface->tagged = FALSE0;
558 surface->current_page_label = NULL((void*)0);
559 _cairo_array_init (&surface->page_labels, sizeof (char *));
560 surface->outlines_dict_res.id = 0;
561 surface->names_dict_res.id = 0;
562 surface->docinfo_res.id = 0;
563 surface->page_labels_res.id = 0;
564 surface->thumbnail_width = 0;
565 surface->thumbnail_height = 0;
566 surface->thumbnail_image = NULL((void*)0);
567
568 surface->debug = FALSE0;
569 if (getenv ("CAIRO_DEBUG_PDF") != NULL((void*)0)) {
570 surface->debug = TRUE1;
571 surface->compress_streams = FALSE0;
572 }
573
574 surface->paginated_surface = _cairo_paginated_surface_create (
575 &surface->base,
576 CAIRO_CONTENT_COLOR_ALPHA,
577 &cairo_pdf_surface_paginated_backend);
578
579 status = surface->paginated_surface->status;
580 if (status == CAIRO_STATUS_SUCCESS) {
581 /* paginated keeps the only reference to surface now, drop ours */
582 cairo_surface_destroy_moz_cairo_surface_destroy (&surface->base);
583 return surface->paginated_surface;
584 }
585
586BAIL3:
587 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
588BAIL2:
589 _cairo_hash_table_destroy (surface->color_glyphs);
590BAIL1:
591 _cairo_hash_table_destroy (surface->all_surfaces);
592BAIL0:
593 _cairo_array_fini (&surface->objects);
594 free (surface);
595
596 /* destroy stream on behalf of caller */
597 status_ignored = _cairo_output_stream_destroy (output);
598
599 return _cairo_surface_create_in_error (status);
600}
601
602/**
603 * cairo_pdf_surface_create_for_stream:
604 * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
605 * to indicate a no-op @write_func. With a no-op @write_func,
606 * the surface may be queried or used as a source without
607 * generating any temporary files.
608 * @closure: the closure argument for @write_func
609 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
610 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
611 *
612 * Creates a PDF surface of the specified size in points to be written
613 * incrementally to the stream represented by @write_func and @closure.
614 *
615 * Return value: a pointer to the newly created surface. The caller
616 * owns the surface and should call cairo_surface_destroy() when done
617 * with it.
618 *
619 * This function always returns a valid pointer, but it will return a
620 * pointer to a "nil" surface if an error such as out of memory
621 * occurs. You can use cairo_surface_status() to check for this.
622 *
623 * Since: 1.2
624 **/
625cairo_surface_t *
626cairo_pdf_surface_create_for_stream_moz_cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func,
627 void *closure,
628 double width_in_points,
629 double height_in_points)
630{
631 cairo_output_stream_t *output;
632
633 output = _cairo_output_stream_create (write_func, NULL((void*)0), closure);
634 if (_cairo_output_stream_get_status (output))
635 return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
636
637 return _cairo_pdf_surface_create_for_stream_internal (output,
638 width_in_points,
639 height_in_points);
640}
641
642/**
643 * cairo_pdf_surface_create:
644 * @filename: a filename for the PDF output (must be writable), %NULL may be
645 * used to specify no output. This will generate a PDF surface that
646 * may be queried and used as a source, without generating a
647 * temporary file.
648 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
649 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
650 *
651 * Creates a PDF surface of the specified size in points to be written
652 * to @filename.
653 *
654 * Return value: a pointer to the newly created surface. The caller
655 * owns the surface and should call cairo_surface_destroy() when done
656 * with it.
657 *
658 * This function always returns a valid pointer, but it will return a
659 * pointer to a "nil" surface if an error such as out of memory
660 * occurs. You can use cairo_surface_status() to check for this.
661 *
662 * Since: 1.2
663 **/
664cairo_surface_t *
665cairo_pdf_surface_create_moz_cairo_pdf_surface_create (const char *filename,
666 double width_in_points,
667 double height_in_points)
668{
669 cairo_output_stream_t *output;
670
671 output = _cairo_output_stream_create_for_filename (filename);
672 if (_cairo_output_stream_get_status (output))
673 return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
674
675 return _cairo_pdf_surface_create_for_stream_internal (output,
676 width_in_points,
677 height_in_points);
678}
679
680static cairo_bool_t
681_cairo_surface_is_pdf (cairo_surface_t *surface)
682{
683 return surface->backend == &cairo_pdf_surface_backend;
684}
685
686/* If the abstract_surface is a paginated surface, and that paginated
687 * surface's target is a pdf_surface, then set pdf_surface to that
688 * target. Otherwise return FALSE.
689 */
690static cairo_bool_t
691_extract_pdf_surface (cairo_surface_t *surface,
692 cairo_pdf_surface_t **pdf_surface)
693{
694 cairo_surface_t *target;
695 cairo_status_t status_ignored;
696
697 if (surface->status)
698 return FALSE0;
699 if (surface->finished) {
700 status_ignored = _cairo_surface_set_error (surface,
701 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
702 return FALSE0;
703 }
704
705 if (! _cairo_surface_is_paginated (surface)) {
706 status_ignored = _cairo_surface_set_error (surface,
707 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
708 return FALSE0;
709 }
710
711 target = _cairo_paginated_surface_get_target (surface);
712 if (target->status) {
713 status_ignored = _cairo_surface_set_error (surface,
714 target->status);
715 return FALSE0;
716 }
717 if (target->finished) {
718 status_ignored = _cairo_surface_set_error (surface,
719 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
720 return FALSE0;
721 }
722
723 if (! _cairo_surface_is_pdf (target)) {
724 status_ignored = _cairo_surface_set_error (surface,
725 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
726 return FALSE0;
727 }
728
729 *pdf_surface = (cairo_pdf_surface_t *) target;
730 return TRUE1;
731}
732
733/**
734 * cairo_pdf_surface_restrict_to_version:
735 * @surface: a PDF #cairo_surface_t
736 * @version: PDF version
737 *
738 * Restricts the generated PDF file to @version. See cairo_pdf_get_versions()
739 * for a list of available version values that can be used here.
740 *
741 * This function should only be called before any drawing operations
742 * have been performed on the given surface. The simplest way to do
743 * this is to call this function immediately after creating the
744 * surface.
745 *
746 * Since: 1.10
747 **/
748void
749cairo_pdf_surface_restrict_to_version_moz_cairo_pdf_surface_restrict_to_version (cairo_surface_t *abstract_surface,
750 cairo_pdf_version_t version)
751{
752 cairo_pdf_surface_t *surface = NULL((void*)0); /* hide compiler warning */
753
754 if (! _extract_pdf_surface (abstract_surface, &surface))
755 return;
756
757 if (version < CAIRO_PDF_VERSION_LAST((int) (sizeof (_cairo_pdf_versions) / sizeof (_cairo_pdf_versions
[0])))
)
758 surface->pdf_version = version;
759
760 _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators,
761 version >= CAIRO_PDF_VERSION_1_5);
762}
763
764/**
765 * cairo_pdf_get_versions:
766 * @versions: supported version list
767 * @num_versions: list length
768 *
769 * Used to retrieve the list of supported versions. See
770 * cairo_pdf_surface_restrict_to_version().
771 *
772 * Since: 1.10
773 **/
774void
775cairo_pdf_get_versions_moz_cairo_pdf_get_versions (cairo_pdf_version_t const **versions,
776 int *num_versions)
777{
778 if (versions != NULL((void*)0))
779 *versions = _cairo_pdf_versions;
780
781 if (num_versions != NULL((void*)0))
782 *num_versions = CAIRO_PDF_VERSION_LAST((int) (sizeof (_cairo_pdf_versions) / sizeof (_cairo_pdf_versions
[0])))
;
783}
784
785/**
786 * cairo_pdf_version_to_string:
787 * @version: a version id
788 *
789 * Get the string representation of the given @version id. This function
790 * will return %NULL if @version isn't valid. See cairo_pdf_get_versions()
791 * for a way to get the list of valid version ids.
792 *
793 * Return value: the string associated to given version.
794 *
795 * Since: 1.10
796 **/
797const char *
798cairo_pdf_version_to_string_moz_cairo_pdf_version_to_string (cairo_pdf_version_t version)
799{
800 if (version < 0 || version >= CAIRO_PDF_VERSION_LAST((int) (sizeof (_cairo_pdf_versions) / sizeof (_cairo_pdf_versions
[0])))
)
801 return NULL((void*)0);
802
803 return _cairo_pdf_version_strings[version];
804}
805
806/**
807 * cairo_pdf_surface_set_size:
808 * @surface: a PDF #cairo_surface_t
809 * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
810 * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
811 *
812 * Changes the size of a PDF surface for the current (and
813 * subsequent) pages.
814 *
815 * This function should only be called before any drawing operations
816 * have been performed on the current page. The simplest way to do
817 * this is to call this function immediately after creating the
818 * surface or immediately after completing a page with either
819 * cairo_show_page() or cairo_copy_page().
820 *
821 * Since: 1.2
822 **/
823void
824cairo_pdf_surface_set_size_moz_cairo_pdf_surface_set_size (cairo_surface_t *surface,
825 double width_in_points,
826 double height_in_points)
827{
828 cairo_pdf_surface_t *pdf_surface = NULL((void*)0); /* hide compiler warning */
829 cairo_status_t status;
830
831 if (! _extract_pdf_surface (surface, &pdf_surface))
832 return;
833
834 _cairo_pdf_surface_set_size_internal (pdf_surface,
835 width_in_points,
836 height_in_points);
837 status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
838 width_in_points,
839 height_in_points);
840 if (status)
841 status = _cairo_surface_set_error (surface, status);
842}
843
844/**
845 * CAIRO_PDF_OUTLINE_ROOT:
846 *
847 * The root outline item in cairo_pdf_surface_add_outline().
848 *
849 * Since: 1.16
850 **/
851
852/**
853 * cairo_pdf_surface_add_outline:
854 * @surface: a PDF #cairo_surface_t
855 * @parent_id: the id of the parent item or %CAIRO_PDF_OUTLINE_ROOT if this is a top level item.
856 * @utf8: the name of the outline
857 * @link_attribs: the link attributes specifying where this outline links to
858 * @flags: outline item flags
859 *
860 * Add an item to the document outline hierarchy with the name @utf8
861 * that links to the location specified by @link_attribs. Link
862 * attributes have the same keys and values as the [Link Tag][link],
863 * excluding the "rect" attribute. The item will be a child of the
864 * item with id @parent_id. Use %CAIRO_PDF_OUTLINE_ROOT as the parent
865 * id of top level items.
866 *
867 * Return value: the id for the added item.
868 *
869 * Since: 1.16
870 **/
871int
872cairo_pdf_surface_add_outline (cairo_surface_t *surface,
873 int parent_id,
874 const char *utf8,
875 const char *link_attribs,
876 cairo_pdf_outline_flags_t flags)
877{
878 cairo_pdf_surface_t *pdf_surface = NULL((void*)0); /* hide compiler warning */
879 cairo_status_t status;
880 int id = 0;
881
882 if (! _extract_pdf_surface (surface, &pdf_surface))
883 return 0;
884
885 status = _cairo_pdf_interchange_add_outline (pdf_surface,
886 parent_id,
887 utf8,
888 link_attribs,
889 flags,
890 &id);
891 if (status)
892 status = _cairo_surface_set_error (surface, status);
893
894 return id;
895}
896
897/**
898 * cairo_pdf_surface_set_metadata:
899 * @surface: a PDF #cairo_surface_t
900 * @metadata: The metadata item to set.
901 * @utf8: metadata value
902 *
903 * Set document metadata. The %CAIRO_PDF_METADATA_CREATE_DATE and
904 * %CAIRO_PDF_METADATA_MOD_DATE values must be in ISO-8601 format:
905 * YYYY-MM-DDThh:mm:ss. An optional timezone of the form "[+/-]hh:mm"
906 * or "Z" for UTC time can be appended. All other metadata values can be any UTF-8
907 * string.
908 *
909 * For example:
910 * <informalexample><programlisting>
911 * cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_TITLE, "My Document");
912 * cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_CREATE_DATE, "2015-12-31T23:59+02:00");
913 * </programlisting></informalexample>
914 *
915 * Since: 1.16
916 **/
917void
918cairo_pdf_surface_set_metadata (cairo_surface_t *surface,
919 cairo_pdf_metadata_t metadata,
920 const char *utf8)
921{
922 cairo_pdf_surface_t *pdf_surface = NULL((void*)0); /* hide compiler warning */
923 cairo_status_t status;
924
925 if (! _extract_pdf_surface (surface, &pdf_surface))
926 return;
927
928 status = _cairo_pdf_interchange_set_metadata (pdf_surface, metadata, utf8);
929 if (status)
930 status = _cairo_surface_set_error (surface, status);
931}
932
933/**
934 * cairo_pdf_surface_set_custom_metadata:
935 * @surface: a PDF #cairo_surface_t
936 * @name: The name of the custom metadata item to set (utf8).
937 * @value: The value of the metadata (utf8).
938 *
939 * Set custom document metadata. @name may be any string except for
940 * the following names reserved by PDF: "Title", "Author", "Subject",
941 * "Keywords", "Creator", "Producer", "CreationDate", "ModDate",
942 * "Trapped".
943 *
944 * If @value is NULL or an empty string, the @name metadata will not be set.
945 *
946 * For example:
947 * <informalexample><programlisting>
948 * cairo_pdf_surface_set_custom_metadata (surface, "ISBN", "978-0123456789");
949 * </programlisting></informalexample>
950 *
951 * Since: 1.18
952 **/
953void
954cairo_pdf_surface_set_custom_metadata (cairo_surface_t *surface,
955 const char *name,
956 const char *value)
957{
958 cairo_pdf_surface_t *pdf_surface = NULL((void*)0); /* hide compiler warning */
959 cairo_status_t status;
960
961 if (! _extract_pdf_surface (surface, &pdf_surface))
962 return;
963
964 status = _cairo_pdf_interchange_set_custom_metadata (pdf_surface, name, value);
965 if (status)
966 status = _cairo_surface_set_error (surface, status);
967}
968
969/**
970 * cairo_pdf_surface_set_page_label:
971 * @surface: a PDF #cairo_surface_t
972 * @utf8: The page label.
973 *
974 * Set page label for the current page.
975 *
976 * Since: 1.16
977 **/
978void
979cairo_pdf_surface_set_page_label (cairo_surface_t *surface,
980 const char *utf8)
981{
982 cairo_pdf_surface_t *pdf_surface = NULL((void*)0); /* hide compiler warning */
983
984 if (! _extract_pdf_surface (surface, &pdf_surface))
985 return;
986
987 free (pdf_surface->current_page_label);
988 pdf_surface->current_page_label = utf8 ? strdup (utf8) : NULL((void*)0);
989}
990
991/**
992 * cairo_pdf_surface_set_thumbnail_size:
993 * @surface: a PDF #cairo_surface_t
994 * @width: Thumbnail width.
995 * @height: Thumbnail height
996 *
997 * Set the thumbnail image size for the current and all subsequent
998 * pages. Setting a width or height of 0 disables thumbnails for the
999 * current and subsequent pages.
1000 *
1001 * Since: 1.16
1002 **/
1003void
1004cairo_pdf_surface_set_thumbnail_size (cairo_surface_t *surface,
1005 int width,
1006 int height)
1007{
1008 cairo_pdf_surface_t *pdf_surface = NULL((void*)0); /* hide compiler warning */
1009
1010 if (! _extract_pdf_surface (surface, &pdf_surface))
1011 return;
1012
1013 pdf_surface->thumbnail_width = width;
1014 pdf_surface->thumbnail_height = height;
1015}
1016
1017static void
1018_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface,
1019 cairo_bool_t clear_doc_surfaces)
1020{
1021 int i, size;
1022 cairo_pdf_pattern_t *pattern;
1023 cairo_pdf_source_surface_t *src_surface;
1024 cairo_pdf_smask_group_t *group;
1025 cairo_pdf_source_surface_t doc_surface;
1026
1027 size = _cairo_array_num_elements (&surface->page_patterns);
1028 for (i = 0; i < size; i++) {
1029 pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->page_patterns, i);
1030 cairo_pattern_destroy_moz_cairo_pattern_destroy (pattern->pattern);
1031 }
1032 _cairo_array_truncate (&surface->page_patterns, 0);
1033
1034 size = _cairo_array_num_elements (&surface->page_surfaces);
1035 for (i = 0; i < size; i++) {
1036 src_surface = (cairo_pdf_source_surface_t *) _cairo_array_index (&surface->page_surfaces, i);
1037 if (src_surface->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1038 cairo_pattern_destroy_moz_cairo_pattern_destroy (src_surface->raster_pattern);
1039 } else {
1040 if (_cairo_surface_is_recording (src_surface->surface) && src_surface->region_id != 0)
1041 _cairo_recording_surface_region_array_remove (src_surface->surface, src_surface->region_id);
1042 cairo_surface_destroy_moz_cairo_surface_destroy (src_surface->surface);
1043 }
1044 }
1045 _cairo_array_truncate (&surface->page_surfaces, 0);
1046
1047 size = _cairo_array_num_elements (&surface->smask_groups);
1048 for (i = 0; i < size; i++) {
1049 _cairo_array_copy_element (&surface->smask_groups, i, &group);
1050 _cairo_pdf_smask_group_destroy (group);
1051 }
1052 _cairo_array_truncate (&surface->smask_groups, 0);
1053 _cairo_array_truncate (&surface->knockout_group, 0);
1054 _cairo_array_truncate (&surface->page_annots, 0);
1055
1056 if (surface->thumbnail_image)
1057 cairo_surface_destroy_moz_cairo_surface_destroy (&surface->thumbnail_image->base);
1058 surface->thumbnail_image = NULL((void*)0);
1059
1060 if (clear_doc_surfaces) {
1061 size = _cairo_array_num_elements (&surface->doc_surfaces);
1062 for (i = 0; i < size; i++) {
1063 _cairo_array_copy_element (&surface->doc_surfaces, i, &doc_surface);
1064 if (doc_surface.type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1065 cairo_pattern_destroy_moz_cairo_pattern_destroy (doc_surface.raster_pattern);
1066 } else {
1067 if (_cairo_surface_is_recording (doc_surface.surface) && doc_surface.region_id != 0)
1068 _cairo_recording_surface_region_array_remove (doc_surface.surface, doc_surface.region_id);
1069 cairo_surface_destroy_moz_cairo_surface_destroy (doc_surface.surface);
1070 }
1071 }
1072 _cairo_array_truncate (&surface->doc_surfaces, 0);
1073 }
1074}
1075
1076static void
1077_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
1078{
1079 int i;
1080
1081 for (i = 0; i < CAIRO_NUM_OPERATORS(CAIRO_OPERATOR_HSL_LUMINOSITY + 1); i++)
1082 res->operators[i] = FALSE0;
1083
1084 _cairo_array_init (&res->alphas, sizeof (double));
1085 _cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t));
1086 _cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t));
1087 _cairo_array_init (&res->shadings, sizeof (cairo_pdf_resource_t));
1088 _cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t));
1089 _cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t));
1090}
1091
1092static void
1093_cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
1094{
1095 _cairo_array_fini (&res->alphas);
1096 _cairo_array_fini (&res->smasks);
1097 _cairo_array_fini (&res->patterns);
1098 _cairo_array_fini (&res->shadings);
1099 _cairo_array_fini (&res->xobjects);
1100 _cairo_array_fini (&res->fonts);
1101}
1102
1103static void
1104_cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
1105{
1106 int i;
1107
1108 for (i = 0; i < CAIRO_NUM_OPERATORS(CAIRO_OPERATOR_HSL_LUMINOSITY + 1); i++)
1109 res->operators[i] = FALSE0;
1110
1111 _cairo_array_truncate (&res->alphas, 0);
1112 _cairo_array_truncate (&res->smasks, 0);
1113 _cairo_array_truncate (&res->patterns, 0);
1114 _cairo_array_truncate (&res->shadings, 0);
1115 _cairo_array_truncate (&res->xobjects, 0);
1116 _cairo_array_truncate (&res->fonts, 0);
1117}
1118
1119static void
1120_cairo_pdf_surface_add_operator (cairo_pdf_surface_t *surface,
1121 cairo_operator_t op)
1122{
1123 cairo_pdf_group_resources_t *res = &surface->resources;
1124
1125 res->operators[op] = TRUE1;
1126}
1127
1128static cairo_int_status_t
1129_cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
1130 double alpha,
1131 int *index)
1132{
1133 int num_alphas, i;
1134 double other;
1135 cairo_int_status_t status;
1136 cairo_pdf_group_resources_t *res = &surface->resources;
1137
1138 num_alphas = _cairo_array_num_elements (&res->alphas);
1139 for (i = 0; i < num_alphas; i++) {
1140 _cairo_array_copy_element (&res->alphas, i, &other);
1141 if (alpha == other) {
1142 *index = i;
1143 return CAIRO_STATUS_SUCCESS;
1144 }
1145 }
1146
1147 status = _cairo_array_append (&res->alphas, &alpha);
1148 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1149 return status;
1150
1151 *index = _cairo_array_num_elements (&res->alphas) - 1;
1152
1153 return CAIRO_STATUS_SUCCESS;
1154}
1155
1156static cairo_int_status_t
1157_cairo_pdf_surface_add_smask (cairo_pdf_surface_t *surface,
1158 cairo_pdf_resource_t smask)
1159{
1160 return _cairo_array_append (&(surface->resources.smasks), &smask);
1161}
1162
1163static cairo_int_status_t
1164_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t *surface,
1165 cairo_pdf_resource_t pattern)
1166{
1167 return _cairo_array_append (&(surface->resources.patterns), &pattern);
1168}
1169
1170static cairo_int_status_t
1171_cairo_pdf_surface_add_shading (cairo_pdf_surface_t *surface,
1172 cairo_pdf_resource_t shading)
1173{
1174 return _cairo_array_append (&(surface->resources.shadings), &shading);
1175}
1176
1177
1178static cairo_int_status_t
1179_cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface,
1180 cairo_pdf_resource_t xobject)
1181{
1182 return _cairo_array_append (&(surface->resources.xobjects), &xobject);
1183}
1184
1185static cairo_int_status_t
1186_cairo_pdf_surface_add_font (unsigned int font_id,
1187 unsigned int subset_id,
1188 void *closure)
1189{
1190 cairo_pdf_surface_t *surface = closure;
1191 cairo_pdf_font_t font;
1192 int num_fonts, i;
1193 cairo_int_status_t status;
1194 cairo_pdf_group_resources_t *res = &surface->resources;
1195
1196 num_fonts = _cairo_array_num_elements (&res->fonts);
1197 for (i = 0; i < num_fonts; i++) {
1198 _cairo_array_copy_element (&res->fonts, i, &font);
1199 if (font.font_id == font_id &&
1200 font.subset_id == subset_id)
1201 return CAIRO_STATUS_SUCCESS;
1202 }
1203
1204 num_fonts = _cairo_array_num_elements (&surface->fonts);
1205 for (i = 0; i < num_fonts; i++) {
1206 _cairo_array_copy_element (&surface->fonts, i, &font);
1207 if (font.font_id == font_id &&
1208 font.subset_id == subset_id)
1209 return _cairo_array_append (&res->fonts, &font);
1210 }
1211
1212 font.font_id = font_id;
1213 font.subset_id = subset_id;
1214 font.subset_resource = _cairo_pdf_surface_new_object (surface);
1215 if (font.subset_resource.id == 0)
1216 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1217
1218 status = _cairo_array_append (&surface->fonts, &font);
1219 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1220 return status;
1221
1222 return _cairo_array_append (&res->fonts, &font);
1223}
1224
1225static cairo_pdf_resource_t
1226_cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface,
1227 unsigned int font_id,
1228 unsigned int subset_id)
1229{
1230 cairo_pdf_font_t font;
1231 int num_fonts, i;
1232
1233 num_fonts = _cairo_array_num_elements (&surface->fonts);
1234 for (i = 0; i < num_fonts; i++) {
1235 _cairo_array_copy_element (&surface->fonts, i, &font);
1236 if (font.font_id == font_id && font.subset_id == subset_id)
1237 return font.subset_resource;
1238 }
1239
1240 font.subset_resource.id = 0;
1241 return font.subset_resource;
1242}
1243
1244static const char *
1245_cairo_operator_to_pdf_blend_mode (cairo_operator_t op)
1246{
1247 switch (op) {
1248 /* The extend blend mode operators */
1249 case CAIRO_OPERATOR_MULTIPLY: return "Multiply";
1250 case CAIRO_OPERATOR_SCREEN: return "Screen";
1251 case CAIRO_OPERATOR_OVERLAY: return "Overlay";
1252 case CAIRO_OPERATOR_DARKEN: return "Darken";
1253 case CAIRO_OPERATOR_LIGHTEN: return "Lighten";
1254 case CAIRO_OPERATOR_COLOR_DODGE: return "ColorDodge";
1255 case CAIRO_OPERATOR_COLOR_BURN: return "ColorBurn";
1256 case CAIRO_OPERATOR_HARD_LIGHT: return "HardLight";
1257 case CAIRO_OPERATOR_SOFT_LIGHT: return "SoftLight";
1258 case CAIRO_OPERATOR_DIFFERENCE: return "Difference";
1259 case CAIRO_OPERATOR_EXCLUSION: return "Exclusion";
1260 case CAIRO_OPERATOR_HSL_HUE: return "Hue";
1261 case CAIRO_OPERATOR_HSL_SATURATION: return "Saturation";
1262 case CAIRO_OPERATOR_HSL_COLOR: return "Color";
1263 case CAIRO_OPERATOR_HSL_LUMINOSITY: return "Luminosity";
1264
1265 default:
1266 /* The original Porter-Duff set */
1267 case CAIRO_OPERATOR_CLEAR:
1268 case CAIRO_OPERATOR_SOURCE:
1269 case CAIRO_OPERATOR_OVER:
1270 case CAIRO_OPERATOR_IN:
1271 case CAIRO_OPERATOR_OUT:
1272 case CAIRO_OPERATOR_ATOP:
1273 case CAIRO_OPERATOR_DEST:
1274 case CAIRO_OPERATOR_DEST_OVER:
1275 case CAIRO_OPERATOR_DEST_IN:
1276 case CAIRO_OPERATOR_DEST_OUT:
1277 case CAIRO_OPERATOR_DEST_ATOP:
1278 case CAIRO_OPERATOR_XOR:
1279 case CAIRO_OPERATOR_ADD:
1280 case CAIRO_OPERATOR_SATURATE:
1281 return "Normal";
1282 }
1283}
1284
1285static void
1286_cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface,
1287 cairo_pdf_group_resources_t *res,
1288 cairo_bool_t gs0)
1289{
1290 int num_alphas, num_smasks, num_resources, i;
1291 double alpha;
1292 cairo_pdf_resource_t *smask, *pattern, *shading, *xobject;
1293 cairo_pdf_font_t *font;
1294
1295 _cairo_output_stream_printf (surface->output, "<<\n");
1296
1297 num_alphas = _cairo_array_num_elements (&res->alphas);
1298 num_smasks = _cairo_array_num_elements (&res->smasks);
1299 if (num_alphas > 0 || num_smasks > 0) {
1300 _cairo_output_stream_printf (surface->output,
1301 " /ExtGState <<\n");
1302
1303 if (gs0) {
1304 _cairo_output_stream_printf (surface->output,
1305 " /gs0 << /BM /Normal /SMask /None /CA 1.0 /ca 1.0 >>\n");
1306 }
1307
1308 for (i = 0; i < CAIRO_NUM_OPERATORS(CAIRO_OPERATOR_HSL_LUMINOSITY + 1); i++) {
1309 if (res->operators[i]) {
1310 _cairo_output_stream_printf (surface->output,
1311 " /b%d << /BM /%s >>\n",
1312 i, _cairo_operator_to_pdf_blend_mode(i));
1313 }
1314 }
1315
1316 for (i = 0; i < num_alphas; i++) {
1317 _cairo_array_copy_element (&res->alphas, i, &alpha);
1318 _cairo_output_stream_printf (surface->output,
1319 " /a%d << /CA %f /ca %f >>\n",
1320 i, alpha, alpha);
1321 }
1322
1323 for (i = 0; i < num_smasks; i++) {
1324 smask = _cairo_array_index (&res->smasks, i);
1325 _cairo_output_stream_printf (surface->output,
1326 " /s%d %d 0 R\n",
1327 smask->id, smask->id);
1328 }
1329
1330 _cairo_output_stream_printf (surface->output,
1331 " >>\n");
1332 }
1333
1334 num_resources = _cairo_array_num_elements (&res->patterns);
1335 if (num_resources > 0) {
1336 _cairo_output_stream_printf (surface->output,
1337 " /Pattern <<");
1338 for (i = 0; i < num_resources; i++) {
1339 pattern = _cairo_array_index (&res->patterns, i);
1340 _cairo_output_stream_printf (surface->output,
1341 " /p%d %d 0 R",
1342 pattern->id, pattern->id);
1343 }
1344
1345 _cairo_output_stream_printf (surface->output,
1346 " >>\n");
1347 }
1348
1349 num_resources = _cairo_array_num_elements (&res->shadings);
1350 if (num_resources > 0) {
1351 _cairo_output_stream_printf (surface->output,
1352 " /Shading <<");
1353 for (i = 0; i < num_resources; i++) {
1354 shading = _cairo_array_index (&res->shadings, i);
1355 _cairo_output_stream_printf (surface->output,
1356 " /sh%d %d 0 R",
1357 shading->id, shading->id);
1358 }
1359
1360 _cairo_output_stream_printf (surface->output,
1361 " >>\n");
1362 }
1363
1364 num_resources = _cairo_array_num_elements (&res->xobjects);
1365 if (num_resources > 0) {
1366 _cairo_output_stream_printf (surface->output,
1367 " /XObject <<");
1368
1369 for (i = 0; i < num_resources; i++) {
1370 xobject = _cairo_array_index (&res->xobjects, i);
1371 _cairo_output_stream_printf (surface->output,
1372 " /x%d %d 0 R",
1373 xobject->id, xobject->id);
1374 }
1375
1376 _cairo_output_stream_printf (surface->output,
1377 " >>\n");
1378 }
1379
1380 num_resources = _cairo_array_num_elements (&res->fonts);
1381 if (num_resources > 0) {
1382 _cairo_output_stream_printf (surface->output," /Font <<\n");
1383 for (i = 0; i < num_resources; i++) {
1384 font = _cairo_array_index (&res->fonts, i);
1385 _cairo_output_stream_printf (surface->output,
1386 " /f-%d-%d %d 0 R\n",
1387 font->font_id,
1388 font->subset_id,
1389 font->subset_resource.id);
1390 }
1391 _cairo_output_stream_printf (surface->output, " >>\n");
1392 }
1393
1394 _cairo_output_stream_printf (surface->output,
1395 ">>\n");
1396}
1397
1398static cairo_pdf_smask_group_t *
1399_cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t *surface,
1400 const cairo_rectangle_int_t *extents)
1401{
1402 cairo_pdf_smask_group_t *group;
1403
1404 group = calloc (1, sizeof (cairo_pdf_smask_group_t));
1405 if (unlikely (group == NULL)(__builtin_expect (!!(group == ((void*)0)), 0))) {
1406 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
1407 return NULL((void*)0);
1408 }
1409
1410 group->group_res = _cairo_pdf_surface_new_object (surface);
1411 if (group->group_res.id == 0) {
1412 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
1413 free (group);
1414 return NULL((void*)0);
1415 }
1416 group->width = surface->width;
1417 group->height = surface->height;
1418 if (extents != NULL((void*)0)) {
1419 group->extents = *extents;
1420 } else {
1421 group->extents.x = 0;
1422 group->extents.y = 0;
1423 group->extents.width = surface->width;
1424 group->extents.height = surface->height;
1425 }
1426
1427 return group;
1428}
1429
1430static void
1431_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
1432{
1433 if (group->operation == PDF_FILL || group->operation == PDF_STROKE)
1434 _cairo_path_fixed_fini (&group->path);
1435 if (group->source)
1436 cairo_pattern_destroy_moz_cairo_pattern_destroy (group->source);
1437 if (group->mask)
1438 cairo_pattern_destroy_moz_cairo_pattern_destroy (group->mask);
1439 free (group->utf8);
1440 free (group->glyphs);
1441 free (group->clusters);
1442 if (group->scaled_font)
1443 cairo_scaled_font_destroy_moz_cairo_scaled_font_destroy (group->scaled_font);
1444 free (group);
1445}
1446
1447static cairo_int_status_t
1448_cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t *surface,
1449 cairo_pdf_smask_group_t *group)
1450{
1451 return _cairo_array_append (&surface->smask_groups, &group);
1452}
1453
1454static cairo_bool_t
1455_cairo_pdf_source_surface_equal (const void *key_a, const void *key_b)
1456{
1457 const cairo_pdf_source_surface_entry_t *a = key_a;
1458 const cairo_pdf_source_surface_entry_t *b = key_b;
1459
1460 if (a->interpolate != b->interpolate)
1461 return FALSE0;
1462
1463 if (a->region_id != b->region_id)
1464 return FALSE0;
1465
1466 if (a->unique_id && b->unique_id && a->unique_id_length == b->unique_id_length)
1467 return (memcmp (a->unique_id, b->unique_id, a->unique_id_length) == 0);
1468
1469 return (a->id == b->id);
1470}
1471
1472static void
1473_cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key)
1474{
1475 if (key->unique_id && key->unique_id_length > 0) {
1476 key->base.hash = _cairo_hash_bytes (_CAIRO_HASH_INIT_VALUE5381,
1477 key->unique_id, key->unique_id_length);
1478 } else {
1479 key->base.hash = key->id;
1480 }
1481 key->base.hash = _cairo_hash_bytes (key->base.hash,
1482 &key->region_id,
1483 sizeof(key->region_id));
1484}
1485
1486static cairo_bool_t
1487_cairo_pdf_color_glyph_equal (const void *key_a, const void *key_b)
1488{
1489 const cairo_pdf_color_glyph_t *a = key_a;
1490 const cairo_pdf_color_glyph_t *b = key_b;
1491
1492 if (a->scaled_font != b->scaled_font)
1493 return FALSE0;
1494
1495 return (a->glyph_index == b->glyph_index);
1496}
1497
1498static void
1499_cairo_pdf_color_glyph_init_key (cairo_pdf_color_glyph_t *key)
1500{
1501 key->base.hash = _cairo_hash_uintptr (_CAIRO_HASH_INIT_VALUE5381, (uintptr_t)key->scaled_font);
1502 key->base.hash = _cairo_hash_uintptr (key->base.hash, key->glyph_index);
1503}
1504
1505static cairo_int_status_t
1506_cairo_pdf_surface_acquire_source_image_from_pattern (cairo_pdf_surface_t *surface,
1507 const cairo_pattern_t *pattern,
1508 cairo_image_surface_t **image,
1509 void **image_extra)
1510{
1511 switch (pattern->type) {
30
Control jumps to 'case CAIRO_PATTERN_TYPE_RASTER_SOURCE:' at line 1517
1512 case CAIRO_PATTERN_TYPE_SURFACE: {
1513 cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
1514 return _cairo_surface_acquire_source_image (surf_pat->surface, image, image_extra);
1515 } break;
1516
1517 case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
1518 cairo_surface_t *surf;
1519 surf = _cairo_raster_source_pattern_acquire (pattern, &surface->base, NULL((void*)0));
1520 if (!surf)
31
Assuming 'surf' is non-null
32
Taking false branch
1521 return CAIRO_INT_STATUS_UNSUPPORTED;
1522 assert (_cairo_surface_is_image (surf))((void) sizeof ((_cairo_surface_is_image (surf)) ? 1 : 0), __extension__
({ if (_cairo_surface_is_image (surf)) ; else __assert_fail (
"_cairo_surface_is_image (surf)", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 1522, __extension__ __PRETTY_FUNCTION__); }))
;
33
Taking true branch
1523 *image = (cairo_image_surface_t *) surf;
1524 } break;
34
Execution continues on line 1535
1525
1526 case CAIRO_PATTERN_TYPE_SOLID:
1527 case CAIRO_PATTERN_TYPE_LINEAR:
1528 case CAIRO_PATTERN_TYPE_RADIAL:
1529 case CAIRO_PATTERN_TYPE_MESH:
1530 default:
1531 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 1531, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
1532 break;
1533 }
1534
1535 return CAIRO_STATUS_SUCCESS;
35
Returning without writing to '(*image)->base.status', which participates in a condition later
36
Returning without writing to '*image_extra'
1536}
1537
1538static void
1539_cairo_pdf_surface_release_source_image_from_pattern (cairo_pdf_surface_t *surface,
1540 const cairo_pattern_t *pattern,
1541 cairo_image_surface_t *image,
1542 void *image_extra)
1543{
1544 switch (pattern->type) {
1545 case CAIRO_PATTERN_TYPE_SURFACE: {
1546 cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
1547 _cairo_surface_release_source_image (surf_pat->surface, image, image_extra);
1548 } break;
1549
1550 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1551 _cairo_raster_source_pattern_release (pattern, &image->base);
1552 break;
1553
1554 case CAIRO_PATTERN_TYPE_SOLID:
1555 case CAIRO_PATTERN_TYPE_LINEAR:
1556 case CAIRO_PATTERN_TYPE_RADIAL:
1557 case CAIRO_PATTERN_TYPE_MESH:
1558 default:
1559
1560 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 1560, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
1561 break;
1562 }
1563}
1564
1565static cairo_int_status_t
1566_get_source_surface_extents (cairo_surface_t *source,
1567 cairo_rectangle_int_t *extents,
1568 cairo_bool_t *bounded,
1569 cairo_bool_t *subsurface)
1570{
1571 cairo_int_status_t status;
1572
1573 *bounded = TRUE1;
1574 *subsurface = FALSE0;
1575 if (source->type == CAIRO_SURFACE_TYPE_RECORDING) {
1576 cairo_surface_t *free_me = NULL((void*)0);
1577
1578 if (_cairo_surface_is_snapshot (source))
1579 free_me = source = _cairo_surface_snapshot_get_target (source);
1580
1581 if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1582 cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
1583
1584 *extents = sub->extents;
1585 *subsurface = TRUE1;
1586 } else {
1587 cairo_box_t box;
1588
1589 *bounded = _cairo_surface_get_extents (source, extents);
1590 if (! *bounded) {
1591 status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)source,
1592 &box, NULL((void*)0));
1593 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
1594 cairo_surface_destroy_moz_cairo_surface_destroy (free_me);
1595 return status;
1596 }
1597 _cairo_box_round_to_rectangle (&box, extents);
1598 }
1599 }
1600 cairo_surface_destroy_moz_cairo_surface_destroy (free_me);
1601 } else {
1602 *bounded = _cairo_surface_get_extents (source, extents);
1603 }
1604
1605 return CAIRO_STATUS_SUCCESS;
1606}
1607
1608/**
1609 * _cairo_pdf_surface_add_source_surface:
1610 * @surface: [in] the pdf surface
1611 * @source_surface: [in] A #cairo_surface_t to use as the source surface
1612 * @source_pattern: [in] A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source
1613 * @region_id: [in] Surfaces containing tags set this to the recording
1614 * surface region id. When tags are used in a XObject, PDF requires a
1615 * separate object for each use (section 14.7.4.2) @region_id is used
1616 * as a key to ensure a separate object is emitted for each use. Set
1617 * to 0 for surfaces without tags.
1618 * @op: [in] the operator used to composite this source
1619 * @filter: [in] filter type of the source pattern
1620 * @stencil_mask: [in] if true, the surface will be written to the PDF as an /ImageMask
1621 * @smask: [in] if true, only the alpha channel will be written (images only)
1622 * @need_transp_group: [in] if true and an XObject is used, make it a Transparency group
1623 * @extents: [in] extents of the operation that is using this source
1624 * @smask_res: [in] if not NULL, the image written will specify this resource as the smask for
1625 * the image (images only)
1626 * @pdf_source: [out] return pdf_source_surface entry in hash table
1627 * @x_offset: [out] if not NULL return x offset of surface
1628 * @y_offset: [out] if not NULL return y offset of surface
1629 * @source_extents: [out] if not NULL return operation extents in source space
1630 *
1631 * Add surface or raster_source pattern to list of surfaces to be
1632 * written to the PDF file when the current page is finished. Returns
1633 * a PDF resource to reference the surface. A hash table of all
1634 * surfaces in the PDF file (keyed by CAIRO_MIME_TYPE_UNIQUE_ID or
1635 * surface unique_id) is used to ensure surfaces with the same id are
1636 * only written once to the PDF file.
1637 *
1638 * Only one of @source_pattern or @source_surface is to be
1639 * specified. Set the other to NULL.
1640 **/
1641static cairo_int_status_t
1642_cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
1643 cairo_surface_t *source_surface,
1644 const cairo_pattern_t *source_pattern,
1645 int region_id,
1646 cairo_operator_t op,
1647 cairo_filter_t filter,
1648 cairo_bool_t stencil_mask,
1649 cairo_bool_t smask,
1650 cairo_bool_t need_transp_group,
1651 const cairo_rectangle_int_t *extents,
1652 cairo_pdf_resource_t *smask_res,
1653 cairo_pdf_source_surface_entry_t **pdf_source,
1654 double *x_offset,
1655 double *y_offset,
1656 cairo_rectangle_int_t *source_extents)
1657{
1658 cairo_pdf_source_surface_t src_surface;
1659 cairo_pdf_source_surface_entry_t surface_key;
1660 cairo_pdf_source_surface_entry_t *surface_entry;
1661 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
1662 cairo_bool_t interpolate;
1663 unsigned char *unique_id = NULL((void*)0);
1664 unsigned long unique_id_length = 0;
1665 cairo_image_surface_t *image;
1666 void *image_extra;
1667 cairo_box_t box;
1668 cairo_rectangle_int_t op_extents;
1669 double x, y;
1670 cairo_bool_t subsurface;
1671 cairo_bool_t emit_image;
1672
1673 switch (filter) {
1674 default:
1675 case CAIRO_FILTER_GOOD:
1676 case CAIRO_FILTER_BEST:
1677 case CAIRO_FILTER_BILINEAR:
1678 interpolate = TRUE1;
1679 break;
1680 case CAIRO_FILTER_FAST:
1681 case CAIRO_FILTER_NEAREST:
1682 case CAIRO_FILTER_GAUSSIAN:
1683 interpolate = FALSE0;
1684 break;
1685 }
1686
1687 x = 0;
1688 y = 0;
1689 if (source_pattern) {
1690 if (source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1691 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source_pattern,
1692 &image, &image_extra);
1693 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1694 return status;
1695 source_surface = &image->base;
1696 cairo_surface_get_device_offset_moz_cairo_surface_get_device_offset (source_surface, &x, &y);
1697 } else {
1698 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source_pattern;
1699 source_surface = surface_pattern->surface;
1700 }
1701 }
1702 if (x_offset)
1703 *x_offset = x;
1704 if (y_offset)
1705 *y_offset = y;
1706
1707 /* transform operation extents to pattern space */
1708 op_extents = *extents;
1709 if (source_pattern)
1710 {
1711 _cairo_box_from_rectangle (&box, extents);
1712 _cairo_matrix_transform_bounding_box_fixed (&source_pattern->matrix, &box, NULL((void*)0));
1713 _cairo_box_round_to_rectangle (&box, &op_extents);
1714 }
1715 if (source_extents)
1716 *source_extents = op_extents;
1717
1718 surface_key.id = source_surface->unique_id;
1719
1720 /* Recording surfaces do not use interpolate. Ensure it is always
1721 * false for recording surfaces. This is because pdf-interchange
1722 * needs to lookup recording surfaces in the hash table using
1723 * interpolate = FALSE in the key since it does not know the
1724 * interpolate value passed to this function.
1725 */
1726 emit_image = source_surface->type != CAIRO_SURFACE_TYPE_RECORDING;
1727 surface_key.interpolate = emit_image ? interpolate : FALSE0;
1728
1729 cairo_surface_get_mime_data_moz_cairo_surface_get_mime_data (source_surface, CAIRO_MIME_TYPE_UNIQUE_ID"application/x-cairo.uuid",
1730 (const unsigned char **) &surface_key.unique_id,
1731 &surface_key.unique_id_length);
1732
1733 surface_key.region_id = region_id;
1734 _cairo_pdf_source_surface_init_key (&surface_key);
1735 surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base);
1736 if (surface_entry) {
1737 if (pdf_source)
1738 *pdf_source = surface_entry;
1739
1740 if (source_pattern && source_pattern->extend != CAIRO_EXTEND_NONE)
1741 _cairo_unbounded_rectangle_init (&op_extents);
1742
1743 _cairo_rectangle_intersect (&op_extents, &surface_entry->extents);
1744 _cairo_rectangle_union (&surface_entry->required_extents, &op_extents);
1745 status = CAIRO_STATUS_SUCCESS;
1746 }
1747
1748 if (status || surface_entry) {
1749 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1750 _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra);
1751 return status;
1752 }
1753
1754 if (surface_key.unique_id && surface_key.unique_id_length > 0) {
1755 unique_id = _cairo_malloc (surface_key.unique_id_length)((surface_key.unique_id_length) != 0 ? malloc(surface_key.unique_id_length
) : ((void*)0))
;
1756 if (unique_id == NULL((void*)0)) {
1757 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1758 goto fail1;
1759 }
1760
1761 unique_id_length = surface_key.unique_id_length;
1762 memcpy (unique_id, surface_key.unique_id, unique_id_length);
1763 } else {
1764 unique_id = NULL((void*)0);
1765 unique_id_length = 0;
1766 }
1767
1768 surface_entry = _cairo_malloc (sizeof (cairo_pdf_source_surface_entry_t))((sizeof (cairo_pdf_source_surface_entry_t)) != 0 ? malloc(sizeof
(cairo_pdf_source_surface_entry_t)) : ((void*)0))
;
1769 if (surface_entry == NULL((void*)0)) {
1770 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1771 goto fail1;
1772 }
1773
1774 if (pdf_source)
1775 *pdf_source = surface_entry;
1776
1777 surface_entry->id = surface_key.id;
1778 surface_entry->region_id = region_id;
1779 surface_entry->operator = op;
1780 surface_entry->interpolate = emit_image ? interpolate : FALSE0;
1781 surface_entry->emit_image = emit_image;
1782 surface_entry->stencil_mask = stencil_mask;
1783 surface_entry->smask = smask;
1784 surface_entry->need_transp_group = need_transp_group;
1785 surface_entry->unique_id_length = unique_id_length;
1786 surface_entry->unique_id = unique_id;
1787 if (smask_res)
1788 surface_entry->smask_res = *smask_res;
1789 else
1790 surface_entry->smask_res.id = 0;
1791
1792 status = _get_source_surface_extents (source_surface,
1793 &surface_entry->extents,
1794 &surface_entry->bounded,
1795 &subsurface);
1796 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1797 goto fail2;
1798
1799 if (subsurface) {
1800 *x_offset = -surface_entry->extents.x;
1801 *y_offset = -surface_entry->extents.y;
1802 }
1803
1804 if (source_pattern && source_pattern->extend != CAIRO_EXTEND_NONE)
1805 _cairo_unbounded_rectangle_init (&op_extents);
1806
1807 _cairo_rectangle_intersect (&op_extents, &surface_entry->extents);
1808 surface_entry->required_extents = op_extents;
1809
1810 _cairo_pdf_source_surface_init_key (surface_entry);
1811
1812 src_surface.hash_entry = surface_entry;
1813 src_surface.region_id = 0;
1814 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1815 src_surface.type = CAIRO_PATTERN_TYPE_RASTER_SOURCE;
1816 src_surface.surface = NULL((void*)0);
1817 status = _cairo_pattern_create_copy (&src_surface.raster_pattern, source_pattern);
1818 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1819 goto fail2;
1820
1821 } else {
1822 src_surface.type = CAIRO_PATTERN_TYPE_SURFACE;
1823 src_surface.surface = cairo_surface_reference_moz_cairo_surface_reference (source_surface);
1824 src_surface.raster_pattern = NULL((void*)0);
1825 if (source_pattern) {
1826 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source_pattern;
1827 src_surface.region_id = surface_pattern->region_array_id;
1828 if (_cairo_surface_is_recording (surface_pattern->surface) &&
1829 surface_pattern->region_array_id != 0)
1830 {
1831 _cairo_recording_surface_region_array_reference (surface_pattern->surface,
1832 surface_pattern->region_array_id);
1833 }
1834 }
1835 }
1836
1837 surface_entry->surface_res = _cairo_pdf_surface_new_object (surface);
1838 if (surface_entry->surface_res.id == 0) {
1839 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1840 goto fail3;
1841 }
1842
1843 if (surface_entry->bounded) {
1844 status = _cairo_array_append (&surface->page_surfaces, &src_surface);
1845 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1846 goto fail3;
1847 } else {
1848 status = _cairo_array_append (&surface->doc_surfaces, &src_surface);
1849 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1850 goto fail3;
1851 }
1852
1853 status = _cairo_hash_table_insert (surface->all_surfaces,
1854 &surface_entry->base);
1855 if (unlikely(status)(__builtin_expect (!!(status), 0)))
1856 goto fail3;
1857
1858 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1859 _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra);
1860
1861 return CAIRO_STATUS_SUCCESS;
1862
1863fail3:
1864 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1865 cairo_pattern_destroy_moz_cairo_pattern_destroy (src_surface.raster_pattern);
1866 else
1867 cairo_surface_destroy_moz_cairo_surface_destroy (src_surface.surface);
1868
1869fail2:
1870 free (surface_entry);
1871
1872fail1:
1873 if (unique_id)
1874 free (unique_id);
1875
1876 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1877 _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra);
1878
1879 return status;
1880}
1881
1882static cairo_int_status_t
1883_cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface,
1884 const cairo_pattern_t *pattern,
1885 cairo_operator_t op,
1886 cairo_analysis_source_t source_type,
1887 const cairo_rectangle_int_t *extents,
1888 cairo_bool_t is_shading,
1889 cairo_pdf_resource_t *pattern_res,
1890 cairo_pdf_resource_t *gstate_res)
1891{
1892 cairo_pdf_pattern_t pdf_pattern;
1893 cairo_int_status_t status;
1894 int region_id = 0;
1895
1896 pdf_pattern.is_shading = is_shading;
1897 pdf_pattern.operator = op;
1898
1899 /* Solid colors are emitted into the content stream */
1900 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
1901 pattern_res->id = 0;
1902 gstate_res->id = 0;
1903 return CAIRO_INT_STATUS_SUCCESS;
1904 }
1905
1906 status = _cairo_pattern_create_copy (&pdf_pattern.pattern, pattern);
1907 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1908 return status;
1909
1910 pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface);
1911 if (pdf_pattern.pattern_res.id == 0) {
1912 cairo_pattern_destroy_moz_cairo_pattern_destroy (pdf_pattern.pattern);
1913 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1914 }
1915
1916 pdf_pattern.gstate_res.id = 0;
1917
1918 /* gradient patterns require an smask object to implement transparency */
1919 if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
1920 pattern->type == CAIRO_PATTERN_TYPE_RADIAL ||
1921 pattern->type == CAIRO_PATTERN_TYPE_MESH)
1922 {
1923 double min_alpha;
1924
1925 _cairo_pattern_alpha_range (pattern, &min_alpha, NULL((void*)0));
1926 if (! CAIRO_ALPHA_IS_OPAQUE (min_alpha)((min_alpha) >= ((double)0xff00 / (double)0xffff))) {
1927 pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
1928 if (pdf_pattern.gstate_res.id == 0) {
1929 cairo_pattern_destroy_moz_cairo_pattern_destroy (pdf_pattern.pattern);
1930 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1931 }
1932 }
1933 }
1934
1935 pdf_pattern.width = surface->width;
1936 pdf_pattern.height = surface->height;
1937 if (extents != NULL((void*)0)) {
1938 pdf_pattern.extents = *extents;
1939 } else {
1940 pdf_pattern.extents.x = 0;
1941 pdf_pattern.extents.y = 0;
1942 pdf_pattern.extents.width = surface->width;
1943 pdf_pattern.extents.height = surface->height;
1944 }
1945
1946 *pattern_res = pdf_pattern.pattern_res;
1947 *gstate_res = pdf_pattern.gstate_res;
1948 /* If the pattern requires a gstate it will be drawn from within
1949 * an XObject. The initial space of each XObject has an inverted
1950 * Y-axis. */
1951 pdf_pattern.inverted_y_axis = pdf_pattern.gstate_res.id ? TRUE1 : surface->in_xobject;
1952
1953 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
1954 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
1955 if (_cairo_pdf_interchange_struct_tree_requires_recording_surface (surface,
1956 surface_pattern,
1957 source_type))
1958 {
1959 region_id = surface_pattern->region_array_id;
1960 }
1961 }
1962 pdf_pattern.region_id = region_id;
1963
1964 status = _cairo_array_append (&surface->page_patterns, &pdf_pattern);
1965 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
1966 cairo_pattern_destroy_moz_cairo_pattern_destroy (pdf_pattern.pattern);
1967 return status;
1968 }
1969
1970 return CAIRO_INT_STATUS_SUCCESS;
1971}
1972
1973/* Get BBox from extents */
1974static void
1975_get_bbox_from_extents (const cairo_rectangle_int_t *extents,
1976 cairo_box_double_t *bbox)
1977{
1978 bbox->p1.x = extents->x;
1979 bbox->p1.y = extents->y;
1980 bbox->p2.x = extents->x + extents->width;
1981 bbox->p2.y = extents->y + extents->height;
1982}
1983
1984static cairo_int_status_t
1985_cairo_pdf_surface_add_pdf_shading (cairo_pdf_surface_t *surface,
1986 const cairo_pattern_t *pattern,
1987 cairo_operator_t op,
1988 const cairo_rectangle_int_t *extents,
1989 cairo_pdf_resource_t *shading_res,
1990 cairo_pdf_resource_t *gstate_res)
1991{
1992 return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
1993 pattern,
1994 op,
1995 CAIRO_ANALYSIS_SOURCE_NONE,
1996 extents,
1997 TRUE1,
1998 shading_res,
1999 gstate_res);
2000}
2001
2002static cairo_int_status_t
2003_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
2004 const cairo_pattern_t *pattern,
2005 cairo_operator_t op,
2006 cairo_analysis_source_t source_type,
2007 const cairo_rectangle_int_t *extents,
2008 cairo_pdf_resource_t *pattern_res,
2009 cairo_pdf_resource_t *gstate_res)
2010{
2011 return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
2012 pattern,
2013 op,
2014 source_type,
2015 extents,
2016 FALSE0,
2017 pattern_res,
2018 gstate_res);
2019}
2020
2021static cairo_int_status_t
2022_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
2023 cairo_pdf_resource_t *resource,
2024 cairo_bool_t compressed,
2025 const char *fmt,
2026 ...)
2027{
2028 va_list ap;
2029 cairo_pdf_resource_t self, length;
2030 cairo_output_stream_t *output = NULL((void*)0);
2031
2032 if (resource) {
2033 self = *resource;
2034 _cairo_pdf_surface_update_object (surface, self);
2035 } else {
2036 self = _cairo_pdf_surface_new_object (surface);
2037 if (self.id == 0)
2038 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2039 }
2040
2041 length = _cairo_pdf_surface_new_object (surface);
2042 if (length.id == 0)
2043 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2044
2045 if (compressed) {
2046 output = _cairo_deflate_stream_create (surface->output);
2047 if (_cairo_output_stream_get_status (output))
2048 return _cairo_output_stream_destroy (output);
2049 }
2050
2051 surface->pdf_stream.active = TRUE1;
2052 surface->pdf_stream.self = self;
2053 surface->pdf_stream.length = length;
2054 surface->pdf_stream.compressed = compressed;
2055 surface->current_pattern_is_solid_color = FALSE0;
2056 surface->current_operator = CAIRO_OPERATOR_OVER;
2057 _cairo_pdf_operators_reset (&surface->pdf_operators);
2058
2059 _cairo_output_stream_printf (surface->output,
2060 "%d 0 obj\n"
2061 "<< /Length %d 0 R\n",
2062 surface->pdf_stream.self.id,
2063 surface->pdf_stream.length.id);
2064 if (compressed)
2065 _cairo_output_stream_printf (surface->output,
2066 " /Filter /FlateDecode\n");
2067
2068 if (fmt != NULL((void*)0)) {
2069 va_start (ap, fmt)__builtin_va_start(ap, fmt);
2070 _cairo_output_stream_vprintf (surface->output, fmt, ap);
2071 va_end (ap)__builtin_va_end(ap);
2072 }
2073
2074 _cairo_output_stream_printf (surface->output,
2075 ">>\n"
2076 "stream\n");
2077
2078 surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
2079
2080 if (compressed) {
2081 assert (surface->pdf_stream.old_output == NULL)((void) sizeof ((surface->pdf_stream.old_output == ((void*
)0)) ? 1 : 0), __extension__ ({ if (surface->pdf_stream.old_output
== ((void*)0)) ; else __assert_fail ("surface->pdf_stream.old_output == NULL"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2081, __extension__ __PRETTY_FUNCTION__); }))
;
2082 surface->pdf_stream.old_output = surface->output;
2083 surface->output = output;
2084 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
2085 }
2086 _cairo_pdf_operators_reset (&surface->pdf_operators);
2087
2088 return _cairo_output_stream_get_status (surface->output);
2089}
2090
2091static cairo_int_status_t
2092_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
2093{
2094 cairo_int_status_t status;
2095 long long length;
2096
2097 if (! surface->pdf_stream.active)
2098 return CAIRO_INT_STATUS_SUCCESS;
2099
2100 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
2101
2102 if (surface->pdf_stream.compressed) {
2103 cairo_int_status_t status2;
2104
2105 status2 = _cairo_output_stream_destroy (surface->output);
2106 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
)
2107 status = status2;
2108
2109 surface->output = surface->pdf_stream.old_output;
2110 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
2111 surface->pdf_stream.old_output = NULL((void*)0);
2112 }
2113
2114 length = _cairo_output_stream_get_position (surface->output) -
2115 surface->pdf_stream.start_offset;
2116 _cairo_output_stream_printf (surface->output,
2117 "\n"
2118 "endstream\n"
2119 "endobj\n");
2120
2121 _cairo_pdf_surface_update_object (surface,
2122 surface->pdf_stream.length);
2123 _cairo_output_stream_printf (surface->output,
2124 "%d 0 obj\n"
2125 " %lld\n"
2126 "endobj\n",
2127 surface->pdf_stream.length.id,
2128 length);
2129
2130 surface->pdf_stream.active = FALSE0;
2131
2132 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
)
2133 status = _cairo_output_stream_get_status (surface->output);
2134
2135 return status;
2136}
2137
2138static void
2139_cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface,
2140 cairo_output_stream_t *mem_stream,
2141 cairo_pdf_resource_t resource,
2142 cairo_pdf_group_resources_t *resources,
2143 cairo_bool_t is_knockout_group,
2144 const cairo_box_double_t *bbox)
2145{
2146 _cairo_pdf_surface_update_object (surface, resource);
2147
2148 _cairo_output_stream_printf (surface->output,
2149 "%d 0 obj\n"
2150 "<< /Type /XObject\n"
2151 " /Length %d\n",
2152 resource.id,
2153 _cairo_memory_stream_length (mem_stream));
2154
2155 if (surface->compress_streams) {
2156 _cairo_output_stream_printf (surface->output,
2157 " /Filter /FlateDecode\n");
2158 }
2159
2160 _cairo_output_stream_printf (surface->output,
2161 " /Subtype /Form\n"
2162 " /BBox [ %f %f %f %f ]\n"
2163 " /Group <<\n"
2164 " /Type /Group\n"
2165 " /S /Transparency\n"
2166 " /I true\n"
2167 " /CS /DeviceRGB\n",
2168 bbox->p1.x, bbox->p1.y, bbox->p2.x, bbox->p2.y);
2169
2170 if (is_knockout_group)
2171 _cairo_output_stream_printf (surface->output,
2172 " /K true\n");
2173
2174 _cairo_output_stream_printf (surface->output,
2175 " >>\n"
2176 " /Resources\n");
2177 _cairo_pdf_surface_emit_group_resources (surface, resources, TRUE1);
2178 _cairo_output_stream_printf (surface->output,
2179 ">>\n"
2180 "stream\n");
2181 _cairo_memory_stream_copy (mem_stream, surface->output);
2182 _cairo_output_stream_printf (surface->output,
2183 "endstream\n"
2184 "endobj\n");
2185}
2186
2187static cairo_int_status_t
2188_cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
2189 const cairo_box_double_t *bbox,
2190 cairo_pdf_resource_t *resource)
2191{
2192 cairo_int_status_t status;
2193
2194 assert (surface->pdf_stream.active == FALSE)((void) sizeof ((surface->pdf_stream.active == 0) ? 1 : 0)
, __extension__ ({ if (surface->pdf_stream.active == 0) ; else
__assert_fail ("surface->pdf_stream.active == FALSE", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2194, __extension__ __PRETTY_FUNCTION__); }))
;
2195 assert (surface->group_stream.active == FALSE)((void) sizeof ((surface->group_stream.active == 0) ? 1 : 0
), __extension__ ({ if (surface->group_stream.active == 0)
; else __assert_fail ("surface->group_stream.active == FALSE"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2195, __extension__ __PRETTY_FUNCTION__); }))
;
2196
2197 surface->group_stream.active = TRUE1;
2198
2199 surface->group_stream.mem_stream = _cairo_memory_stream_create ();
2200
2201 if (surface->compress_streams) {
2202 surface->group_stream.stream =
2203 _cairo_deflate_stream_create (surface->group_stream.mem_stream);
2204 } else {
2205 surface->group_stream.stream = surface->group_stream.mem_stream;
2206 }
2207 status = _cairo_output_stream_get_status (surface->group_stream.stream);
2208
2209 surface->group_stream.old_output = surface->output;
2210 surface->output = surface->group_stream.stream;
2211 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
2212 _cairo_pdf_group_resources_clear (&surface->resources);
2213
2214 if (resource) {
2215 surface->group_stream.resource = *resource;
2216 } else {
2217 surface->group_stream.resource = _cairo_pdf_surface_new_object (surface);
2218 if (surface->group_stream.resource.id == 0)
2219 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2220 }
2221 surface->group_stream.is_knockout = FALSE0;
2222 surface->group_stream.bbox = *bbox;
2223
2224 /* Reset gstate */
2225 surface->reset_gs_required = TRUE1;
2226 surface->current_pattern_is_solid_color = FALSE0;
2227 surface->current_operator = CAIRO_OPERATOR_OVER;
2228 _cairo_pdf_operators_reset (&surface->pdf_operators);
2229
2230 return status;
2231}
2232
2233static cairo_int_status_t
2234_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface,
2235 const cairo_box_double_t *bbox)
2236{
2237 cairo_int_status_t status;
2238
2239 status = _cairo_pdf_surface_open_group (surface, bbox, NULL((void*)0));
2240 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2241 return status;
2242
2243 surface->group_stream.is_knockout = TRUE1;
2244
2245 return CAIRO_INT_STATUS_SUCCESS;
2246}
2247
2248static cairo_int_status_t
2249_cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
2250 cairo_pdf_resource_t *group)
2251{
2252 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS, status2;
2253
2254 assert (surface->pdf_stream.active == FALSE)((void) sizeof ((surface->pdf_stream.active == 0) ? 1 : 0)
, __extension__ ({ if (surface->pdf_stream.active == 0) ; else
__assert_fail ("surface->pdf_stream.active == FALSE", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2254, __extension__ __PRETTY_FUNCTION__); }))
;
2255 assert (surface->group_stream.active == TRUE)((void) sizeof ((surface->group_stream.active == 1) ? 1 : 0
), __extension__ ({ if (surface->group_stream.active == 1)
; else __assert_fail ("surface->group_stream.active == TRUE"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2255, __extension__ __PRETTY_FUNCTION__); }))
;
2256
2257 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
2258 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2259 return status;
2260
2261 if (surface->compress_streams) {
2262 status = _cairo_output_stream_destroy (surface->group_stream.stream);
2263 surface->group_stream.stream = NULL((void*)0);
2264
2265 _cairo_output_stream_printf (surface->group_stream.mem_stream,
2266 "\n");
2267 }
2268 surface->output = surface->group_stream.old_output;
2269 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
2270 surface->group_stream.active = FALSE0;
2271 _cairo_pdf_surface_write_memory_stream (surface,
2272 surface->group_stream.mem_stream,
2273 surface->group_stream.resource,
2274 &surface->resources,
2275 surface->group_stream.is_knockout,
2276 &surface->group_stream.bbox);
2277 if (group)
2278 *group = surface->group_stream.resource;
2279
2280 status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
2281 if (status == CAIRO_INT_STATUS_SUCCESS)
2282 status = status2;
2283
2284 surface->group_stream.mem_stream = NULL((void*)0);
2285 surface->group_stream.stream = NULL((void*)0);
2286 surface->reset_gs_required = FALSE0;
2287
2288 return status;
2289}
2290
2291static cairo_int_status_t
2292_cairo_pdf_surface_open_object_stream (cairo_pdf_surface_t *surface)
2293{
2294 if (surface->debug || surface->pdf_version < CAIRO_PDF_VERSION_1_5) {
2295 /* Object streams not supported. All objects will be written
2296 * directly to the file. */
2297 assert (surface->pdf_stream.active == FALSE)((void) sizeof ((surface->pdf_stream.active == 0) ? 1 : 0)
, __extension__ ({ if (surface->pdf_stream.active == 0) ; else
__assert_fail ("surface->pdf_stream.active == FALSE", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2297, __extension__ __PRETTY_FUNCTION__); }))
;
2298 assert (surface->group_stream.active == FALSE)((void) sizeof ((surface->group_stream.active == 0) ? 1 : 0
), __extension__ ({ if (surface->group_stream.active == 0)
; else __assert_fail ("surface->group_stream.active == FALSE"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2298, __extension__ __PRETTY_FUNCTION__); }))
;
2299 surface->object_stream.stream = surface->output;
2300 } else {
2301 surface->object_stream.resource = _cairo_pdf_surface_new_object (surface);
2302 if (surface->object_stream.resource.id == 0)
2303 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2304
2305 _cairo_array_truncate (&surface->object_stream.objects, 0);
2306 surface->object_stream.stream = _cairo_memory_stream_create ();
2307 surface->object_stream.active = TRUE1;
2308 }
2309 return _cairo_output_stream_get_status (surface->object_stream.stream);
2310}
2311
2312cairo_int_status_t
2313_cairo_pdf_surface_object_begin (cairo_pdf_surface_t *surface,
2314 cairo_pdf_resource_t resource)
2315{
2316 cairo_xref_stream_object_t xref_obj;
2317 cairo_pdf_object_t *object;
2318 cairo_int_status_t status;
2319
2320 if (surface->object_stream.active) {
2321 xref_obj.resource = resource;
2322 xref_obj.offset = _cairo_output_stream_get_position (surface->object_stream.stream);
2323 status = _cairo_array_append (&surface->object_stream.objects, &xref_obj);
2324 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2325 return status;
2326
2327 object = _cairo_array_index (&surface->objects, resource.id - 1);
2328 object->type = PDF_OBJECT_COMPRESSED;
2329 object->u.compressed_obj.xref_stream = surface->object_stream.resource;
2330 object->u.compressed_obj.index = _cairo_array_num_elements (&surface->object_stream.objects) - 1;
2331
2332 } else {
2333 _cairo_pdf_surface_update_object (surface, resource);
2334 _cairo_output_stream_printf (surface->output,
2335 "%d 0 obj\n",
2336 resource.id);
2337 }
2338 return CAIRO_INT_STATUS_SUCCESS;
2339}
2340
2341void
2342_cairo_pdf_surface_object_end (cairo_pdf_surface_t *surface)
2343{
2344 if (!surface->object_stream.active) {
2345 _cairo_output_stream_printf (surface->output,
2346 "endobj\n");
2347 }
2348}
2349
2350static int
2351_cairo_xref_stream_object_compare (const void *a,
2352 const void *b)
2353{
2354 const cairo_xref_stream_object_t *a_obj = a;
2355 const cairo_xref_stream_object_t *b_obj = b;
2356
2357 if (a_obj->offset < b_obj->offset)
2358 return -1;
2359 else if (a_obj->offset > b_obj->offset)
2360 return 1;
2361 else
2362 return 0;
2363}
2364
2365static cairo_int_status_t
2366_cairo_pdf_surface_close_object_stream (cairo_pdf_surface_t *surface)
2367{
2368 int i, num_objects;
2369 cairo_xref_stream_object_t *xref_obj;
2370 long long start_pos, length;
2371 cairo_output_stream_t *index_stream;
2372 cairo_output_stream_t *deflate_stream;
2373 cairo_pdf_resource_t length_res;
2374 cairo_int_status_t status;
2375 cairo_pdf_object_t *object;
2376
2377 if (!surface->object_stream.active) {
2378 surface->object_stream.stream = NULL((void*)0);
2379 return CAIRO_INT_STATUS_SUCCESS;
2380 }
2381
2382 num_objects = _cairo_array_num_elements (&surface->object_stream.objects);
2383 if (num_objects == 0) {
2384 object = _cairo_array_index (&surface->objects, surface->object_stream.resource.id - 1);
2385 object->type = PDF_OBJECT_FREE;
2386 return CAIRO_INT_STATUS_SUCCESS;
2387 }
2388
2389 index_stream = _cairo_memory_stream_create ();
2390 /* PDF requires the object id/offset pairs to be sorted by offset. */
2391 _cairo_array_sort (&surface->object_stream.objects, _cairo_xref_stream_object_compare);
2392 for (i = 0; i < num_objects; i++) {
2393 xref_obj = _cairo_array_index (&surface->object_stream.objects, i);
2394 _cairo_output_stream_printf (index_stream,
2395 "%d %lld\n",
2396 xref_obj->resource.id,
2397 xref_obj->offset);
2398 }
2399
2400 length_res = _cairo_pdf_surface_new_object (surface);
2401 if (length_res.id == 0)
2402 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2403
2404 _cairo_pdf_surface_update_object (surface, surface->object_stream.resource);
2405 _cairo_output_stream_printf (surface->output,
2406 "%d 0 obj\n"
2407 "<< /Type /ObjStm\n"
2408 " /Length %d 0 R\n"
2409 " /N %d\n"
2410 " /First %d\n",
2411 surface->object_stream.resource.id,
2412 length_res.id,
2413 num_objects,
2414 _cairo_memory_stream_length (index_stream));
2415
2416 if (surface->compress_streams) {
2417 _cairo_output_stream_printf (surface->output,
2418 " /Filter /FlateDecode\n");
2419 }
2420
2421 _cairo_output_stream_printf (surface->output,
2422 ">>\n"
2423 "stream\n");
2424
2425 start_pos = _cairo_output_stream_get_position (surface->output);
2426 if (surface->compress_streams) {
2427 deflate_stream = _cairo_deflate_stream_create (surface->output);
2428 _cairo_memory_stream_copy (index_stream, deflate_stream);
2429 _cairo_memory_stream_copy (surface->object_stream.stream, deflate_stream);
2430 status = _cairo_output_stream_destroy (deflate_stream);
2431 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2432 return status;
2433
2434 length = _cairo_output_stream_get_position (surface->output) - start_pos;
2435 } else {
2436 _cairo_memory_stream_copy (index_stream, surface->output);
2437 _cairo_memory_stream_copy (surface->object_stream.stream, surface->output);
2438 length = _cairo_output_stream_get_position (surface->output) - start_pos;
2439 }
2440
2441 _cairo_output_stream_printf (surface->output,
2442 "\n"
2443 "endstream\n"
2444 "endobj\n");
2445
2446 _cairo_pdf_surface_update_object (surface,
2447 length_res);
2448 _cairo_output_stream_printf (surface->output,
2449 "%d 0 obj\n"
2450 " %lld\n"
2451 "endobj\n",
2452 length_res.id,
2453 length);
2454
2455 status = _cairo_output_stream_destroy (index_stream);
2456 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2457 return status;
2458
2459 status = _cairo_output_stream_destroy (surface->object_stream.stream);
2460 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2461 return status;
2462
2463 surface->object_stream.stream = NULL((void*)0);
2464 surface->object_stream.active = FALSE0;
2465
2466 return _cairo_output_stream_get_status (surface->output);
2467}
2468
2469static cairo_int_status_t
2470_cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
2471 const cairo_box_double_t *bbox,
2472 cairo_pdf_resource_t *resource,
2473 cairo_bool_t is_form,
2474 cairo_bool_t is_group,
2475 int struct_parents)
2476{
2477 cairo_int_status_t status;
2478
2479 assert (surface->pdf_stream.active == FALSE)((void) sizeof ((surface->pdf_stream.active == 0) ? 1 : 0)
, __extension__ ({ if (surface->pdf_stream.active == 0) ; else
__assert_fail ("surface->pdf_stream.active == FALSE", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2479, __extension__ __PRETTY_FUNCTION__); }))
;
2480 assert (surface->group_stream.active == FALSE)((void) sizeof ((surface->group_stream.active == 0) ? 1 : 0
), __extension__ ({ if (surface->group_stream.active == 0)
; else __assert_fail ("surface->group_stream.active == FALSE"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2480, __extension__ __PRETTY_FUNCTION__); }))
;
2481
2482 surface->content_resources = _cairo_pdf_surface_new_object (surface);
2483 if (surface->content_resources.id == 0)
2484 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2485
2486 if (is_form) {
2487 assert (bbox != NULL)((void) sizeof ((bbox != ((void*)0)) ? 1 : 0), __extension__ (
{ if (bbox != ((void*)0)) ; else __assert_fail ("bbox != NULL"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2487, __extension__ __PRETTY_FUNCTION__); }))
;
2488
2489 cairo_output_stream_t *mem_stream = _cairo_memory_stream_create ();
2490 if (is_group) {
2491 _cairo_output_stream_printf (mem_stream,
2492 " /Type /XObject\n"
2493 " /Subtype /Form\n"
2494 " /BBox [ %f %f %f %f ]\n"
2495 " /Group <<\n"
2496 " /Type /Group\n"
2497 " /S /Transparency\n"
2498 " /I true\n"
2499 " /CS /DeviceRGB\n"
2500 " >>\n"
2501 " /Resources %d 0 R\n",
2502 bbox->p1.x,
2503 bbox->p1.y,
2504 bbox->p2.x,
2505 bbox->p2.y,
2506 surface->content_resources.id);
2507 } else {
2508 _cairo_output_stream_printf (mem_stream,
2509 " /Type /XObject\n"
2510 " /Subtype /Form\n"
2511 " /BBox [ %f %f %f %f ]\n"
2512 " /Resources %d 0 R\n",
2513 bbox->p1.x,
2514 bbox->p1.y,
2515 bbox->p2.x,
2516 bbox->p2.y,
2517 surface->content_resources.id);
2518 }
2519 if (struct_parents >= 0) {
2520 _cairo_output_stream_printf (mem_stream,
2521 " /StructParents %d\n", struct_parents);
2522 }
2523
2524 unsigned char *data;
2525 unsigned long length;
2526 status = _cairo_memory_stream_destroy (mem_stream, &data, &length);
2527 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2528 return status;
2529
2530 char *str = _cairo_strndupstrndup ((const char*)data, length); /* Add NULL terminator */
2531
2532 status =
2533 _cairo_pdf_surface_open_stream (surface,
2534 resource,
2535 surface->compress_streams,
2536 "%s",
2537 str);
2538 free (str);
2539 free (data);
2540 } else {
2541 status =
2542 _cairo_pdf_surface_open_stream (surface,
2543 resource,
2544 surface->compress_streams,
2545 NULL((void*)0));
2546 _cairo_output_stream_printf (surface->output,
2547 "1 0 0 -1 0 %f cm\n",
2548 surface->height);
2549 }
2550 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2551 return status;
2552
2553 surface->content = surface->pdf_stream.self;
2554
2555 _cairo_output_stream_printf (surface->output, "q\n");
2556 _cairo_pdf_operators_reset (&surface->pdf_operators);
2557
2558 return _cairo_output_stream_get_status (surface->output);
2559}
2560
2561static cairo_int_status_t
2562_cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface,
2563 cairo_bool_t is_form)
2564{
2565 cairo_int_status_t status;
2566
2567 assert (surface->pdf_stream.active == TRUE)((void) sizeof ((surface->pdf_stream.active == 1) ? 1 : 0)
, __extension__ ({ if (surface->pdf_stream.active == 1) ; else
__assert_fail ("surface->pdf_stream.active == TRUE", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2567, __extension__ __PRETTY_FUNCTION__); }))
;
2568 assert (surface->group_stream.active == FALSE)((void) sizeof ((surface->group_stream.active == 0) ? 1 : 0
), __extension__ ({ if (surface->group_stream.active == 0)
; else __assert_fail ("surface->group_stream.active == FALSE"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 2568, __extension__ __PRETTY_FUNCTION__); }))
;
2569
2570 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
2571 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2572 return status;
2573
2574 _cairo_output_stream_printf (surface->output, "Q\n");
2575 status = _cairo_pdf_surface_close_stream (surface);
2576 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2577 return status;
2578
2579 _cairo_pdf_surface_update_object (surface, surface->content_resources);
2580 _cairo_output_stream_printf (surface->output,
2581 "%d 0 obj\n",
2582 surface->content_resources.id);
2583 _cairo_pdf_surface_emit_group_resources (surface, &surface->resources, is_form);
2584 _cairo_output_stream_printf (surface->output,
2585 "endobj\n");
2586
2587 return _cairo_output_stream_get_status (surface->output);
2588}
2589
2590static void
2591_cairo_pdf_source_surface_entry_pluck (void *entry, void *closure)
2592{
2593 cairo_pdf_source_surface_entry_t *surface_entry = entry;
2594 cairo_hash_table_t *patterns = closure;
2595
2596 _cairo_hash_table_remove (patterns, &surface_entry->base);
2597 free (surface_entry->unique_id);
2598
2599 free (surface_entry);
2600}
2601
2602static void
2603_cairo_pdf_color_glyph_pluck (void *entry, void *closure)
2604{
2605 cairo_pdf_color_glyph_t *glyph_entry = entry;
2606 cairo_hash_table_t *patterns = closure;
2607
2608 _cairo_hash_table_remove (patterns, &glyph_entry->base);
2609 cairo_scaled_font_destroy_moz_cairo_scaled_font_destroy (glyph_entry->scaled_font);
2610
2611 free (glyph_entry);
2612}
2613
2614static cairo_int_status_t
2615_cairo_pdf_surface_write_page_dicts (cairo_pdf_surface_t *surface)
2616{
2617 cairo_int_status_t status;
2618 cairo_pdf_page_info_t *page_info;
2619 int num_annots;
2620 cairo_pdf_resource_t res;
2621
2622 for (unsigned i = 0; i < _cairo_array_num_elements (&surface->pages); i++) {
2623 page_info = _cairo_array_index (&surface->pages, i);
2624
2625 status = _cairo_pdf_surface_object_begin (surface, page_info->page_res);
2626 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2627 return status;
2628
2629 _cairo_output_stream_printf (surface->object_stream.stream,
2630 "<< /Type /Page %% %d\n"
2631 " /Parent %d 0 R\n"
2632 " /MediaBox [ 0 0 %f %f ]\n"
2633 " /Contents %d 0 R\n"
2634 " /Group <<\n"
2635 " /Type /Group\n"
2636 " /S /Transparency\n"
2637 " /I true\n"
2638 " /CS /DeviceRGB\n"
2639 " >>\n"
2640 " /Resources %d 0 R\n",
2641 i + 1,
2642 surface->pages_resource.id,
2643 page_info->width,
2644 page_info->height,
2645 page_info->content.id,
2646 page_info->resources.id);
2647
2648 if (page_info->struct_parents >= 0) {
2649 _cairo_output_stream_printf (surface->object_stream.stream,
2650 " /StructParents %d\n",
2651 page_info->struct_parents);
2652 }
2653
2654 num_annots = _cairo_array_num_elements (&page_info->annots);
2655 if (num_annots > 0) {
2656 _cairo_output_stream_printf (surface->object_stream.stream,
2657 " /Annots [ ");
2658 for (int j = 0; j < num_annots; j++) {
2659 _cairo_array_copy_element (&page_info->annots, j, &res);
2660 _cairo_output_stream_printf (surface->object_stream.stream,
2661 "%d 0 R ",
2662 res.id);
2663 }
2664 _cairo_output_stream_printf (surface->object_stream.stream, "]\n");
2665 }
2666
2667 if (page_info->thumbnail.id) {
2668 _cairo_output_stream_printf (surface->object_stream.stream,
2669 " /Thumb %d 0 R\n",
2670 page_info->thumbnail.id);
2671 }
2672
2673 _cairo_output_stream_printf (surface->object_stream.stream,
2674 ">>\n");
2675 _cairo_pdf_surface_object_end (surface);
2676 }
2677
2678 return status;
2679}
2680
2681static cairo_status_t
2682_cairo_pdf_surface_finish (void *abstract_surface)
2683{
2684 cairo_pdf_surface_t *surface = abstract_surface;
2685 long long offset;
2686 cairo_pdf_resource_t catalog;
2687 cairo_status_t status = CAIRO_STATUS_SUCCESS, status2;
2688 int size, i;
2689 cairo_pdf_jbig2_global_t *global;
2690 char *label;
2691 cairo_pdf_resource_t xref_res;
2692
2693 /* Some of the data may be in an inconistent state if there is an error status. */
2694 if (surface->base.status != CAIRO_STATUS_SUCCESS)
2695 goto CLEANUP;
2696
2697 _cairo_pdf_surface_clear (surface, FALSE0);
2698
2699 status = _cairo_pdf_surface_open_object_stream (surface);
2700 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2701 goto CLEANUP;
2702
2703 /* Emit unbounded surfaces */
2704 status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface, TRUE1);
2705 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2706 goto CLEANUP;
2707
2708 _cairo_pdf_surface_clear (surface, TRUE1);
2709
2710 status = _cairo_pdf_surface_emit_font_subsets (surface);
2711 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2712 goto CLEANUP;
2713
2714 /* Emit any new patterns or surfaces created by the Type 3 font subset. */
2715 _cairo_pdf_surface_write_patterns_and_smask_groups (surface, TRUE1);
2716
2717 _cairo_pdf_surface_clear (surface, TRUE1);
2718
2719 status = _cairo_pdf_surface_write_pages (surface);
2720 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2721 goto CLEANUP;
2722
2723 status = _cairo_pdf_interchange_write_document_objects (surface);
2724 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2725 goto CLEANUP;
2726
2727 status = _cairo_pdf_surface_write_page_dicts (surface);
2728 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2729 goto CLEANUP;
2730
2731 catalog = _cairo_pdf_surface_new_object (surface);
2732 if (catalog.id == 0) {
2733 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2734 goto CLEANUP;
2735 }
2736
2737 status = _cairo_pdf_surface_write_catalog (surface, catalog);
2738 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2739 goto CLEANUP;
2740
2741 status = _cairo_pdf_surface_close_object_stream (surface);
2742 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2743 goto CLEANUP;
2744
2745 if (!surface->debug && surface->pdf_version >= CAIRO_PDF_VERSION_1_5)
2746 {
2747 xref_res = _cairo_pdf_surface_new_object (surface);
2748 status = _cairo_pdf_surface_write_xref_stream (surface,
2749 xref_res,
2750 catalog,
2751 surface->docinfo_res,
2752 &offset);
2753 } else {
2754 offset = _cairo_pdf_surface_write_xref (surface);
2755 _cairo_output_stream_printf (surface->output,
2756 "trailer\n"
2757 "<< /Size %d\n"
2758 " /Root %d 0 R\n"
2759 " /Info %d 0 R\n"
2760 ">>\n",
2761 surface->next_available_resource.id,
2762 catalog.id,
2763 surface->docinfo_res.id);
2764 }
2765 _cairo_output_stream_printf (surface->output,
2766 "startxref\n"
2767 "%lld\n"
2768 "%%%%EOF\n",
2769 offset);
2770
2771 CLEANUP:
2772
2773 /* pdf_operators has already been flushed when the last stream was
2774 * closed so we should never be writing anything here - however,
2775 * the stream may itself be in an error state. */
2776 status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
2777 if (status == CAIRO_STATUS_SUCCESS)
2778 status = status2;
2779
2780 /* close any active streams still open due to fatal errors */
2781 status2 = _cairo_pdf_surface_close_stream (surface);
2782 if (status == CAIRO_STATUS_SUCCESS)
2783 status = status2;
2784
2785 if (surface->group_stream.stream != NULL((void*)0)) {
2786 status2 = _cairo_output_stream_destroy (surface->group_stream.stream);
2787 if (status == CAIRO_STATUS_SUCCESS)
2788 status = status2;
2789 }
2790 if (surface->group_stream.mem_stream != NULL((void*)0)) {
2791 status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
2792 if (status == CAIRO_STATUS_SUCCESS)
2793 status = status2;
2794 }
2795 if (surface->pdf_stream.active)
2796 surface->output = surface->pdf_stream.old_output;
2797 if (surface->group_stream.active)
2798 surface->output = surface->group_stream.old_output;
2799
2800 /* and finish the pdf surface */
2801 status2 = _cairo_output_stream_destroy (surface->output);
2802 if (status == CAIRO_STATUS_SUCCESS)
2803 status = status2;
2804
2805 _cairo_pdf_group_resources_fini (&surface->resources);
2806
2807 _cairo_array_fini (&surface->objects);
2808 size = _cairo_array_num_elements (&surface->pages);
2809 for (i = 0; i < size; i++) {
2810 cairo_pdf_page_info_t *page_info = _cairo_array_index (&surface->pages, i);
2811 _cairo_array_fini (&page_info->annots);
2812 }
2813 _cairo_array_fini (&surface->pages);
2814 _cairo_array_fini (&surface->rgb_linear_functions);
2815 _cairo_array_fini (&surface->alpha_linear_functions);
2816 _cairo_array_fini (&surface->page_patterns);
2817 _cairo_array_fini (&surface->page_surfaces);
2818 _cairo_array_fini (&surface->object_stream.objects);
2819
2820 _cairo_array_fini (&surface->doc_surfaces);
2821 _cairo_hash_table_foreach (surface->all_surfaces,
2822 _cairo_pdf_source_surface_entry_pluck,
2823 surface->all_surfaces);
2824 _cairo_hash_table_destroy (surface->all_surfaces);
2825 _cairo_array_fini (&surface->smask_groups);
2826 _cairo_array_fini (&surface->fonts);
2827 _cairo_array_fini (&surface->knockout_group);
2828 _cairo_array_fini (&surface->page_annots);
2829
2830 _cairo_hash_table_foreach (surface->color_glyphs,
2831 _cairo_pdf_color_glyph_pluck,
2832 surface->color_glyphs);
2833 _cairo_hash_table_destroy (surface->color_glyphs);
2834
2835 if (surface->font_subsets) {
2836 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
2837 surface->font_subsets = NULL((void*)0);
2838 }
2839
2840 size = _cairo_array_num_elements (&surface->jbig2_global);
2841 for (i = 0; i < size; i++) {
2842 global = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, i);
2843 free(global->id);
2844 if (!global->emitted)
2845 return _cairo_error (CAIRO_STATUS_JBIG2_GLOBAL_MISSING);
2846 }
2847 _cairo_array_fini (&surface->jbig2_global);
2848
2849 size = _cairo_array_num_elements (&surface->page_labels);
2850 for (i = 0; i < size; i++) {
2851 _cairo_array_copy_element (&surface->page_labels, i, &label);
2852 free (label);
2853 }
2854 _cairo_array_fini (&surface->page_labels);
2855
2856 _cairo_surface_clipper_reset (&surface->clipper);
2857
2858 _cairo_pdf_interchange_fini (surface);
2859
2860 return status;
2861}
2862
2863static cairo_int_status_t
2864_cairo_pdf_surface_start_page (void *abstract_surface)
2865{
2866 cairo_pdf_surface_t *surface = abstract_surface;
2867 cairo_pdf_page_info_t page_info;
2868 cairo_int_status_t status;
2869
2870 /* Document header */
2871 if (! surface->header_emitted) {
2872 const char *version;
2873
2874 switch (surface->pdf_version) {
2875 case CAIRO_PDF_VERSION_1_4:
2876 version = "1.4";
2877 break;
2878 case CAIRO_PDF_VERSION_1_5:
2879 version = "1.5";
2880 break;
2881 case CAIRO_PDF_VERSION_1_6:
2882 version = "1.6";
2883 break;
2884 default:
2885 case CAIRO_PDF_VERSION_1_7:
2886 version = "1.7";
2887 break;
2888 }
2889
2890 _cairo_output_stream_printf (surface->output,
2891 "%%PDF-%s\n", version);
2892 _cairo_output_stream_printf (surface->output,
2893 "%%%c%c%c%c\n", 181, 237, 174, 251);
2894 surface->header_emitted = TRUE1;
2895 }
2896
2897 _cairo_pdf_group_resources_clear (&surface->resources);
2898 surface->in_xobject = FALSE0;
2899
2900 page_info.page_res = _cairo_pdf_surface_new_object (surface);
2901 if (page_info.page_res.id == 0)
2902 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2903
2904 page_info.width = surface->width;
2905 page_info.height = surface->height;
2906 page_info.content.id = 0;
2907 page_info.resources.id = 0;
2908 page_info.thumbnail.id = 0;
2909 page_info.struct_parents = -1;
2910 _cairo_array_init (&page_info.annots, sizeof (cairo_pdf_resource_t));
2911
2912 status = _cairo_array_append (&surface->pages, &page_info);
2913 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2914 return status;
2915
2916 return CAIRO_STATUS_SUCCESS;
2917}
2918
2919static cairo_int_status_t
2920_cairo_pdf_surface_has_fallback_images (void *abstract_surface,
2921 cairo_bool_t has_fallbacks)
2922{
2923 cairo_int_status_t status;
2924 cairo_pdf_surface_t *surface = abstract_surface;
2925 cairo_box_double_t bbox;
2926
2927 status = _cairo_pdf_interchange_end_page_content (surface);
2928 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2929 return status;
2930
2931 surface->has_fallback_images = has_fallbacks;
2932 surface->in_xobject = has_fallbacks;
2933 bbox.p1.x = 0;
2934 bbox.p1.y = 0;
2935 bbox.p2.x = surface->width;
2936 bbox.p2.y = surface->height;
2937 status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL((void*)0), has_fallbacks, has_fallbacks, -1);
2938 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2939 return status;
2940
2941 return CAIRO_STATUS_SUCCESS;
2942}
2943
2944static cairo_bool_t
2945_cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
2946{
2947 return TRUE1;
2948}
2949
2950static cairo_bool_t
2951_cairo_pdf_surface_requires_thumbnail_image (void *abstract_surface,
2952 int *width,
2953 int *height)
2954{
2955 cairo_pdf_surface_t *surface = abstract_surface;
2956
2957 if (surface->thumbnail_width > 0 && surface->thumbnail_height > 0) {
2958 *width = surface->thumbnail_width;
2959 *height = surface->thumbnail_height;
2960 return TRUE1;
2961 }
2962
2963 return FALSE0;
2964}
2965
2966static cairo_int_status_t
2967_cairo_pdf_surface_set_thumbnail_image (void *abstract_surface,
2968 cairo_image_surface_t *image)
2969{
2970 cairo_pdf_surface_t *surface = abstract_surface;
2971
2972 surface->thumbnail_image = (cairo_image_surface_t *)cairo_surface_reference_moz_cairo_surface_reference(&image->base);
2973
2974 return CAIRO_STATUS_SUCCESS;
2975}
2976
2977static cairo_int_status_t
2978_cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surface,
2979 const cairo_pattern_t *source,
2980 const cairo_rectangle_int_t *extents,
2981 cairo_pdf_source_surface_entry_t **pdf_source,
2982 double *x_offset,
2983 double *y_offset,
2984 cairo_rectangle_int_t *source_extents)
2985{
2986 cairo_image_surface_t *image;
2987 cairo_surface_t *pad_image;
2988 void *image_extra;
2989 cairo_int_status_t status;
2990 int w, h;
2991 cairo_box_t box;
2992 cairo_rectangle_int_t rect;
2993 cairo_surface_pattern_t pad_pattern;
2994
2995 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source,
2996 &image, &image_extra);
2997 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2998 return status;
2999
3000 pad_image = &image->base;
3001
3002 /* get the operation extents in pattern space */
3003 _cairo_box_from_rectangle (&box, extents);
3004 _cairo_matrix_transform_bounding_box_fixed (&source->matrix, &box, NULL((void*)0));
3005 _cairo_box_round_to_rectangle (&box, &rect);
3006
3007 /* Check if image needs padding to fill extents */
3008 w = image->width;
3009 h = image->height;
3010 if (_cairo_fixed_integer_ceil(box.p1.x) < 0 ||
3011 _cairo_fixed_integer_ceil(box.p1.y) < 0 ||
3012 _cairo_fixed_integer_floor(box.p2.x) > w ||
3013 _cairo_fixed_integer_floor(box.p2.y) > h)
3014 {
3015 pad_image = _cairo_image_surface_create_with_content (image->base.content,
3016 rect.width,
3017 rect.height);
3018 if (pad_image->status) {
3019 status = pad_image->status;
3020 goto BAIL;
3021 }
3022
3023 _cairo_pattern_init_for_surface (&pad_pattern, &image->base);
3024 cairo_matrix_init_translate_moz_cairo_matrix_init_translate (&pad_pattern.base.matrix, rect.x, rect.y);
3025 pad_pattern.base.extend = CAIRO_EXTEND_PAD;
3026 status = _cairo_surface_paint (pad_image,
3027 CAIRO_OPERATOR_SOURCE, &pad_pattern.base,
3028 NULL((void*)0));
3029 _cairo_pattern_fini (&pad_pattern.base);
3030 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3031 goto BAIL;
3032 }
3033
3034 status = _cairo_pdf_surface_add_source_surface (surface,
3035 pad_image,
3036 NULL((void*)0),
3037 -1 , /* node_surface_index */
3038 CAIRO_OPERATOR_OVER, /* not used for images */
3039 source->filter,
3040 FALSE0, /* stencil mask */
3041 FALSE0, /* smask */
3042 FALSE0, /* need_transp_group */
3043 extents,
3044 NULL((void*)0), /* smask_res */
3045 pdf_source,
3046 x_offset,
3047 y_offset,
3048 source_extents);
3049 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3050 goto BAIL;
3051
3052 if (pad_image != &image->base) {
3053 /* If using a padded image, replace _add_source_surface
3054 * x/y_offset with padded image offset. Note:
3055 * _add_source_surface only sets a non zero x/y_offset for
3056 * RASTER_SOURCE patterns. _add_source_surface will always set
3057 * x/y_offset to 0 for surfaces so we can ignore the returned
3058 * offset and replace it with the offset required for the
3059 * padded image */
3060 *x_offset = rect.x;
3061 *y_offset = rect.y;
3062 }
3063
3064BAIL:
3065 if (pad_image != &image->base)
3066 cairo_surface_destroy_moz_cairo_surface_destroy (pad_image);
3067
3068 _cairo_pdf_surface_release_source_image_from_pattern (surface, source, image, image_extra);
3069
3070 return status;
3071}
3072
3073/* Emit alpha channel from the image into stream_res.
3074 */
3075static cairo_int_status_t
3076_cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
3077 cairo_image_surface_t *image,
3078 cairo_bool_t stencil_mask,
3079 cairo_bool_t interpolate,
3080 cairo_pdf_resource_t *stream_res)
3081{
3082 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
3083 char *alpha;
3084 unsigned long alpha_size;
3085 uint32_t *pixel32;
3086 uint8_t *pixel8;
3087 int i, x, y, bit, a;
3088 cairo_image_transparency_t transparency;
3089
3090 /* This is the only image format we support, which simplifies things. */
3091 assert (image->format == CAIRO_FORMAT_ARGB32 ||((void) sizeof ((image->format == CAIRO_FORMAT_ARGB32 || image
->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8
|| image->format == CAIRO_FORMAT_A1) ? 1 : 0), __extension__
({ if (image->format == CAIRO_FORMAT_ARGB32 || image->
format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8
|| image->format == CAIRO_FORMAT_A1) ; else __assert_fail
("image->format == CAIRO_FORMAT_ARGB32 || image->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8 || image->format == CAIRO_FORMAT_A1"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 3094, __extension__ __PRETTY_FUNCTION__); }))
3092 image->format == CAIRO_FORMAT_RGB24 ||((void) sizeof ((image->format == CAIRO_FORMAT_ARGB32 || image
->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8
|| image->format == CAIRO_FORMAT_A1) ? 1 : 0), __extension__
({ if (image->format == CAIRO_FORMAT_ARGB32 || image->
format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8
|| image->format == CAIRO_FORMAT_A1) ; else __assert_fail
("image->format == CAIRO_FORMAT_ARGB32 || image->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8 || image->format == CAIRO_FORMAT_A1"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 3094, __extension__ __PRETTY_FUNCTION__); }))
3093 image->format == CAIRO_FORMAT_A8 ||((void) sizeof ((image->format == CAIRO_FORMAT_ARGB32 || image
->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8
|| image->format == CAIRO_FORMAT_A1) ? 1 : 0), __extension__
({ if (image->format == CAIRO_FORMAT_ARGB32 || image->
format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8
|| image->format == CAIRO_FORMAT_A1) ; else __assert_fail
("image->format == CAIRO_FORMAT_ARGB32 || image->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8 || image->format == CAIRO_FORMAT_A1"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 3094, __extension__ __PRETTY_FUNCTION__); }))
3094 image->format == CAIRO_FORMAT_A1 )((void) sizeof ((image->format == CAIRO_FORMAT_ARGB32 || image
->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8
|| image->format == CAIRO_FORMAT_A1) ? 1 : 0), __extension__
({ if (image->format == CAIRO_FORMAT_ARGB32 || image->
format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8
|| image->format == CAIRO_FORMAT_A1) ; else __assert_fail
("image->format == CAIRO_FORMAT_ARGB32 || image->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_A8 || image->format == CAIRO_FORMAT_A1"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 3094, __extension__ __PRETTY_FUNCTION__); }))
;
3095
3096 transparency = _cairo_image_analyze_transparency (image);
3097 if (stencil_mask) {
3098 assert (transparency == CAIRO_IMAGE_IS_OPAQUE ||((void) sizeof ((transparency == CAIRO_IMAGE_IS_OPAQUE || transparency
== CAIRO_IMAGE_HAS_BILEVEL_ALPHA) ? 1 : 0), __extension__ ({
if (transparency == CAIRO_IMAGE_IS_OPAQUE || transparency ==
CAIRO_IMAGE_HAS_BILEVEL_ALPHA) ; else __assert_fail ("transparency == CAIRO_IMAGE_IS_OPAQUE || transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 3099, __extension__ __PRETTY_FUNCTION__); }))
3099 transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA)((void) sizeof ((transparency == CAIRO_IMAGE_IS_OPAQUE || transparency
== CAIRO_IMAGE_HAS_BILEVEL_ALPHA) ? 1 : 0), __extension__ ({
if (transparency == CAIRO_IMAGE_IS_OPAQUE || transparency ==
CAIRO_IMAGE_HAS_BILEVEL_ALPHA) ; else __assert_fail ("transparency == CAIRO_IMAGE_IS_OPAQUE || transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 3099, __extension__ __PRETTY_FUNCTION__); }))
;
3100 } else {
3101 assert (transparency != CAIRO_IMAGE_IS_OPAQUE)((void) sizeof ((transparency != CAIRO_IMAGE_IS_OPAQUE) ? 1 :
0), __extension__ ({ if (transparency != CAIRO_IMAGE_IS_OPAQUE
) ; else __assert_fail ("transparency != CAIRO_IMAGE_IS_OPAQUE"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 3101, __extension__ __PRETTY_FUNCTION__); }))
;
3102 }
3103
3104 if (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA || transparency == CAIRO_IMAGE_IS_OPAQUE) {
3105 alpha_size = (image->width + 7) / 8 * image->height;
3106 alpha = _cairo_malloc_ab ((image->width+7) / 8, image->height);
3107 } else {
3108 alpha_size = image->height * image->width;
3109 alpha = _cairo_malloc_ab (image->height, image->width);
3110 }
3111
3112 if (unlikely (alpha == NULL)(__builtin_expect (!!(alpha == ((void*)0)), 0))) {
3113 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3114 goto CLEANUP;
3115 }
3116
3117 i = 0;
3118 for (y = 0; y < image->height; y++) {
3119 if (transparency == CAIRO_IMAGE_IS_OPAQUE) {
3120 for (x = 0; x < (image->width + 7) / 8; x++)
3121 alpha[i++] = 0xff;
3122 } else if (image->format == CAIRO_FORMAT_A1) {
3123 pixel8 = (uint8_t *) (image->data + y * image->stride);
3124
3125 for (x = 0; x < (image->width + 7) / 8; x++, pixel8++) {
3126 a = *pixel8;
3127 a = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a)((((a) * 0x0802LU & 0x22110LU) | ((a) * 0x8020LU & 0x88440LU
)) * 0x10101LU >> 16)
;
3128 alpha[i++] = a;
3129 }
3130 } else {
3131 pixel8 = (uint8_t *) (image->data + y * image->stride);
3132 pixel32 = (uint32_t *) (image->data + y * image->stride);
3133 bit = 7;
3134 for (x = 0; x < image->width; x++) {
3135 if (image->format == CAIRO_FORMAT_ARGB32) {
3136 a = (*pixel32 & 0xff000000) >> 24;
3137 pixel32++;
3138 } else {
3139 a = *pixel8;
3140 pixel8++;
3141 }
3142
3143 if (transparency == CAIRO_IMAGE_HAS_ALPHA) {
3144 alpha[i++] = a;
3145 } else { /* transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA or CAIRO_IMAGE_IS_OPAQUE */
3146 if (bit == 7)
3147 alpha[i] = 0;
3148 if (a != 0)
3149 alpha[i] |= (1 << bit);
3150 bit--;
3151 if (bit < 0) {
3152 bit = 7;
3153 i++;
3154 }
3155 }
3156 }
3157 if (bit != 7)
3158 i++;
3159 }
3160 }
3161
3162 if (stencil_mask) {
3163 status = _cairo_pdf_surface_open_stream (surface,
3164 stream_res,
3165 TRUE1,
3166 " /Type /XObject\n"
3167 " /Subtype /Image\n"
3168 " /ImageMask true\n"
3169 " /Width %d\n"
3170 " /Height %d\n"
3171 " /Interpolate %s\n"
3172 " /BitsPerComponent 1\n"
3173 " /Decode [1 0]\n",
3174 image->width, image->height,
3175 interpolate ? "true" : "false");
3176 } else {
3177 status = _cairo_pdf_surface_open_stream (surface,
3178 stream_res,
3179 TRUE1,
3180 " /Type /XObject\n"
3181 " /Subtype /Image\n"
3182 " /Width %d\n"
3183 " /Height %d\n"
3184 " /ColorSpace /DeviceGray\n"
3185 " /Interpolate %s\n"
3186 " /BitsPerComponent %d\n",
3187 image->width, image->height,
3188 interpolate ? "true" : "false",
3189 transparency == CAIRO_IMAGE_HAS_ALPHA ? 8 : 1);
3190 }
3191 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3192 goto CLEANUP_ALPHA;
3193
3194 _cairo_output_stream_write (surface->output, alpha, alpha_size);
3195 status = _cairo_pdf_surface_close_stream (surface);
3196
3197 CLEANUP_ALPHA:
3198 free (alpha);
3199 CLEANUP:
3200 return status;
3201}
3202
3203/**
3204 * _cairo_pdf_surface_emit_image:
3205 * @surface: the pdf surface
3206 * @image_surf: The image to write
3207 * @surface_entry: Contains image resource, smask resource, interpolate and stencil mask parameters.
3208 *
3209 * Emit an image stream using the @image_res resource and write out
3210 * the image data from @image_surf. If @smask_res is not null, @smask_res will
3211 * be specified as the smask for the image. Otherwise emit the an smask if
3212 * the image is requires one.
3213 **/
3214static cairo_int_status_t
3215_cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
3216 cairo_image_surface_t *image_surf,
3217 cairo_pdf_source_surface_entry_t *surface_entry)
3218{
3219 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
3220 char *data;
3221 unsigned long data_size;
3222 uint32_t *pixel;
3223 int i, x, y, bit;
3224 cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
3225 cairo_bool_t need_smask;
3226 cairo_image_color_t color;
3227 cairo_image_surface_t *image;
3228 cairo_image_transparency_t transparency;
3229 char smask_buf[30];
3230
3231 image = image_surf;
3232 if (image->format != CAIRO_FORMAT_RGB24 &&
3233 image->format != CAIRO_FORMAT_ARGB32 &&
3234 image->format != CAIRO_FORMAT_A8 &&
3235 image->format != CAIRO_FORMAT_A1)
3236 {
3237 cairo_surface_t *surf;
3238 cairo_surface_pattern_t pattern;
3239
3240 surf = _cairo_image_surface_create_with_content (image_surf->base.content,
3241 image_surf->width,
3242 image_surf->height);
3243 image = (cairo_image_surface_t *) surf;
3244 if (surf->status) {
3245 status = surf->status;
3246 goto CLEANUP;
3247 }
3248
3249 _cairo_pattern_init_for_surface (&pattern, &image_surf->base);
3250 status = _cairo_surface_paint (surf,
3251 CAIRO_OPERATOR_SOURCE, &pattern.base,
3252 NULL((void*)0));
3253 _cairo_pattern_fini (&pattern.base);
3254 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3255 goto CLEANUP;
3256 }
3257
3258 if (surface_entry->smask || surface_entry->stencil_mask) {
3259 return _cairo_pdf_surface_emit_smask (surface, image,
3260 surface_entry->stencil_mask,
3261 surface_entry->interpolate,
3262 &surface_entry->surface_res);
3263 }
3264
3265 color = _cairo_image_analyze_color (image);
3266 switch (color) {
3267 default:
3268 case CAIRO_IMAGE_UNKNOWN_COLOR:
3269 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 3269, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
3270 case CAIRO_IMAGE_IS_COLOR:
3271 data_size = image->height * image->width * 3;
3272 data = _cairo_malloc_abc (image->width, image->height, 3);
3273 break;
3274
3275 case CAIRO_IMAGE_IS_GRAYSCALE:
3276 data_size = image->height * image->width;
3277 data = _cairo_malloc_ab (image->width, image->height);
3278 break;
3279 case CAIRO_IMAGE_IS_MONOCHROME:
3280 data_size = (image->width + 7) / 8 * image->height;
3281 data = _cairo_malloc_ab ((image->width+7) / 8, image->height);
3282 break;
3283 }
3284 if (unlikely (data == NULL)(__builtin_expect (!!(data == ((void*)0)), 0))) {
3285 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3286 goto CLEANUP;
3287 }
3288
3289 i = 0;
3290 for (y = 0; y < image->height; y++) {
3291 pixel = (uint32_t *) (image->data + y * image->stride);
3292
3293 bit = 7;
3294 for (x = 0; x < image->width; x++, pixel++) {
3295 int r, g, b;
3296
3297 /* XXX: We're un-premultiplying alpha here. My reading of the PDF
3298 * specification suggests that we should be able to avoid having
3299 * to do this by filling in the SMask's Matte dictionary
3300 * appropriately, but my attempts to do that so far have
3301 * failed. */
3302 if (image->format == CAIRO_FORMAT_ARGB32) {
3303 uint8_t a;
3304 a = (*pixel & 0xff000000) >> 24;
3305 if (a == 0) {
3306 r = g = b = 0;
3307 } else {
3308 r = (((*pixel & 0xff0000) >> 16) * 255 + a / 2) / a;
3309 g = (((*pixel & 0x00ff00) >> 8) * 255 + a / 2) / a;
3310 b = (((*pixel & 0x0000ff) >> 0) * 255 + a / 2) / a;
3311 }
3312 } else if (image->format == CAIRO_FORMAT_RGB24) {
3313 r = (*pixel & 0x00ff0000) >> 16;
3314 g = (*pixel & 0x0000ff00) >> 8;
3315 b = (*pixel & 0x000000ff) >> 0;
3316 } else {
3317 r = g = b = 0;
3318 }
3319
3320 switch (color) {
3321 case CAIRO_IMAGE_IS_COLOR:
3322 case CAIRO_IMAGE_UNKNOWN_COLOR:
3323 data[i++] = r;
3324 data[i++] = g;
3325 data[i++] = b;
3326 break;
3327
3328 case CAIRO_IMAGE_IS_GRAYSCALE:
3329 data[i++] = r;
3330 break;
3331
3332 case CAIRO_IMAGE_IS_MONOCHROME:
3333 if (bit == 7)
3334 data[i] = 0;
3335 if (r != 0)
3336 data[i] |= (1 << bit);
3337 bit--;
3338 if (bit < 0) {
3339 bit = 7;
3340 i++;
3341 }
3342 break;
3343 }
3344 }
3345 if (bit != 7)
3346 i++;
3347 }
3348
3349 if (surface_entry->smask_res.id != 0) {
3350 need_smask = TRUE1;
3351 smask = surface_entry->smask_res;
3352 } else {
3353 need_smask = FALSE0;
3354 if (image->format == CAIRO_FORMAT_ARGB32 ||
3355 image->format == CAIRO_FORMAT_A8 ||
3356 image->format == CAIRO_FORMAT_A1)
3357 {
3358 transparency = _cairo_image_analyze_transparency (image);
3359 if (transparency != CAIRO_IMAGE_IS_OPAQUE) {
3360 need_smask = TRUE1;
3361 smask = _cairo_pdf_surface_new_object (surface);
3362 if (smask.id == 0) {
3363 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3364 goto CLEANUP_RGB;
3365 }
3366
3367 status = _cairo_pdf_surface_emit_smask (surface, image, FALSE0, surface_entry->interpolate, &smask);
3368 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3369 goto CLEANUP_RGB;
3370 }
3371 }
3372 }
3373
3374 if (need_smask)
3375 snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", smask.id);
3376 else
3377 smask_buf[0] = 0;
3378
3379 status = _cairo_pdf_surface_open_stream (surface,
3380 &surface_entry->surface_res,
3381 TRUE1,
3382 " /Type /XObject\n"
3383 " /Subtype /Image\n"
3384 " /Width %d\n"
3385 " /Height %d\n"
3386 " /ColorSpace %s\n"
3387 " /Interpolate %s\n"
3388 " /BitsPerComponent %d\n"
3389 "%s",
3390 image->width,
3391 image->height,
3392 color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray",
3393 surface_entry->interpolate ? "true" : "false",
3394 color == CAIRO_IMAGE_IS_MONOCHROME? 1 : 8,
3395 smask_buf);
3396 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3397 goto CLEANUP_RGB;
3398
3399#undef IMAGE_DICTIONARY
3400
3401 _cairo_output_stream_write (surface->output, data, data_size);
3402 status = _cairo_pdf_surface_close_stream (surface);
3403
3404CLEANUP_RGB:
3405 free (data);
3406CLEANUP:
3407 if (image != image_surf)
3408 cairo_surface_destroy_moz_cairo_surface_destroy (&image->base);
3409
3410 return status;
3411}
3412
3413static cairo_int_status_t
3414_cairo_pdf_surface_lookup_jbig2_global (cairo_pdf_surface_t *surface,
3415 const unsigned char *global_id,
3416 unsigned long global_id_length,
3417 cairo_pdf_jbig2_global_t **entry)
3418{
3419 cairo_pdf_jbig2_global_t global;
3420 int size, i;
3421 cairo_int_status_t status;
3422
3423 size = _cairo_array_num_elements (&surface->jbig2_global);
3424 for (i = 0; i < size; i++) {
3425 *entry = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, i);
3426 if ((*entry)->id && global_id && (*entry)->id_length == global_id_length
3427 && memcmp((*entry)->id, global_id, global_id_length) == 0) {
3428 return CAIRO_STATUS_SUCCESS;
3429 }
3430 }
3431
3432 global.id = _cairo_malloc (global_id_length)((global_id_length) != 0 ? malloc(global_id_length) : ((void*
)0))
;
3433 if (unlikely (global.id == NULL)(__builtin_expect (!!(global.id == ((void*)0)), 0))) {
3434 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3435 }
3436
3437 memcpy (global.id, global_id, global_id_length);
3438 global.id_length = global_id_length;
3439 global.res = _cairo_pdf_surface_new_object (surface);
3440 if (global.res.id == 0) {
3441 free(global.id);
3442 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3443 }
3444
3445 global.emitted = FALSE0;
3446 status = _cairo_array_append (&surface->jbig2_global, &global);
3447 if (unlikely(status)(__builtin_expect (!!(status), 0)))
3448 return status;
3449
3450 size = _cairo_array_num_elements (&surface->jbig2_global);
3451 *entry = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, size - 1);
3452 return CAIRO_STATUS_SUCCESS;
3453}
3454
3455static cairo_int_status_t
3456_cairo_pdf_surface_emit_jbig2_image (cairo_pdf_surface_t *surface,
3457 cairo_surface_t *source,
3458 cairo_pdf_source_surface_entry_t *surface_entry,
3459 cairo_bool_t test)
3460{
3461 cairo_int_status_t status;
3462 const unsigned char *mime_data;
3463 unsigned long mime_data_length;
3464 cairo_image_info_t info;
3465 const unsigned char *global_id;
3466 unsigned long global_id_length;
3467 const unsigned char *global_data;
3468 unsigned long global_data_length;
3469 cairo_pdf_jbig2_global_t *global_entry = NULL((void*)0); /* hide compiler warning */
3470 char smask_buf[30];
3471 char decode_parms_buf[100];
3472
3473 cairo_surface_get_mime_data_moz_cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2"application/x-cairo.jbig2",
3474 &mime_data, &mime_data_length);
3475 if (mime_data == NULL((void*)0))
3476 return CAIRO_INT_STATUS_UNSUPPORTED;
3477
3478 status = _cairo_image_info_get_jbig2_info (&info, mime_data, mime_data_length);
3479 if (status)
3480 return status;
3481
3482 /* At this point we know emitting jbig2 will succeed. */
3483 if (test)
3484 return CAIRO_STATUS_SUCCESS;
3485
3486 cairo_surface_get_mime_data_moz_cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID"application/x-cairo.jbig2-global-id",
3487 &global_id, &global_id_length);
3488 if (global_id && global_id_length > 0) {
3489 status = _cairo_pdf_surface_lookup_jbig2_global (surface, global_id, global_id_length, &global_entry);
3490 if (unlikely(status)(__builtin_expect (!!(status), 0)))
3491 return status;
3492
3493 if (!global_entry->emitted) {
3494 cairo_surface_get_mime_data_moz_cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL"application/x-cairo.jbig2-global",
3495 &global_data, &global_data_length);
3496 if (global_data) {
3497 status = _cairo_pdf_surface_open_stream (surface, &global_entry->res, FALSE0, NULL((void*)0));
3498 if (unlikely(status)(__builtin_expect (!!(status), 0)))
3499 return status;
3500
3501 _cairo_output_stream_write (surface->output, global_data, global_data_length);
3502 status = _cairo_pdf_surface_close_stream (surface);
3503 if (unlikely(status)(__builtin_expect (!!(status), 0)))
3504 return status;
3505
3506 global_entry->emitted = TRUE1;
3507 }
3508 }
3509
3510 snprintf(decode_parms_buf, sizeof(decode_parms_buf),
3511 " /DecodeParms << /JBIG2Globals %d 0 R >>\n", global_entry->res.id);
3512 } else {
3513 decode_parms_buf[0] = 0;
3514 }
3515
3516 if (surface_entry->smask_res.id)
3517 snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", surface_entry->smask_res.id);
3518 else
3519 smask_buf[0] = 0;
3520
3521 if (surface_entry->stencil_mask) {
3522 status = _cairo_pdf_surface_open_stream (surface,
3523 &surface_entry->surface_res,
3524 FALSE0,
3525 " /Type /XObject\n"
3526 " /Subtype /Image\n"
3527 " /ImageMask true\n"
3528 " /Width %d\n"
3529 " /Height %d\n"
3530 " /Interpolate %s\n"
3531 " /BitsPerComponent 1\n"
3532 " /Decode [1 0]\n"
3533 " /Filter /JPXDecode\n"
3534 "%s",
3535 info.width,
3536 info.height,
3537 surface_entry->interpolate ? "true" : "false",
3538 decode_parms_buf);
3539 } else {
3540 status = _cairo_pdf_surface_open_stream (surface,
3541 &surface_entry->surface_res,
3542 FALSE0,
3543 " /Type /XObject\n"
3544 " /Subtype /Image\n"
3545 " /Width %d\n"
3546 " /Height %d\n"
3547 " /ColorSpace /DeviceGray\n"
3548 " /BitsPerComponent 1\n"
3549 " /Interpolate %s\n"
3550 "%s"
3551 " /Filter /JBIG2Decode\n"
3552 "%s",
3553 info.width,
3554 info.height,
3555 surface_entry->interpolate ? "true" : "false",
3556 smask_buf,
3557 decode_parms_buf);
3558 }
3559 if (unlikely(status)(__builtin_expect (!!(status), 0)))
3560 return status;
3561
3562 _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
3563 status = _cairo_pdf_surface_close_stream (surface);
3564
3565 return status;
3566}
3567
3568static cairo_int_status_t
3569_cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface,
3570 cairo_surface_t *source,
3571 cairo_pdf_source_surface_entry_t *surface_entry,
3572 cairo_bool_t test)
3573{
3574 cairo_int_status_t status;
3575 const unsigned char *mime_data;
3576 unsigned long mime_data_length;
3577 cairo_image_info_t info;
3578 char smask_buf[30];
3579
3580 if (surface->pdf_version < CAIRO_PDF_VERSION_1_5)
3581 return CAIRO_INT_STATUS_UNSUPPORTED;
3582
3583 cairo_surface_get_mime_data_moz_cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2"image/jp2",
3584 &mime_data, &mime_data_length);
3585 if (mime_data == NULL((void*)0))
3586 return CAIRO_INT_STATUS_UNSUPPORTED;
3587
3588 status = _cairo_image_info_get_jpx_info (&info, mime_data, mime_data_length);
3589 if (status)
3590 return status;
3591
3592 if ((surface_entry->smask || surface_entry->stencil_mask) && info.num_components != 1)
3593 return CAIRO_INT_STATUS_UNSUPPORTED;
3594
3595 if ((surface_entry->stencil_mask) && info.bits_per_component != 1)
3596 return CAIRO_INT_STATUS_UNSUPPORTED;
3597
3598 if (surface_entry->smask_res.id)
3599 snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", surface_entry->smask_res.id);
3600 else
3601 smask_buf[0] = 0;
3602
3603 /* At this point we know emitting jpx will succeed. */
3604 if (test)
3605 return CAIRO_STATUS_SUCCESS;
3606
3607 if (surface_entry->stencil_mask) {
3608 status = _cairo_pdf_surface_open_stream (surface,
3609 &surface_entry->surface_res,
3610 FALSE0,
3611 " /Type /XObject\n"
3612 " /Subtype /Image\n"
3613 " /ImageMask true\n"
3614 " /Width %d\n"
3615 " /Height %d\n"
3616 " /Interpolate %s\n"
3617 " /BitsPerComponent 1\n"
3618 " /Decode [1 0]\n"
3619 " /Filter /JPXDecode\n",
3620 info.width,
3621 info.height,
3622 surface_entry->interpolate ? "true" : "false");
3623 } else {
3624 status = _cairo_pdf_surface_open_stream (surface,
3625 &surface_entry->surface_res,
3626 FALSE0,
3627 " /Type /XObject\n"
3628 " /Subtype /Image\n"
3629 " /Width %d\n"
3630 " /Height %d\n"
3631 " /Interpolate %s\n"
3632 "%s"
3633 " /Filter /JPXDecode\n",
3634 info.width,
3635 info.height,
3636 surface_entry->interpolate ? "true" : "false",
3637 smask_buf);
3638 }
3639 if (status)
3640 return status;
3641
3642 _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
3643 status = _cairo_pdf_surface_close_stream (surface);
3644
3645 return status;
3646}
3647
3648static cairo_int_status_t
3649_cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
3650 cairo_surface_t *source,
3651 cairo_pdf_source_surface_entry_t *surface_entry,
3652 cairo_bool_t test)
3653{
3654 cairo_int_status_t status;
3655 const unsigned char *mime_data;
3656 unsigned long mime_data_length;
3657 cairo_image_info_t info;
3658 const char *colorspace;
3659 char smask_buf[30];
3660
3661 cairo_surface_get_mime_data_moz_cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG"image/jpeg",
3662 &mime_data, &mime_data_length);
3663 if (unlikely (source->status)(__builtin_expect (!!(source->status), 0)))
3664 return source->status;
3665 if (mime_data == NULL((void*)0))
3666 return CAIRO_INT_STATUS_UNSUPPORTED;
3667
3668 status = _cairo_image_info_get_jpeg_info (&info, mime_data, mime_data_length);
3669 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3670 return status;
3671
3672 if ((surface_entry->smask || surface_entry->stencil_mask) && info.num_components != 1)
3673 return CAIRO_INT_STATUS_UNSUPPORTED;
3674
3675 if ((surface_entry->stencil_mask) && info.bits_per_component != 1)
3676 return CAIRO_INT_STATUS_UNSUPPORTED;
3677
3678 switch (info.num_components) {
3679 case 1:
3680 colorspace = "/DeviceGray";
3681 break;
3682 case 3:
3683 colorspace = "/DeviceRGB";
3684 break;
3685 case 4:
3686 colorspace = "/DeviceCMYK";
3687 break;
3688 default:
3689 return CAIRO_INT_STATUS_UNSUPPORTED;
3690 }
3691
3692 /* At this point we know emitting jpeg will succeed. */
3693 if (test)
3694 return CAIRO_STATUS_SUCCESS;
3695
3696 if (surface_entry->smask_res.id)
3697 snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", surface_entry->smask_res.id);
3698 else
3699 smask_buf[0] = 0;
3700
3701 if (surface_entry->stencil_mask) {
3702 status = _cairo_pdf_surface_open_stream (surface,
3703 &surface_entry->surface_res,
3704 FALSE0,
3705 " /Type /XObject\n"
3706 " /Subtype /Image\n"
3707 " /ImageMask true\n"
3708 " /Width %d\n"
3709 " /Height %d\n"
3710 " /Interpolate %s\n"
3711 " /BitsPerComponent 1\n"
3712 " /Decode [1 0]\n"
3713 " /Filter /DCTDecode\n",
3714 info.width,
3715 info.height,
3716 surface_entry->interpolate ? "true" : "false");
3717 } else {
3718 status = _cairo_pdf_surface_open_stream (surface,
3719 &surface_entry->surface_res,
3720 FALSE0,
3721 " /Type /XObject\n"
3722 " /Subtype /Image\n"
3723 " /Width %d\n"
3724 " /Height %d\n"
3725 " /ColorSpace %s\n"
3726 " /Interpolate %s\n"
3727 " /BitsPerComponent %d\n"
3728 "%s"
3729 " /Filter /DCTDecode\n",
3730 info.width,
3731 info.height,
3732 colorspace,
3733 surface_entry->interpolate ? "true" : "false",
3734 info.bits_per_component,
3735 smask_buf);
3736 }
3737 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3738 return status;
3739
3740 _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
3741 status = _cairo_pdf_surface_close_stream (surface);
3742
3743 return status;
3744}
3745
3746static cairo_int_status_t
3747_cairo_pdf_surface_emit_ccitt_image (cairo_pdf_surface_t *surface,
3748 cairo_surface_t *source,
3749 cairo_pdf_source_surface_entry_t *surface_entry,
3750 cairo_bool_t test)
3751{
3752 cairo_status_t status;
3753 const unsigned char *ccitt_data;
3754 unsigned long ccitt_data_len;
3755 const unsigned char *ccitt_params_string;
3756 unsigned long ccitt_params_string_len;
3757 char *params, *p, *end;
3758 cairo_ccitt_params_t ccitt_params;
3759 char buf[300];
3760
3761 cairo_surface_get_mime_data_moz_cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_CCITT_FAX"image/g3fax",
3762 &ccitt_data, &ccitt_data_len);
3763 if (unlikely (source->status)(__builtin_expect (!!(source->status), 0)))
3764 return source->status;
3765 if (ccitt_data == NULL((void*)0))
3766 return CAIRO_INT_STATUS_UNSUPPORTED;
3767
3768 cairo_surface_get_mime_data_moz_cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_CCITT_FAX_PARAMS"application/x-cairo.ccitt.params",
3769 &ccitt_params_string, &ccitt_params_string_len);
3770 if (unlikely (source->status)(__builtin_expect (!!(source->status), 0)))
3771 return source->status;
3772 if (ccitt_params_string == NULL((void*)0))
3773 return CAIRO_INT_STATUS_UNSUPPORTED;
3774
3775 /* ensure params_string is null terminated */
3776 params = _cairo_strndupstrndup ((const char *)ccitt_params_string, ccitt_params_string_len);
3777 if (unlikely (params == NULL)(__builtin_expect (!!(params == ((void*)0)), 0)))
3778 return _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
3779
3780 status = _cairo_tag_parse_ccitt_params (params, &ccitt_params);
3781 if (unlikely(status)(__builtin_expect (!!(status), 0)))
3782 return source->status;
3783
3784 free (params);
3785
3786 /* At this point we know emitting jbig2 will succeed. */
3787 if (test)
3788 return CAIRO_STATUS_SUCCESS;
3789
3790 p = buf;
3791 *p = 0;
3792 end = buf + sizeof(buf) - 1;
3793 p += snprintf (p, end - p, "/Columns %d /Rows %d /K %d",
3794 ccitt_params.columns,
3795 ccitt_params.rows,
3796 ccitt_params.k);
3797 if (ccitt_params.end_of_line)
3798 p += snprintf (p, end - p, " /EndOfLine true");
3799
3800 if (ccitt_params.encoded_byte_align)
3801 p += snprintf (p, end - p, " /EncodedByteAlign true");
3802
3803 if (!ccitt_params.end_of_block)
3804 p += snprintf (p, end - p, " /EndOfBlock false");
3805
3806 if (ccitt_params.black_is_1)
3807 p += snprintf (p, end - p, " /BlackIs1 true");
3808
3809 if (ccitt_params.damaged_rows_before_error > 0) {
3810 p += snprintf (p, end - p, " /DamagedRowsBeforeError %d",
3811 ccitt_params.damaged_rows_before_error);
3812 }
3813
3814 if (surface_entry->stencil_mask) {
3815 status = _cairo_pdf_surface_open_stream (surface,
3816 &surface_entry->surface_res,
3817 FALSE0,
3818 " /Type /XObject\n"
3819 " /Subtype /Image\n"
3820 " /ImageMask true\n"
3821 " /Width %d\n"
3822 " /Height %d\n"
3823 " /Interpolate %s\n"
3824 " /BitsPerComponent 1\n"
3825 " /Decode [1 0]\n"
3826 " /Filter /CCITTFaxDecode\n"
3827 " /DecodeParms << %s >> ",
3828 ccitt_params.columns,
3829 ccitt_params.rows,
3830 surface_entry->interpolate ? "true" : "false",
3831 buf);
3832 } else {
3833 status = _cairo_pdf_surface_open_stream (surface,
3834 &surface_entry->surface_res,
3835 FALSE0,
3836 " /Type /XObject\n"
3837 " /Subtype /Image\n"
3838 " /Width %d\n"
3839 " /Height %d\n"
3840 " /ColorSpace /DeviceGray\n"
3841 " /BitsPerComponent 1\n"
3842 " /Interpolate %s\n"
3843 " /Filter /CCITTFaxDecode\n"
3844 " /DecodeParms << %s >> ",
3845 ccitt_params.columns,
3846 ccitt_params.rows,
3847 surface_entry->interpolate ? "true" : "false",
3848 buf);
3849 }
3850 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3851 return status;
3852
3853 _cairo_output_stream_write (surface->output, ccitt_data, ccitt_data_len);
3854 status = _cairo_pdf_surface_close_stream (surface);
3855
3856 return status;
3857}
3858
3859static cairo_int_status_t
3860_cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
3861 cairo_pdf_source_surface_t *pdf_source)
3862{
3863 cairo_rectangle_int_t old_surface_extents;
3864 cairo_bool_t old_surface_bounded;
3865 cairo_paginated_mode_t old_paginated_mode;
3866 cairo_surface_clipper_t old_clipper;
3867 cairo_bool_t old_in_xobject;
3868 cairo_box_double_t bbox;
3869 cairo_int_status_t status;
3870 int alpha = 0;
3871 cairo_surface_t *free_me = NULL((void*)0);
3872 cairo_surface_t *source;
3873 const cairo_rectangle_int_t *extents;
3874 cairo_bool_t is_subsurface;
3875 cairo_bool_t transparency_group;
3876 cairo_recording_surface_t *recording;
3877 int struct_parents = -1;
3878
3879 assert (pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE)((void) sizeof ((pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE
) ? 1 : 0), __extension__ ({ if (pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE
) ; else __assert_fail ("pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 3879, __extension__ __PRETTY_FUNCTION__); }))
;
3880
3881 if (pdf_source->hash_entry->bounded) {
3882 extents = &pdf_source->hash_entry->extents;
3883 } else {
3884 extents = &pdf_source->hash_entry->required_extents;
3885 }
3886
3887 is_subsurface = FALSE0;
3888 source = pdf_source->surface;
3889 if (_cairo_surface_is_snapshot (source))
3890 free_me = source = _cairo_surface_snapshot_get_target (source);
3891
3892 if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
3893 cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
3894
3895 source = sub->target;
3896 extents = &sub->extents;
3897 is_subsurface = TRUE1;
3898 }
3899
3900 assert (source->type == CAIRO_SURFACE_TYPE_RECORDING)((void) sizeof ((source->type == CAIRO_SURFACE_TYPE_RECORDING
) ? 1 : 0), __extension__ ({ if (source->type == CAIRO_SURFACE_TYPE_RECORDING
) ; else __assert_fail ("source->type == CAIRO_SURFACE_TYPE_RECORDING"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 3900, __extension__ __PRETTY_FUNCTION__); }))
;
3901 recording = (cairo_recording_surface_t *) source;
3902
3903 old_in_xobject = surface->in_xobject;
3904 old_surface_extents = surface->surface_extents;
3905 old_surface_bounded = surface->surface_bounded;
3906 old_paginated_mode = surface->paginated_mode;
3907 old_clipper = surface->clipper;
3908 surface->surface_extents = *extents;
3909 _cairo_surface_clipper_init (&surface->clipper,
3910 _cairo_pdf_surface_clipper_intersect_clip_path);
3911
3912 _cairo_pdf_operators_reset (&surface->pdf_operators);
3913 surface->in_xobject = TRUE1;
3914 surface->surface_extents = *extents;
3915 surface->surface_bounded = TRUE1;
3916
3917 /* Patterns are emitted after fallback images. The paginated mode
3918 * needs to be set to _RENDER while the recording surface is replayed
3919 * back to this surface.
3920 */
3921 surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
3922 _cairo_pdf_group_resources_clear (&surface->resources);
3923 _get_bbox_from_extents (extents, &bbox);
3924
3925 /* We can optimize away the transparency group allowing the viewer
3926 * to replay the group in place when:
3927 * - ca/CA when painting this groups is 1.0 (need_transp_group is FALSE),
3928 * - all operators are OVER, and
3929 * - the recording contains only opaque and/or clear alpha.
3930 */
3931 transparency_group = pdf_source->hash_entry->need_transp_group ||
3932 !(pdf_source->hash_entry->operator == CAIRO_OPERATOR_OVER &&
3933 _cairo_recording_surface_has_only_bilevel_alpha (recording) &&
3934 _cairo_recording_surface_has_only_op_over (recording));
3935
3936 status = _cairo_pdf_interchange_emit_recording_surface_begin (surface,
3937 pdf_source->surface,
3938 pdf_source->hash_entry->region_id,
3939 pdf_source->hash_entry->surface_res,
3940 &struct_parents);
3941 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3942 goto err;
3943
3944 status = _cairo_pdf_surface_open_content_stream (surface,
3945 &bbox,
3946 &pdf_source->hash_entry->surface_res,
3947 TRUE1,
3948 transparency_group,
3949 struct_parents);
3950 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3951 goto err;
3952
3953 /* Reset gstate */
3954 surface->reset_gs_required = TRUE1;
3955
3956 if (source->content == CAIRO_CONTENT_COLOR) {
3957 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
3958 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3959 goto err;
3960
3961 _cairo_output_stream_printf (surface->output,
3962 "q /a%d gs 0 0 0 rg %d %d %d %d re f Q\n",
3963 alpha,
3964 extents->x,
3965 extents->y,
3966 extents->width,
3967 extents->height);
3968 }
3969
3970 status = _cairo_recording_surface_replay_region (source,
3971 pdf_source->region_id,
3972 is_subsurface ? extents : NULL((void*)0),
3973 &surface->base,
3974 CAIRO_RECORDING_REGION_NATIVE);
3975 assert (status != CAIRO_INT_STATUS_UNSUPPORTED)((void) sizeof ((status != CAIRO_INT_STATUS_UNSUPPORTED) ? 1 :
0), __extension__ ({ if (status != CAIRO_INT_STATUS_UNSUPPORTED
) ; else __assert_fail ("status != CAIRO_INT_STATUS_UNSUPPORTED"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 3975, __extension__ __PRETTY_FUNCTION__); }))
;
3976 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3977 goto err;
3978
3979 status = _cairo_pdf_surface_close_content_stream (surface, TRUE1);
3980
3981 _cairo_surface_clipper_reset (&surface->clipper);
3982 surface->clipper = old_clipper;
3983 _cairo_pdf_operators_reset (&surface->pdf_operators);
3984 surface->in_xobject = old_in_xobject;
3985 surface->paginated_mode = old_paginated_mode;
3986 surface->surface_extents = old_surface_extents;
3987 surface->surface_bounded = old_surface_bounded;
3988 surface->reset_gs_required = FALSE0;
3989
3990 if (pdf_source->hash_entry->region_id > 0)
3991 status = _cairo_pdf_interchange_emit_recording_surface_end (surface, pdf_source->surface);
3992
3993err:
3994 cairo_surface_destroy_moz_cairo_surface_destroy (free_me);
3995 return status;
3996}
3997
3998/**
3999 * _cairo_pdf_surface_emit_surface:
4000 * @surface: [in] the pdf surface
4001 * @source: [in] #cairo_pdf_source_surface_t containing the surface to write
4002 * @test: [in] if true, test what type of surface will be emitted.
4003 * @is_image: [out] if @test is true, returns TRUE if the surface will be emitted
4004 * as an Image XObject.
4005 *
4006 * If @test is FALSE, emit @src_surface as an XObject.
4007 * If @test is TRUE, don't emit anything. Set @is_image based on the output that would be emitted.
4008 **/
4009static cairo_int_status_t
4010_cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface,
4011 cairo_pdf_source_surface_t *source,
4012 cairo_bool_t test,
4013 cairo_bool_t *is_image)
4014{
4015 cairo_image_surface_t *image;
4016 void *image_extra;
4017 cairo_int_status_t status;
4018
4019 /* Try all the supported mime types and recording type, falling through
4020 * each option if unsupported */
4021 if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
4022 status = _cairo_pdf_surface_emit_jbig2_image (surface,
4023 source->surface,
4024 source->hash_entry,
4025 test);
4026 if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
4027 *is_image = TRUE1;
4028 return status;
4029 }
4030
4031 status = _cairo_pdf_surface_emit_jpx_image (surface,
4032 source->surface,
4033 source->hash_entry,
4034 test);
4035 if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
4036 *is_image = TRUE1;
4037 return status;
4038 }
4039
4040 status = _cairo_pdf_surface_emit_jpeg_image (surface,
4041 source->surface,
4042 source->hash_entry,
4043 test);
4044 if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
4045 *is_image = TRUE1;
4046 return status;
4047 }
4048
4049 status = _cairo_pdf_surface_emit_ccitt_image (surface,
4050 source->surface,
4051 source->hash_entry,
4052 test);
4053 if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
4054 *is_image = TRUE1;
4055 return status;
4056 }
4057
4058 if (source->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
4059 if (test) {
4060 *is_image = FALSE0;
4061 return CAIRO_INT_STATUS_SUCCESS;
4062 } else {
4063 return _cairo_pdf_surface_emit_recording_surface (surface, source);
4064 }
4065 }
4066 }
4067
4068 /* The only option left is to emit as an image surface */
4069
4070 if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
4071 status = _cairo_surface_acquire_source_image (source->surface, &image, &image_extra);
4072 } else {
4073 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface,
4074 source->raster_pattern,
4075 &image,
4076 &image_extra);
4077 }
4078 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4079 return status;
4080
4081 if (test) {
4082 *is_image = TRUE1;
4083 } else {
4084 status = _cairo_pdf_surface_emit_image (surface,
4085 image,
4086 source->hash_entry);
4087 }
4088
4089 if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
4090 _cairo_surface_release_source_image (source->surface, image, image_extra);
4091 } else {
4092 _cairo_pdf_surface_release_source_image_from_pattern (surface,
4093 source->raster_pattern,
4094 image,
4095 image_extra);
4096 }
4097
4098 return status;
4099}
4100
4101static cairo_int_status_t
4102_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
4103 cairo_pdf_pattern_t *pdf_pattern)
4104{
4105 cairo_pattern_t *pattern = pdf_pattern->pattern;
4106 cairo_int_status_t status;
4107 cairo_matrix_t cairo_p2d, pdf_p2d;
4108 cairo_extend_t extend = cairo_pattern_get_extend_moz_cairo_pattern_get_extend (pattern);
4109 double xstep, ystep;
4110 cairo_rectangle_int_t pattern_extents;
4111 double x_offset;
4112 double y_offset;
4113 char draw_surface[50];
4114 char draw_surface2[200];
4115 cairo_box_double_t bbox;
4116 cairo_matrix_t mat;
4117 cairo_pdf_source_surface_entry_t *pdf_source;
4118 cairo_rectangle_int_t op_extents;
4119
4120 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-pdf-surface.c"
, 4120, __extension__ __PRETTY_FUNCTION__); }))
;
4121 if (pattern->extend == CAIRO_EXTEND_PAD) {
4122 status = _cairo_pdf_surface_add_padded_image_surface (surface,
4123 pattern,
4124 &pdf_pattern->extents,
4125 &pdf_source,
4126 &x_offset,
4127 &y_offset,
4128 &op_extents);
4129 } else {
4130 status = _cairo_pdf_surface_add_source_surface (surface,
4131 NULL((void*)0),
4132 pattern,
4133 pdf_pattern->region_id,
4134 pdf_pattern->operator,
4135 pattern->filter,
4136 FALSE0, /* stencil mask */
4137 FALSE0, /* smask */
4138 FALSE0, /* need_transp_group */
4139 &pdf_pattern->extents,
4140 NULL((void*)0), /* smask_res */
4141 &pdf_source,
4142 &x_offset,
4143 &y_offset,
4144 &op_extents);
4145 }
4146 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4147 return status;
4148
4149 pattern_extents = pdf_source->extents;
4150 if (!pdf_source->bounded)
4151 {
4152 extend = CAIRO_EXTEND_NONE;
4153 _cairo_rectangle_intersect (&pattern_extents, &op_extents);
4154 }
4155
4156 switch (extend) {
4157 case CAIRO_EXTEND_PAD:
4158 case CAIRO_EXTEND_NONE:
4159 {
4160 /* In PS/PDF, (as far as I can tell), all patterns are
4161 * repeating. So we support cairo's EXTEND_NONE semantics
4162 * by setting the repeat step size to a size large enough
4163 * to guarantee that no more than a single occurrence will
4164 * be visible.
4165 *
4166 * First, map the surface extents into pattern space (since
4167 * xstep and ystep are in pattern space). Then use an upper
4168 * bound on the length of the diagonal of the pattern image
4169 * and the surface as repeat size. This guarantees to never
4170 * repeat visibly.
4171 */
4172 double x1 = 0.0, y1 = 0.0;
4173 double x2 = surface->surface_extents.width;
4174 double y2 = surface->surface_extents.height;
4175 _cairo_matrix_transform_bounding_box (&pattern->matrix,
4176 &x1, &y1, &x2, &y2,
4177 NULL((void*)0));
4178
4179 /* Rather than computing precise bounds of the union, just
4180 * add the surface extents unconditionally. We only
4181 * required an answer that's large enough, we don't really
4182 * care if it's not as tight as possible.*/
4183 xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
4184 pattern_extents.width + pattern_extents.height);
4185 }
4186 break;
4187 case CAIRO_EXTEND_REPEAT:
4188 xstep = pattern_extents.width;
4189 ystep = pattern_extents.height;
4190 break;
4191
4192 case CAIRO_EXTEND_REFLECT:
4193 pattern_extents.width *= 2;
4194 pattern_extents.height *= 2;
4195 xstep = pattern_extents.width;
4196 ystep = pattern_extents.height;
4197 break;
4198
4199 /* All the rest (if any) should have been analyzed away, so this
4200 * case should be unreachable. */
4201 default:
4202 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 4202, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
4203 xstep = 0;
4204 ystep = 0;
4205 }
4206
4207 /* At this point, (that is, within the surface backend interface),
4208 * the pattern's matrix maps from cairo's device space to cairo's
4209 * pattern space, (both with their origin at the upper-left, and
4210 * cairo's pattern space of size width,height).
4211 *
4212 * Then, we must emit a PDF pattern object that maps from its own
4213 * pattern space, (which has a size that we establish in the BBox
4214 * dictionary entry), to the PDF page's *initial* space, (which
4215 * does not benefit from the Y-axis flipping matrix that we emit
4216 * on each page). So the PDF patterns matrix maps from a
4217 * (width,height) pattern space to a device space with the origin
4218 * in the lower-left corner.
4219 *
4220 * So to handle all of that, we start with an identity matrix for
4221 * the PDF pattern to device matrix. We translate it up by the
4222 * image height then flip it in the Y direction, (moving us from
4223 * the PDF origin to cairo's origin). We then multiply in the
4224 * inverse of the cairo pattern matrix, (since it maps from device
4225 * to pattern, while we're setting up pattern to device). Finally,
4226 * we translate back down by the image height and flip again to
4227 * end up at the lower-left origin that PDF expects.
4228 *
4229 * Additionally, within the stream that paints the pattern itself,
4230 * we are using a PDF image object that has a size of (1,1) so we
4231 * have to scale it up by the image width and height to fill our
4232 * pattern cell.
4233 */
4234 cairo_p2d = pattern->matrix;
4235 status = cairo_matrix_invert_moz_cairo_matrix_invert (&cairo_p2d);
4236 /* cairo_pattern_set_matrix ensures the matrix is invertible */
4237 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-pdf-surface.c"
, 4237, __extension__ __PRETTY_FUNCTION__); }))
;
4238
4239 if (pdf_pattern->inverted_y_axis)
4240 cairo_matrix_init_moz_cairo_matrix_init (&mat, 1, 0, 0, 1, 0, 0);
4241 else
4242 cairo_matrix_init_moz_cairo_matrix_init (&mat, 1, 0, 0, -1, 0, surface->height);
4243
4244 cairo_matrix_multiply_moz_cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &mat);
4245 cairo_matrix_translate_moz_cairo_matrix_translate (&pdf_p2d, x_offset, y_offset);
4246 if (pdf_source->emit_image) {
4247 cairo_matrix_translate_moz_cairo_matrix_translate (&pdf_p2d, 0.0, pdf_source->extents.height);
4248 cairo_matrix_scale_moz_cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
4249 }
4250
4251 _get_bbox_from_extents (&pattern_extents, &bbox);
4252 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
4253 status = _cairo_pdf_surface_open_stream (surface,
4254 &pdf_pattern->pattern_res,
4255 FALSE0,
4256 " /PatternType 1\n"
4257 " /BBox [ %f %f %f %f ]\n"
4258 " /XStep %f\n"
4259 " /YStep %f\n"
4260 " /TilingType 1\n"
4261 " /PaintType 1\n"
4262 " /Matrix [ %f %f %f %f %f %f ]\n"
4263 " /Resources << /XObject << /x%d %d 0 R >> >>\n",
4264 bbox.p1.x, bbox.p1.y, bbox.p2.x, bbox.p2.y,
4265 xstep, ystep,
4266 pdf_p2d.xx, pdf_p2d.yx,
4267 pdf_p2d.xy, pdf_p2d.yy,
4268 pdf_p2d.x0, pdf_p2d.y0,
4269 pdf_source->surface_res.id,
4270 pdf_source->surface_res.id);
4271 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4272 return status;
4273
4274 if (pdf_source->emit_image) {
4275 snprintf(draw_surface,
4276 sizeof (draw_surface),
4277 "q %d 0 0 %d 0 0 cm /x%d Do Q",
4278 pdf_source->extents.width,
4279 pdf_source->extents.height,
4280 pdf_source->surface_res.id);
4281 } else {
4282 snprintf(draw_surface,
4283 sizeof (draw_surface),
4284 "/x%d Do",
4285 pdf_source->surface_res.id);
4286 }
4287
4288 if (extend == CAIRO_EXTEND_REFLECT) {
4289 cairo_rectangle_int_t p_extents = pdf_source->extents;
4290 snprintf(draw_surface2,
4291 sizeof (draw_surface2),
4292 "%d %d %d %d re W n %s",
4293 p_extents.x, p_extents.y,
4294 p_extents.width, p_extents.height,
4295 draw_surface);
4296
4297 _cairo_output_stream_printf (surface->output, "q %s Q\n", draw_surface2);
4298
4299 cairo_matrix_init_translate_moz_cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y);
4300 cairo_matrix_scale_moz_cairo_matrix_scale (&mat, -1, 1);
4301 cairo_matrix_translate_moz_cairo_matrix_translate (&mat, -2*p_extents.width, 0);
4302 cairo_matrix_translate_moz_cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y);
4303 _cairo_output_stream_printf (surface->output, "q ");
4304 _cairo_output_stream_print_matrix (surface->output, &mat);
4305 _cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2);
4306
4307 cairo_matrix_init_translate_moz_cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y);
4308 cairo_matrix_scale_moz_cairo_matrix_scale (&mat, 1, -1);
4309 cairo_matrix_translate_moz_cairo_matrix_translate (&mat, 0, -2*p_extents.height);
4310 cairo_matrix_translate_moz_cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y);
4311 _cairo_output_stream_printf (surface->output, "q ");
4312 _cairo_output_stream_print_matrix (surface->output, &mat);
4313 _cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2);
4314
4315 cairo_matrix_init_translate_moz_cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y);
4316 cairo_matrix_scale_moz_cairo_matrix_scale (&mat, -1, -1);
4317 cairo_matrix_translate_moz_cairo_matrix_translate (&mat, -2*p_extents.width, -2*p_extents.height);
4318 cairo_matrix_translate_moz_cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y);
4319 _cairo_output_stream_printf (surface->output, "q ");
4320 _cairo_output_stream_print_matrix (surface->output, &mat);
4321 _cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2);
4322 } else {
4323 _cairo_output_stream_printf (surface->output,
4324 " %s \n",
4325 draw_surface);
4326 }
4327
4328 status = _cairo_pdf_surface_close_stream (surface);
4329 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4330 return status;
4331
4332 return _cairo_output_stream_get_status (surface->output);
4333}
4334
4335typedef struct _cairo_pdf_color_stop {
4336 double offset;
4337 double color[4];
4338 cairo_pdf_resource_t resource;
4339} cairo_pdf_color_stop_t;
4340
4341static cairo_int_status_t
4342cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t *surface,
4343 cairo_pdf_color_stop_t *stop1,
4344 cairo_pdf_color_stop_t *stop2,
4345 cairo_pdf_resource_t *function)
4346{
4347 int num_elems, i;
4348 cairo_pdf_rgb_linear_function_t elem;
4349 cairo_pdf_resource_t res;
4350 cairo_int_status_t status;
4351
4352 num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions);
4353 for (i = 0; i < num_elems; i++) {
4354 _cairo_array_copy_element (&surface->rgb_linear_functions, i, &elem);
4355 if (memcmp (&elem.color1[0], &stop1->color[0], sizeof (double)*3) != 0)
4356 continue;
4357 if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0)
4358 continue;
4359 *function = elem.resource;
4360 return CAIRO_STATUS_SUCCESS;
4361 }
4362
4363 res = _cairo_pdf_surface_new_object (surface);
4364 if (res.id == 0)
4365 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4366
4367 _cairo_output_stream_printf (surface->output,
4368 "%d 0 obj\n"
4369 "<< /FunctionType 2\n"
4370 " /Domain [ 0 1 ]\n"
4371 " /C0 [ %f %f %f ]\n"
4372 " /C1 [ %f %f %f ]\n"
4373 " /N 1\n"
4374 ">>\n"
4375 "endobj\n",
4376 res.id,
4377 stop1->color[0],
4378 stop1->color[1],
4379 stop1->color[2],
4380 stop2->color[0],
4381 stop2->color[1],
4382 stop2->color[2]);
4383
4384 elem.resource = res;
4385 memcpy (&elem.color1[0], &stop1->color[0], sizeof (double)*3);
4386 memcpy (&elem.color2[0], &stop2->color[0], sizeof (double)*3);
4387
4388 status = _cairo_array_append (&surface->rgb_linear_functions, &elem);
4389 *function = res;
4390
4391 return status;
4392}
4393
4394static cairo_int_status_t
4395cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t *surface,
4396 cairo_pdf_color_stop_t *stop1,
4397 cairo_pdf_color_stop_t *stop2,
4398 cairo_pdf_resource_t *function)
4399{
4400 int num_elems, i;
4401 cairo_pdf_alpha_linear_function_t elem;
4402 cairo_pdf_resource_t res;
4403 cairo_int_status_t status;
4404
4405 num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions);
4406 for (i = 0; i < num_elems; i++) {
4407 _cairo_array_copy_element (&surface->alpha_linear_functions, i, &elem);
4408 if (elem.alpha1 != stop1->color[3])
4409 continue;
4410 if (elem.alpha2 != stop2->color[3])
4411 continue;
4412 *function = elem.resource;
4413 return CAIRO_STATUS_SUCCESS;
4414 }
4415
4416 res = _cairo_pdf_surface_new_object (surface);
4417 if (res.id == 0)
4418 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4419
4420 _cairo_output_stream_printf (surface->output,
4421 "%d 0 obj\n"
4422 "<< /FunctionType 2\n"
4423 " /Domain [ 0 1 ]\n"
4424 " /C0 [ %f ]\n"
4425 " /C1 [ %f ]\n"
4426 " /N 1\n"
4427 ">>\n"
4428 "endobj\n",
4429 res.id,
4430 stop1->color[3],
4431 stop2->color[3]);
4432
4433 elem.resource = res;
4434 elem.alpha1 = stop1->color[3];
4435 elem.alpha2 = stop2->color[3];
4436
4437 status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
4438 *function = res;
4439
4440 return status;
4441}
4442
4443static cairo_int_status_t
4444_cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
4445 unsigned int n_stops,
4446 cairo_pdf_color_stop_t *stops,
4447 cairo_bool_t is_alpha,
4448 cairo_pdf_resource_t *function)
4449{
4450 cairo_pdf_resource_t res;
4451 unsigned int i;
4452 cairo_int_status_t status;
4453
4454 /* emit linear gradients between pairs of subsequent stops... */
4455 for (i = 0; i < n_stops-1; i++) {
4456 if (is_alpha) {
4457 status = cairo_pdf_surface_emit_alpha_linear_function (surface,
4458 &stops[i],
4459 &stops[i+1],
4460 &stops[i].resource);
4461 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4462 return status;
4463 } else {
4464 status = cairo_pdf_surface_emit_rgb_linear_function (surface,
4465 &stops[i],
4466 &stops[i+1],
4467 &stops[i].resource);
4468 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4469 return status;
4470 }
4471 }
4472
4473 /* ... and stitch them together */
4474 res = _cairo_pdf_surface_new_object (surface);
4475 if (res.id == 0)
4476 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4477
4478 _cairo_output_stream_printf (surface->output,
4479 "%d 0 obj\n"
4480 "<< /FunctionType 3\n"
4481 " /Domain [ %f %f ]\n",
4482 res.id,
4483 stops[0].offset,
4484 stops[n_stops - 1].offset);
4485
4486 _cairo_output_stream_printf (surface->output,
4487 " /Functions [ ");
4488 for (i = 0; i < n_stops-1; i++)
4489 _cairo_output_stream_printf (surface->output,
4490 "%d 0 R ", stops[i].resource.id);
4491 _cairo_output_stream_printf (surface->output,
4492 "]\n");
4493
4494 _cairo_output_stream_printf (surface->output,
4495 " /Bounds [ ");
4496 for (i = 1; i < n_stops-1; i++)
4497 _cairo_output_stream_printf (surface->output,
4498 "%f ", stops[i].offset);
4499 _cairo_output_stream_printf (surface->output,
4500 "]\n");
4501
4502 _cairo_output_stream_printf (surface->output,
4503 " /Encode [ ");
4504 for (i = 1; i < n_stops; i++)
4505 _cairo_output_stream_printf (surface->output,
4506 "0 1 ");
4507 _cairo_output_stream_printf (surface->output,
4508 "]\n");
4509
4510 _cairo_output_stream_printf (surface->output,
4511 ">>\n"
4512 "endobj\n");
4513
4514 *function = res;
4515
4516 return _cairo_output_stream_get_status (surface->output);
4517}
4518
4519
4520static void
4521calc_gradient_color (cairo_pdf_color_stop_t *new_stop,
4522 cairo_pdf_color_stop_t *stop1,
4523 cairo_pdf_color_stop_t *stop2)
4524{
4525 int i;
4526 double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
4527
4528 for (i = 0; i < 4; i++)
4529 new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
4530}
4531
4532#define COLOR_STOP_EPSILON1e-6 1e-6
4533
4534static cairo_int_status_t
4535_cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
4536 cairo_gradient_pattern_t *pattern,
4537 cairo_pdf_resource_t *color_function,
4538 cairo_pdf_resource_t *alpha_function)
4539{
4540 cairo_pdf_color_stop_t *allstops, *stops;
4541 unsigned int n_stops;
4542 unsigned int i;
4543 cairo_bool_t emit_alpha = FALSE0;
4544 cairo_int_status_t status;
4545
4546 color_function->id = 0;
4547 alpha_function->id = 0;
4548
4549 allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t));
4550 if (unlikely (allstops == NULL)(__builtin_expect (!!(allstops == ((void*)0)), 0)))
4551 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4552
4553 stops = &allstops[1];
4554 n_stops = pattern->n_stops;
4555
4556 for (i = 0; i < n_stops; i++) {
4557 stops[i].color[0] = pattern->stops[i].color.red;
4558 stops[i].color[1] = pattern->stops[i].color.green;
4559 stops[i].color[2] = pattern->stops[i].color.blue;
4560 stops[i].color[3] = pattern->stops[i].color.alpha;
4561 if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3])((stops[i].color[3]) >= ((double)0xff00 / (double)0xffff)))
4562 emit_alpha = TRUE1;
4563 stops[i].offset = pattern->stops[i].offset;
4564 }
4565
4566 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
4567 pattern->base.extend == CAIRO_EXTEND_REFLECT) {
4568 if (stops[0].offset > COLOR_STOP_EPSILON1e-6) {
4569 if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
4570 memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
4571 else
4572 calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
4573 stops = allstops;
4574 n_stops++;
4575 }
4576 stops[0].offset = 0.0;
4577
4578 if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON1e-6) {
4579 if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
4580 memcpy (&stops[n_stops],
4581 &stops[n_stops - 1],
4582 sizeof (cairo_pdf_color_stop_t));
4583 } else {
4584 calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
4585 }
4586 n_stops++;
4587 }
4588 stops[n_stops-1].offset = 1.0;
4589 }
4590
4591 if (stops[0].offset == stops[n_stops - 1].offset) {
4592 /*
4593 * The first and the last stops have the same offset, but we
4594 * don't want a function with an empty domain, because that
4595 * would provoke underdefined behaviour from rasterisers.
4596 * This can only happen with EXTEND_PAD, because EXTEND_NONE
4597 * is optimised into a clear pattern in cairo-gstate, and
4598 * REFLECT/REPEAT are always transformed to have the first
4599 * stop at t=0 and the last stop at t=1. Thus we want a step
4600 * function going from the first color to the last one.
4601 *
4602 * This can be accomplished by stitching three functions:
4603 * - a constant first color function,
4604 * - a step from the first color to the last color (with empty domain)
4605 * - a constant last color function
4606 */
4607 cairo_pdf_color_stop_t pad_stops[4];
4608
4609 assert (pattern->base.extend == CAIRO_EXTEND_PAD)((void) sizeof ((pattern->base.extend == CAIRO_EXTEND_PAD)
? 1 : 0), __extension__ ({ if (pattern->base.extend == CAIRO_EXTEND_PAD
) ; else __assert_fail ("pattern->base.extend == CAIRO_EXTEND_PAD"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 4609, __extension__ __PRETTY_FUNCTION__); }))
;
4610
4611 pad_stops[0] = pad_stops[1] = stops[0];
4612 pad_stops[2] = pad_stops[3] = stops[n_stops - 1];
4613
4614 pad_stops[0].offset = 0;
4615 pad_stops[3].offset = 1;
4616
4617 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
4618 4,
4619 pad_stops,
4620 FALSE0,
4621 color_function);
4622 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4623 goto BAIL;
4624
4625 if (emit_alpha) {
4626 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
4627 4,
4628 pad_stops,
4629 TRUE1,
4630 alpha_function);
4631 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4632 goto BAIL;
4633 }
4634 } else if (n_stops == 2) {
4635 /* no need for stitched function */
4636 status = cairo_pdf_surface_emit_rgb_linear_function (surface,
4637 &stops[0],
4638 &stops[n_stops - 1],
4639 color_function);
4640 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4641 goto BAIL;
4642
4643 if (emit_alpha) {
4644 status = cairo_pdf_surface_emit_alpha_linear_function (surface,
4645 &stops[0],
4646 &stops[n_stops - 1],
4647 alpha_function);
4648 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4649 goto BAIL;
4650 }
4651 } else {
4652 /* multiple stops: stitch. XXX possible optimization: regularly spaced
4653 * stops do not require stitching. XXX */
4654 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
4655 n_stops,
4656 stops,
4657 FALSE0,
4658 color_function);
4659 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4660 goto BAIL;
4661
4662 if (emit_alpha) {
4663 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
4664 n_stops,
4665 stops,
4666 TRUE1,
4667 alpha_function);
4668 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4669 goto BAIL;
4670 }
4671 }
4672
4673BAIL:
4674 free (allstops);
4675 return status;
4676}
4677
4678static cairo_int_status_t
4679_cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface,
4680 cairo_gradient_pattern_t *pattern,
4681 cairo_pdf_resource_t *function,
4682 int begin,
4683 int end)
4684{
4685 cairo_pdf_resource_t res;
4686 int i;
4687
4688 res = _cairo_pdf_surface_new_object (surface);
4689 if (res.id == 0)
4690 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4691
4692 _cairo_output_stream_printf (surface->output,
4693 "%d 0 obj\n"
4694 "<< /FunctionType 3\n"
4695 " /Domain [ %d %d ]\n",
4696 res.id,
4697 begin,
4698 end);
4699
4700 _cairo_output_stream_printf (surface->output,
4701 " /Functions [ ");
4702 for (i = begin; i < end; i++)
4703 _cairo_output_stream_printf (surface->output,
4704 "%d 0 R ", function->id);
4705 _cairo_output_stream_printf (surface->output,
4706 "]\n");
4707
4708 _cairo_output_stream_printf (surface->output,
4709 " /Bounds [ ");
4710 for (i = begin + 1; i < end; i++)
4711 _cairo_output_stream_printf (surface->output,
4712 "%d ", i);
4713 _cairo_output_stream_printf (surface->output,
4714 "]\n");
4715
4716 _cairo_output_stream_printf (surface->output,
4717 " /Encode [ ");
4718 for (i = begin; i < end; i++) {
4719 if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) {
4720 _cairo_output_stream_printf (surface->output,
4721 "1 0 ");
4722 } else {
4723 _cairo_output_stream_printf (surface->output,
4724 "0 1 ");
4725 }
4726 }
4727 _cairo_output_stream_printf (surface->output,
4728 "]\n");
4729
4730 _cairo_output_stream_printf (surface->output,
4731 ">>\n"
4732 "endobj\n");
4733
4734 *function = res;
4735
4736 return _cairo_output_stream_get_status (surface->output);
4737}
4738
4739static cairo_int_status_t
4740cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
4741 cairo_pdf_pattern_t *pdf_pattern,
4742 cairo_pdf_resource_t gstate_resource,
4743 cairo_pdf_resource_t gradient_mask)
4744{
4745 cairo_pdf_resource_t smask_resource;
4746 cairo_int_status_t status;
4747 char buf[100];
4748 double x1, y1, x2, y2;
4749
4750 if (pdf_pattern->is_shading) {
4751 snprintf(buf, sizeof(buf),
4752 " /Shading\n"
4753 " << /sh%d %d 0 R >>\n",
4754 gradient_mask.id,
4755 gradient_mask.id);
4756 } else {
4757 snprintf(buf, sizeof(buf),
4758 " /Pattern\n"
4759 " << /p%d %d 0 R >>\n",
4760 gradient_mask.id,
4761 gradient_mask.id);
4762 }
4763
4764 if (pdf_pattern->is_shading) {
4765 cairo_box_t box;
4766
4767 /* When emitting a shading operator we are in cairo pattern
4768 * coordinates. _cairo_pdf_surface_paint_gradient has set the
4769 * ctm to the pattern matrix (including the conversion from
4770 * pdf to cairo coordinates) */
4771 _cairo_box_from_rectangle (&box, &pdf_pattern->extents);
4772 _cairo_box_to_doubles (&box, &x1, &y1, &x2, &y2);
4773 _cairo_matrix_transform_bounding_box (&pdf_pattern->pattern->matrix, &x1, &y1, &x2, &y2, NULL((void*)0));
4774 } else {
4775 cairo_box_double_t box;
4776
4777 /* When emitting a shading pattern we are in pdf page
4778 * coordinates. The color and alpha shading patterns painted
4779 * in the XObject below contain the cairo pattern to pdf page
4780 * matrix in the /Matrix entry of the pattern. */
4781 _get_bbox_from_extents (&pdf_pattern->extents, &box);
4782 x1 = box.p1.x;
4783 y1 = box.p1.y;
4784 x2 = box.p2.x;
4785 y2 = box.p2.y;
4786 }
4787 status = _cairo_pdf_surface_open_stream (surface,
4788 NULL((void*)0),
4789 surface->compress_streams,
4790 " /Type /XObject\n"
4791 " /Subtype /Form\n"
4792 " /FormType 1\n"
4793 " /BBox [ %f %f %f %f ]\n"
4794 " /Resources\n"
4795 " << /ExtGState\n"
4796 " << /a0 << /ca 1 /CA 1 >>"
4797 " >>\n"
4798 "%s"
4799 " >>\n"
4800 " /Group\n"
4801 " << /Type /Group\n"
4802 " /S /Transparency\n"
4803 " /I true\n"
4804 " /CS /DeviceGray\n"
4805 " >>\n",
4806 x1,y1,x2,y2,
4807 buf);
4808 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4809 return status;
4810
4811 if (pdf_pattern->is_shading) {
4812 _cairo_output_stream_printf (surface->output,
4813 "/a0 gs /sh%d sh\n",
4814 gradient_mask.id);
4815 } else {
4816 _cairo_output_stream_printf (surface->output,
4817 "q\n"
4818 "/a0 gs\n"
4819 "/Pattern cs /p%d scn\n"
4820 "0 0 %f %f re\n"
4821 "f\n"
4822 "Q\n",
4823 gradient_mask.id,
4824 surface->width,
4825 surface->height);
4826 }
4827
4828 status = _cairo_pdf_surface_close_stream (surface);
4829 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4830 return status;
4831
4832 smask_resource = _cairo_pdf_surface_new_object (surface);
4833 if (smask_resource.id == 0)
4834 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4835
4836 _cairo_output_stream_printf (surface->output,
4837 "%d 0 obj\n"
4838 "<< /Type /Mask\n"
4839 " /S /Luminosity\n"
4840 " /G %d 0 R\n"
4841 ">>\n"
4842 "endobj\n",
4843 smask_resource.id,
4844 surface->pdf_stream.self.id);
4845
4846 /* Create GState which uses the transparency group as an SMask. */
4847 _cairo_pdf_surface_update_object (surface, gstate_resource);
4848
4849 _cairo_output_stream_printf (surface->output,
4850 "%d 0 obj\n"
4851 "<< /Type /ExtGState\n"
4852 " /SMask %d 0 R\n"
4853 " /ca 1\n"
4854 " /CA 1\n"
4855 " /AIS false\n"
4856 ">>\n"
4857 "endobj\n",
4858 gstate_resource.id,
4859 smask_resource.id);
4860
4861 return _cairo_output_stream_get_status (surface->output);
4862}
4863
4864static void
4865_cairo_pdf_surface_output_gradient (cairo_pdf_surface_t *surface,
4866 const cairo_pdf_pattern_t *pdf_pattern,
4867 cairo_pdf_resource_t pattern_resource,
4868 const cairo_matrix_t *pat_to_pdf,
4869 const cairo_circle_double_t*start,
4870 const cairo_circle_double_t*end,
4871 const double *domain,
4872 const char *colorspace,
4873 cairo_pdf_resource_t color_function)
4874{
4875 _cairo_output_stream_printf (surface->output,
4876 "%d 0 obj\n",
4877 pattern_resource.id);
4878
4879 if (!pdf_pattern->is_shading) {
4880 _cairo_output_stream_printf (surface->output,
4881 "<< /Type /Pattern\n"
4882 " /PatternType 2\n"
4883 " /Matrix [ ");
4884 _cairo_output_stream_print_matrix (surface->output, pat_to_pdf);
4885 _cairo_output_stream_printf (surface->output,
4886 " ]\n"
4887 " /Shading\n");
4888 }
4889
4890 if (pdf_pattern->pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
4891 _cairo_output_stream_printf (surface->output,
4892 " << /ShadingType 2\n"
4893 " /ColorSpace %s\n"
4894 " /Coords [ %f %f %f %f ]\n",
4895 colorspace,
4896 start->center.x, start->center.y,
4897 end->center.x, end->center.y);
4898 } else {
4899 _cairo_output_stream_printf (surface->output,
4900 " << /ShadingType 3\n"
4901 " /ColorSpace %s\n"
4902 " /Coords [ %f %f %f %f %f %f ]\n",
4903 colorspace,
4904 start->center.x, start->center.y,
4905 MAX (start->radius, 0)((start->radius) > (0) ? (start->radius) : (0)),
4906 end->center.x, end->center.y,
4907 MAX (end->radius, 0)((end->radius) > (0) ? (end->radius) : (0)));
4908 }
4909
4910 _cairo_output_stream_printf (surface->output,
4911 " /Domain [ %f %f ]\n",
4912 domain[0], domain[1]);
4913
4914 if (pdf_pattern->pattern->extend != CAIRO_EXTEND_NONE) {
4915 _cairo_output_stream_printf (surface->output,
4916 " /Extend [ true true ]\n");
4917 } else {
4918 _cairo_output_stream_printf (surface->output,
4919 " /Extend [ false false ]\n");
4920 }
4921
4922 _cairo_output_stream_printf (surface->output,
4923 " /Function %d 0 R\n"
4924 " >>\n",
4925 color_function.id);
4926
4927 if (!pdf_pattern->is_shading) {
4928 _cairo_output_stream_printf (surface->output,
4929 ">>\n");
4930 }
4931
4932 _cairo_output_stream_printf (surface->output,
4933 "endobj\n");
4934}
4935
4936static cairo_int_status_t
4937_cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t *surface,
4938 cairo_pdf_pattern_t *pdf_pattern)
4939{
4940 cairo_gradient_pattern_t *pattern = (cairo_gradient_pattern_t *) pdf_pattern->pattern;
4941 cairo_pdf_resource_t color_function, alpha_function;
4942 cairo_matrix_t pat_to_pdf;
4943 cairo_circle_double_t start, end;
4944 double domain[2];
4945 cairo_int_status_t status;
4946 cairo_matrix_t mat;
4947
4948 assert (pattern->n_stops != 0)((void) sizeof ((pattern->n_stops != 0) ? 1 : 0), __extension__
({ if (pattern->n_stops != 0) ; else __assert_fail ("pattern->n_stops != 0"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 4948, __extension__ __PRETTY_FUNCTION__); }))
;
4949
4950 status = _cairo_pdf_surface_emit_pattern_stops (surface,
4951 pattern,
4952 &color_function,
4953 &alpha_function);
4954 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4955 return status;
4956
4957 pat_to_pdf = pattern->base.matrix;
4958 status = cairo_matrix_invert_moz_cairo_matrix_invert (&pat_to_pdf);
4959 /* cairo_pattern_set_matrix ensures the matrix is invertible */
4960 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-pdf-surface.c"
, 4960, __extension__ __PRETTY_FUNCTION__); }))
;
4961
4962 if (pdf_pattern->inverted_y_axis)
4963 cairo_matrix_init_moz_cairo_matrix_init (&mat, 1, 0, 0, 1, 0, 0);
4964 else
4965 cairo_matrix_init_moz_cairo_matrix_init (&mat, 1, 0, 0, -1, 0, surface->height);
4966
4967 cairo_matrix_multiply_moz_cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &mat);
4968
4969 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
4970 pattern->base.extend == CAIRO_EXTEND_REFLECT)
4971 {
4972 double bounds_x1, bounds_x2, bounds_y1, bounds_y2;
4973 double x_scale, y_scale, tolerance;
4974
4975 /* TODO: use tighter extents */
4976 bounds_x1 = 0;
4977 bounds_y1 = 0;
4978 bounds_x2 = surface->width;
4979 bounds_y2 = surface->height;
4980 _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
4981 &bounds_x1, &bounds_y1,
4982 &bounds_x2, &bounds_y2,
4983 NULL((void*)0));
4984
4985 x_scale = surface->base.x_resolution / surface->base.x_fallback_resolution;
4986 y_scale = surface->base.y_resolution / surface->base.y_fallback_resolution;
4987
4988 tolerance = fabs (_cairo_matrix_compute_determinant (&pattern->base.matrix));
4989 tolerance /= _cairo_matrix_transformed_circle_major_axis (&pattern->base.matrix, 1);
4990 tolerance *= MIN (x_scale, y_scale)((x_scale) < (y_scale) ? (x_scale) : (y_scale));
4991
4992 _cairo_gradient_pattern_box_to_parameter (pattern,
4993 bounds_x1, bounds_y1,
4994 bounds_x2, bounds_y2,
4995 tolerance, domain);
4996 } else if (pattern->stops[0].offset == pattern->stops[pattern->n_stops - 1].offset) {
4997 /*
4998 * If the first and the last stop offset are the same, then
4999 * the color function is a step function.
5000 * _cairo_ps_surface_emit_pattern_stops emits it as a stitched
5001 * function no matter how many stops the pattern has. The
5002 * domain of the stitched function will be [0 1] in this case.
5003 *
5004 * This is done to avoid emitting degenerate gradients for
5005 * EXTEND_PAD patterns having a step color function.
5006 */
5007 domain[0] = 0.0;
5008 domain[1] = 1.0;
5009
5010 assert (pattern->base.extend == CAIRO_EXTEND_PAD)((void) sizeof ((pattern->base.extend == CAIRO_EXTEND_PAD)
? 1 : 0), __extension__ ({ if (pattern->base.extend == CAIRO_EXTEND_PAD
) ; else __assert_fail ("pattern->base.extend == CAIRO_EXTEND_PAD"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 5010, __extension__ __PRETTY_FUNCTION__); }))
;
5011 } else {
5012 domain[0] = pattern->stops[0].offset;
5013 domain[1] = pattern->stops[pattern->n_stops - 1].offset;
5014 }
5015
5016 /* PDF requires the first and last stop to be the same as the
5017 * extreme coordinates. For repeating patterns this moves the
5018 * extreme coordinates out to the begin/end of the repeating
5019 * function. For non repeating patterns this may move the extreme
5020 * coordinates in if there are not stops at offset 0 and 1. */
5021 _cairo_gradient_pattern_interpolate (pattern, domain[0], &start);
5022 _cairo_gradient_pattern_interpolate (pattern, domain[1], &end);
5023
5024 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
5025 pattern->base.extend == CAIRO_EXTEND_REFLECT)
5026 {
5027 int repeat_begin, repeat_end;
5028
5029 repeat_begin = floor (domain[0]);
5030 repeat_end = ceil (domain[1]);
5031
5032 status = _cairo_pdf_surface_emit_repeating_function (surface,
5033 pattern,
5034 &color_function,
5035 repeat_begin,
5036 repeat_end);
5037 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5038 return status;
5039
5040 if (alpha_function.id != 0) {
5041 status = _cairo_pdf_surface_emit_repeating_function (surface,
5042 pattern,
5043 &alpha_function,
5044 repeat_begin,
5045 repeat_end);
5046 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5047 return status;
5048 }
5049 } else if (pattern->n_stops <= 2) {
5050 /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
5051 * Type 2 function is used by itself without a stitching
5052 * function. Type 2 functions always have the domain [0 1] */
5053 domain[0] = 0.0;
5054 domain[1] = 1.0;
5055 }
5056
5057 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
5058 _cairo_pdf_surface_output_gradient (surface, pdf_pattern,
5059 pdf_pattern->pattern_res,
5060 &pat_to_pdf, &start, &end, domain,
5061 "/DeviceRGB", color_function);
5062
5063 if (alpha_function.id != 0) {
5064 cairo_pdf_resource_t mask_resource;
5065
5066 assert (pdf_pattern->gstate_res.id != 0)((void) sizeof ((pdf_pattern->gstate_res.id != 0) ? 1 : 0)
, __extension__ ({ if (pdf_pattern->gstate_res.id != 0) ; else
__assert_fail ("pdf_pattern->gstate_res.id != 0", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 5066, __extension__ __PRETTY_FUNCTION__); }))
;
5067
5068 /* Create pattern for SMask. */
5069 mask_resource = _cairo_pdf_surface_new_object (surface);
5070 if (mask_resource.id == 0)
5071 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5072
5073 _cairo_pdf_surface_output_gradient (surface, pdf_pattern,
5074 mask_resource,
5075 &pat_to_pdf, &start, &end, domain,
5076 "/DeviceGray", alpha_function);
5077
5078 status = cairo_pdf_surface_emit_transparency_group (surface,
5079 pdf_pattern,
5080 pdf_pattern->gstate_res,
5081 mask_resource);
5082 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5083 return status;
5084 }
5085
5086 return _cairo_output_stream_get_status (surface->output);
5087}
5088
5089static cairo_int_status_t
5090_cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
5091 cairo_pdf_pattern_t *pdf_pattern)
5092{
5093 cairo_matrix_t pat_to_pdf;
5094 cairo_int_status_t status;
5095 cairo_pattern_t *pattern = pdf_pattern->pattern;
5096 cairo_pdf_shading_t shading;
5097 int i;
5098 cairo_pdf_resource_t res;
5099 cairo_matrix_t mat;
5100
5101 pat_to_pdf = pattern->matrix;
5102 status = cairo_matrix_invert_moz_cairo_matrix_invert (&pat_to_pdf);
5103 /* cairo_pattern_set_matrix ensures the matrix is invertible */
5104 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-pdf-surface.c"
, 5104, __extension__ __PRETTY_FUNCTION__); }))
;
5105
5106 if (pdf_pattern->inverted_y_axis)
5107 cairo_matrix_init_moz_cairo_matrix_init (&mat, 1, 0, 0, 1, 0, 0);
5108 else
5109 cairo_matrix_init_moz_cairo_matrix_init (&mat, 1, 0, 0, -1, 0, surface->height);
5110
5111 cairo_matrix_multiply_moz_cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &mat);
5112
5113 status = _cairo_pdf_shading_init_color (&shading, (cairo_mesh_pattern_t *) pattern);
5114 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5115 return status;
5116
5117 res = _cairo_pdf_surface_new_object (surface);
5118 if (unlikely (res.id == 0)(__builtin_expect (!!(res.id == 0), 0)))
5119 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5120
5121 _cairo_output_stream_printf (surface->output,
5122 "%d 0 obj\n"
5123 "<< /ShadingType %d\n"
5124 " /ColorSpace /DeviceRGB\n"
5125 " /BitsPerCoordinate %d\n"
5126 " /BitsPerComponent %d\n"
5127 " /BitsPerFlag %d\n"
5128 " /Decode [",
5129 res.id,
5130 shading.shading_type,
5131 shading.bits_per_coordinate,
5132 shading.bits_per_component,
5133 shading.bits_per_flag);
5134
5135 for (i = 0; i < shading.decode_array_length; i++)
5136 _cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
5137
5138 _cairo_output_stream_printf (surface->output,
5139 "]\n"
5140 " /Length %ld\n"
5141 ">>\n"
5142 "stream\n",
5143 shading.data_length);
5144
5145 _cairo_output_stream_write (surface->output, shading.data, shading.data_length);
5146
5147 _cairo_output_stream_printf (surface->output,
5148 "\nendstream\n"
5149 "endobj\n");
5150
5151 _cairo_pdf_shading_fini (&shading);
5152
5153 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
5154 _cairo_output_stream_printf (surface->output,
5155 "%d 0 obj\n"
5156 "<< /Type /Pattern\n"
5157 " /PatternType 2\n"
5158 " /Matrix [ ",
5159 pdf_pattern->pattern_res.id);
5160 _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
5161 _cairo_output_stream_printf (surface->output,
5162 " ]\n"
5163 " /Shading %d 0 R\n"
5164 ">>\n"
5165 "endobj\n",
5166 res.id);
5167
5168 if (pdf_pattern->gstate_res.id != 0) {
5169 cairo_pdf_resource_t mask_resource;
5170
5171 /* Create pattern for SMask. */
5172 res = _cairo_pdf_surface_new_object (surface);
5173 if (unlikely (res.id == 0)(__builtin_expect (!!(res.id == 0), 0)))
5174 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5175
5176 status = _cairo_pdf_shading_init_alpha (&shading, (cairo_mesh_pattern_t *) pattern);
5177 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5178 return status;
5179
5180 _cairo_output_stream_printf (surface->output,
5181 "%d 0 obj\n"
5182 "<< /ShadingType %d\n"
5183 " /ColorSpace /DeviceGray\n"
5184 " /BitsPerCoordinate %d\n"
5185 " /BitsPerComponent %d\n"
5186 " /BitsPerFlag %d\n"
5187 " /Decode [",
5188 res.id,
5189 shading.shading_type,
5190 shading.bits_per_coordinate,
5191 shading.bits_per_component,
5192 shading.bits_per_flag);
5193
5194 for (i = 0; i < shading.decode_array_length; i++)
5195 _cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
5196
5197 _cairo_output_stream_printf (surface->output,
5198 "]\n"
5199 " /Length %ld\n"
5200 ">>\n"
5201 "stream\n",
5202 shading.data_length);
5203
5204 _cairo_output_stream_write (surface->output, shading.data, shading.data_length);
5205
5206 _cairo_output_stream_printf (surface->output,
5207 "\nendstream\n"
5208 "endobj\n");
5209 _cairo_pdf_shading_fini (&shading);
5210
5211 mask_resource = _cairo_pdf_surface_new_object (surface);
5212 if (unlikely (mask_resource.id == 0)(__builtin_expect (!!(mask_resource.id == 0), 0)))
5213 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5214
5215 _cairo_output_stream_printf (surface->output,
5216 "%d 0 obj\n"
5217 "<< /Type /Pattern\n"
5218 " /PatternType 2\n"
5219 " /Matrix [ ",
5220 mask_resource.id);
5221 _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
5222 _cairo_output_stream_printf (surface->output,
5223 " ]\n"
5224 " /Shading %d 0 R\n"
5225 ">>\n"
5226 "endobj\n",
5227 res.id);
5228
5229 status = cairo_pdf_surface_emit_transparency_group (surface,
5230 pdf_pattern,
5231 pdf_pattern->gstate_res,
5232 mask_resource);
5233 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5234 return status;
5235 }
5236
5237 return _cairo_output_stream_get_status (surface->output);
5238}
5239
5240static cairo_int_status_t
5241_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
5242{
5243 cairo_int_status_t status;
5244
5245 switch (pdf_pattern->pattern->type) {
5246 case CAIRO_PATTERN_TYPE_SOLID:
5247 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 5247, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
5248 status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
5249 break;
5250
5251 case CAIRO_PATTERN_TYPE_SURFACE:
5252 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
5253 status = _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
5254 break;
5255
5256 case CAIRO_PATTERN_TYPE_LINEAR:
5257 case CAIRO_PATTERN_TYPE_RADIAL:
5258 status = _cairo_pdf_surface_emit_gradient (surface, pdf_pattern);
5259 break;
5260
5261 case CAIRO_PATTERN_TYPE_MESH:
5262 status = _cairo_pdf_surface_emit_mesh_pattern (surface, pdf_pattern);
5263 break;
5264
5265 default:
5266 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 5266, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
5267 status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
5268 break;
5269 }
5270
5271 return status;
5272}
5273
5274static cairo_int_status_t
5275_cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
5276 cairo_operator_t op,
5277 const cairo_pattern_t *source,
5278 cairo_analysis_source_t source_type,
5279 const cairo_rectangle_int_t *extents,
5280 double alpha,
5281 cairo_pdf_resource_t *smask_res,
5282 cairo_bool_t stencil_mask)
5283{
5284 cairo_matrix_t cairo_p2d, pdf_p2d;
5285 cairo_int_status_t status;
5286 int alpha_id;
5287 double x_offset;
5288 double y_offset;
5289 cairo_pdf_source_surface_entry_t *pdf_source;
5290 int region_id = 0;
5291
5292 if (source->extend == CAIRO_EXTEND_PAD &&
5293 !(source->type == CAIRO_PATTERN_TYPE_SURFACE &&
5294 ((cairo_surface_pattern_t *)source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING))
5295 {
5296 status = _cairo_pdf_surface_add_padded_image_surface (surface,
5297 source,
5298 extents,
5299 &pdf_source,
5300 &x_offset,
5301 &y_offset,
5302 NULL((void*)0));
5303 } else {
5304 if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
5305 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source;
5306 if (_cairo_pdf_interchange_struct_tree_requires_recording_surface (surface,
5307 surface_pattern,
5308 source_type))
5309 {
5310 region_id = surface_pattern->region_array_id;
5311 }
5312 }
5313 status = _cairo_pdf_surface_add_source_surface (surface,
5314 NULL((void*)0),
5315 source,
5316 region_id,
5317 op,
5318 source->filter,
5319 stencil_mask,
5320 FALSE0, /* smask */
5321 alpha != 1.0, /* need_transp_group */
5322 extents,
5323 smask_res,
5324
5325 &pdf_source,
5326 &x_offset,
5327 &y_offset,
5328 NULL((void*)0));
5329 }
5330 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5331 return status;
5332
5333 cairo_p2d = source->matrix;
5334 status = cairo_matrix_invert_moz_cairo_matrix_invert (&cairo_p2d);
5335 /* cairo_pattern_set_matrix ensures the matrix is invertible */
5336 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-pdf-surface.c"
, 5336, __extension__ __PRETTY_FUNCTION__); }))
;
5337
5338 pdf_p2d = surface->cairo_to_pdf;
5339 cairo_matrix_multiply_moz_cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
5340 cairo_matrix_translate_moz_cairo_matrix_translate (&pdf_p2d, x_offset, y_offset);
5341 if (pdf_source->emit_image) {
5342 int width, height;
5343
5344 if (pdf_source->bounded) {
5345 width = pdf_source->extents.width;
5346 height = pdf_source->extents.height;
5347 } else {
5348 /* We can't scale an image to an unbounded surface size so just set the size to 1 */
5349 width = 1;
5350 height = 1;
5351 }
5352
5353 cairo_matrix_translate_moz_cairo_matrix_translate (&pdf_p2d, 0.0, height);
5354 cairo_matrix_scale_moz_cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
5355 cairo_matrix_scale_moz_cairo_matrix_scale (&pdf_p2d, width, height);
5356 }
5357
5358 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5359 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5360 return status;
5361
5362 if (! _cairo_matrix_is_identity (&pdf_p2d)) {
5363 _cairo_output_stream_print_matrix (surface->output, &pdf_p2d);
5364 _cairo_output_stream_printf (surface->output, " cm\n");
5365 }
5366
5367 status = _cairo_pdf_surface_add_alpha (surface, alpha, &alpha_id);
5368 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5369 return status;
5370
5371 if (stencil_mask) {
5372 _cairo_output_stream_printf (surface->output,
5373 "/x%d Do\n",
5374 pdf_source->surface_res.id);
5375 } else {
5376 _cairo_output_stream_printf (surface->output,
5377 "/a%d gs /x%d Do\n",
5378 alpha_id,
5379 pdf_source->surface_res.id);
5380 }
5381
5382 return _cairo_pdf_surface_add_xobject (surface, pdf_source->surface_res);
5383}
5384
5385static cairo_int_status_t
5386_cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t *surface,
5387 cairo_operator_t op,
5388 const cairo_pattern_t *source,
5389 const cairo_rectangle_int_t *extents,
5390 double alpha)
5391{
5392 cairo_pdf_resource_t shading_res, gstate_res;
5393 cairo_matrix_t pat_to_pdf;
5394 cairo_int_status_t status;
5395 int alpha_id;
5396
5397 status = _cairo_pdf_surface_add_pdf_shading (surface, source,
5398 op, extents,
5399 &shading_res, &gstate_res);
5400 if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO)(__builtin_expect (!!(status == CAIRO_INT_STATUS_NOTHING_TO_DO
), 0))
)
5401 return CAIRO_INT_STATUS_SUCCESS;
5402 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5403 return status;
5404
5405 pat_to_pdf = source->matrix;
5406 status = cairo_matrix_invert_moz_cairo_matrix_invert (&pat_to_pdf);
5407 /* cairo_pattern_set_matrix ensures the matrix is invertible */
5408 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-pdf-surface.c"
, 5408, __extension__ __PRETTY_FUNCTION__); }))
;
5409 cairo_matrix_multiply_moz_cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
5410
5411 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5412 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5413 return status;
5414
5415 if (! _cairo_matrix_is_identity (&pat_to_pdf)) {
5416 _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
5417 _cairo_output_stream_printf (surface->output, " cm\n");
5418 }
5419
5420 status = _cairo_pdf_surface_add_shading (surface, shading_res);
5421 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5422 return status;
5423
5424 if (gstate_res.id != 0) {
5425 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5426 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5427 return status;
5428
5429 _cairo_output_stream_printf (surface->output,
5430 "/s%d gs /sh%d sh\n",
5431 gstate_res.id,
5432 shading_res.id);
5433 } else {
5434 status = _cairo_pdf_surface_add_alpha (surface, alpha, &alpha_id);
5435 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5436 return status;
5437
5438 _cairo_output_stream_printf (surface->output,
5439 "/a%d gs /sh%d sh\n",
5440 alpha_id,
5441 shading_res.id);
5442 }
5443
5444 return status;
5445}
5446
5447static cairo_int_status_t
5448_cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface,
5449 cairo_operator_t op,
5450 const cairo_pattern_t *source,
5451 cairo_analysis_source_t source_type,
5452 const cairo_rectangle_int_t *extents,
5453 double alpha,
5454 cairo_bool_t mask)
5455{
5456 switch (source->type) {
5457 case CAIRO_PATTERN_TYPE_SURFACE:
5458 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
5459 return _cairo_pdf_surface_paint_surface_pattern (surface,
5460 op,
5461 source,
5462 source_type,
5463 extents,
5464 alpha,
5465 NULL((void*)0),
5466 mask);
5467 case CAIRO_PATTERN_TYPE_LINEAR:
5468 case CAIRO_PATTERN_TYPE_RADIAL:
5469 case CAIRO_PATTERN_TYPE_MESH:
5470 return _cairo_pdf_surface_paint_gradient (surface,
5471 op,
5472 source,
5473 extents,
5474 alpha);
5475
5476 case CAIRO_PATTERN_TYPE_SOLID:
5477 default:
5478 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 5478, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
5479 return CAIRO_STATUS_SUCCESS;
5480 }
5481}
5482
5483static cairo_bool_t
5484_can_paint_pattern (const cairo_pattern_t *pattern)
5485{
5486 switch (pattern->type) {
5487 case CAIRO_PATTERN_TYPE_SOLID:
5488 return FALSE0;
5489
5490 case CAIRO_PATTERN_TYPE_SURFACE:
5491 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
5492 return (pattern->extend == CAIRO_EXTEND_NONE ||
5493 pattern->extend == CAIRO_EXTEND_PAD);
5494
5495 case CAIRO_PATTERN_TYPE_LINEAR:
5496 case CAIRO_PATTERN_TYPE_RADIAL:
5497 return TRUE1;
5498
5499 case CAIRO_PATTERN_TYPE_MESH:
5500 return FALSE0;
5501
5502 default:
5503 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 5503, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
5504 return FALSE0;
5505 }
5506}
5507
5508static cairo_int_status_t
5509_cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface,
5510 cairo_operator_t op)
5511{
5512 cairo_int_status_t status;
5513
5514 if (surface->reset_gs_required) {
5515 _cairo_output_stream_printf (surface->output, "/gs0 gs\n");
5516 surface->reset_gs_required = FALSE0;
5517 }
5518
5519 if (op == surface->current_operator)
5520 return CAIRO_STATUS_SUCCESS;
5521
5522 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5523 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5524 return status;
5525
5526 _cairo_output_stream_printf (surface->output,
5527 "/b%d gs\n", op);
5528 surface->current_operator = op;
5529 _cairo_pdf_surface_add_operator (surface, op);
5530
5531 return CAIRO_STATUS_SUCCESS;
5532}
5533
5534static cairo_int_status_t
5535_cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
5536 const cairo_pattern_t *pattern,
5537 cairo_pdf_resource_t pattern_res,
5538 cairo_bool_t is_stroke)
5539{
5540 cairo_int_status_t status;
5541 int alpha;
5542 const cairo_color_t *solid_color = NULL((void*)0);
5543
5544 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
5545 const cairo_solid_pattern_t *solid = (const cairo_solid_pattern_t *) pattern;
5546
5547 solid_color = &solid->color;
5548 }
5549
5550 if (solid_color != NULL((void*)0)) {
5551 if (surface->current_pattern_is_solid_color == FALSE0 ||
5552 surface->current_color_red != solid_color->red ||
5553 surface->current_color_green != solid_color->green ||
5554 surface->current_color_blue != solid_color->blue ||
5555 surface->current_color_is_stroke != is_stroke)
5556 {
5557 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5558 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5559 return status;
5560
5561 _cairo_output_stream_printf (surface->output,
5562 "%f %f %f ",
5563 solid_color->red,
5564 solid_color->green,
5565 solid_color->blue);
5566
5567 if (is_stroke)
5568 _cairo_output_stream_printf (surface->output, "RG ");
5569 else
5570 _cairo_output_stream_printf (surface->output, "rg ");
5571
5572 surface->current_color_red = solid_color->red;
5573 surface->current_color_green = solid_color->green;
5574 surface->current_color_blue = solid_color->blue;
5575 surface->current_color_is_stroke = is_stroke;
5576 }
5577
5578 if (surface->current_pattern_is_solid_color == FALSE0 ||
5579 surface->current_color_alpha != solid_color->alpha)
5580 {
5581 status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha);
5582 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5583 return status;
5584
5585 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5586 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5587 return status;
5588
5589 _cairo_output_stream_printf (surface->output,
5590 "/a%d gs\n",
5591 alpha);
5592 surface->current_color_alpha = solid_color->alpha;
5593 }
5594
5595 surface->current_pattern_is_solid_color = TRUE1;
5596 } else {
5597 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
5598 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5599 return status;
5600
5601 status = _cairo_pdf_surface_add_pattern (surface, pattern_res);
5602 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5603 return status;
5604
5605 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5606 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5607 return status;
5608
5609 /* fill-stroke calls select_pattern twice. Don't save if the
5610 * gstate is already saved. */
5611 if (!surface->select_pattern_gstate_saved)
5612 _cairo_output_stream_printf (surface->output, "q ");
5613
5614 if (is_stroke) {
5615 _cairo_output_stream_printf (surface->output,
5616 "/Pattern CS /p%d SCN ",
5617 pattern_res.id);
5618 } else {
5619 _cairo_output_stream_printf (surface->output,
5620 "/Pattern cs /p%d scn ",
5621 pattern_res.id);
5622 }
5623 _cairo_output_stream_printf (surface->output,
5624 "/a%d gs\n",
5625 alpha);
5626 surface->select_pattern_gstate_saved = TRUE1;
5627 surface->current_pattern_is_solid_color = FALSE0;
5628 }
5629
5630 return _cairo_output_stream_get_status (surface->output);
5631}
5632
5633static cairo_int_status_t
5634_cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
5635{
5636 cairo_int_status_t status;
5637
5638 if (surface->select_pattern_gstate_saved) {
5639 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5640 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5641 return status;
5642
5643 _cairo_output_stream_printf (surface->output, "Q\n");
5644 _cairo_pdf_operators_reset (&surface->pdf_operators);
5645 surface->current_pattern_is_solid_color = FALSE0;
5646 }
5647 surface->select_pattern_gstate_saved = FALSE0;
5648
5649 return CAIRO_STATUS_SUCCESS;
5650}
5651
5652static cairo_int_status_t
5653_cairo_pdf_surface_show_page (void *abstract_surface)
5654{
5655 cairo_pdf_surface_t *surface = abstract_surface;
5656 cairo_int_status_t status;
5657
5658 status = _cairo_array_append (&surface->page_labels, &surface->current_page_label);
5659 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5660 return status;
5661
5662 surface->current_page_label = NULL((void*)0);
5663
5664 status = _cairo_pdf_interchange_end_page_content (surface);
5665 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5666 return status;
5667
5668 status = _cairo_pdf_surface_close_content_stream (surface, FALSE0);
5669 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5670 return status;
5671
5672 _cairo_surface_clipper_reset (&surface->clipper);
5673
5674 status = _cairo_pdf_surface_write_page (surface);
5675 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5676 return status;
5677
5678 _cairo_pdf_surface_clear (surface, FALSE0);
5679
5680 return CAIRO_STATUS_SUCCESS;
5681}
5682
5683static cairo_bool_t
5684_cairo_pdf_surface_get_extents (void *abstract_surface,
5685 cairo_rectangle_int_t *rectangle)
5686{
5687 cairo_pdf_surface_t *surface = abstract_surface;
5688
5689 if (surface->surface_bounded)
5690 *rectangle = surface->surface_extents;
5691
5692 return surface->surface_bounded;
5693}
5694
5695static void
5696_cairo_pdf_surface_get_font_options (void *abstract_surface,
5697 cairo_font_options_t *options)
5698{
5699 _cairo_font_options_init_default (options);
5700
5701 cairo_font_options_set_hint_style_moz_cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
5702 cairo_font_options_set_hint_metrics_moz_cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
5703 cairo_font_options_set_antialias_moz_cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
5704 _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_OFF);
5705}
5706
5707static cairo_int_status_t
5708_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
5709{
5710 cairo_pdf_page_info_t *page_info;
5711 int num_pages, i;
5712 cairo_int_status_t status;
5713
5714 status = _cairo_pdf_surface_object_begin (surface, surface->pages_resource);
5715 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5716 return status;
5717
5718 _cairo_output_stream_printf (surface->object_stream.stream,
5719 "<< /Type /Pages\n"
5720 " /Kids [ ");
5721
5722 num_pages = _cairo_array_num_elements (&surface->pages);
5723 for (i = 0; i < num_pages; i++) {
5724 page_info = _cairo_array_index (&surface->pages, i);
5725 _cairo_output_stream_printf (surface->object_stream.stream, "%d 0 R ", page_info->page_res.id);
5726 }
5727
5728 _cairo_output_stream_printf (surface->object_stream.stream, "]\n");
5729 _cairo_output_stream_printf (surface->object_stream.stream, " /Count %d\n", num_pages);
5730
5731
5732 /* TODO: Figure out which other defaults to be inherited by /Page
5733 * objects. */
5734 _cairo_output_stream_printf (surface->object_stream.stream,
5735 ">>\n");
5736 _cairo_pdf_surface_object_end (surface);
5737
5738 return CAIRO_INT_STATUS_SUCCESS;
5739}
5740
5741cairo_int_status_t
5742_cairo_utf8_to_pdf_string (const char *utf8, char **str_out)
5743{
5744 int i;
5745 int len;
5746 unsigned char *p;
5747 cairo_bool_t ascii;
5748 char *str;
5749 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
5750
5751 ascii = TRUE1;
5752 p = (unsigned char *)utf8;
5753 len = 0;
5754 while (*p) {
5755 if (*p < 32 || *p > 126) {
5756 ascii = FALSE0;
5757 break;
5758 }
5759 if (*p == '(' || *p == ')' || *p == '\\')
5760 len += 2;
5761 else
5762 len++;
5763 p++;
5764 }
5765
5766 if (ascii) {
5767 str = _cairo_malloc (len + 3)((len + 3) != 0 ? malloc(len + 3) : ((void*)0));
5768 if (str == NULL((void*)0))
5769 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5770
5771 str[0] = '(';
5772 p = (unsigned char *)utf8;
5773 i = 1;
5774 while (*p) {
5775 if (*p == '(' || *p == ')' || *p == '\\')
5776 str[i++] = '\\';
5777 str[i++] = *p;
5778 p++;
5779 }
5780 str[i++] = ')';
5781 str[i++] = 0;
5782 } else {
5783 uint16_t *utf16 = NULL((void*)0);
5784 int utf16_len = 0;
5785
5786 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
5787 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5788 return status;
5789
5790 str = _cairo_malloc (utf16_len*4 + 7)((utf16_len*4 + 7) != 0 ? malloc(utf16_len*4 + 7) : ((void*)0
))
;
5791 if (str == NULL((void*)0)) {
5792 free (utf16);
5793 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5794 }
5795
5796 strcpy (str, "<FEFF");
5797 for (i = 0; i < utf16_len; i++)
5798 snprintf (str + 4*i + 5, 5, "%04X", utf16[i]);
5799
5800 strcat (str, ">");
5801 free (utf16);
5802 }
5803 *str_out = str;
5804
5805 return status;
5806}
5807
5808static cairo_int_status_t
5809_cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t *surface,
5810 const char *utf8)
5811{
5812 uint16_t *utf16 = NULL((void*)0);
5813 int utf16_len = 0;
5814 cairo_int_status_t status;
5815 int i;
5816
5817 if (utf8 && *utf8) {
5818 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
5819 if (unlikely (status == CAIRO_INT_STATUS_INVALID_STRING)(__builtin_expect (!!(status == CAIRO_INT_STATUS_INVALID_STRING
), 0))
) {
5820 utf16 = NULL((void*)0);
5821 utf16_len = 0;
5822 } else if (unlikely (status)(__builtin_expect (!!(status), 0))) {
5823 return status;
5824 }
5825 }
5826
5827 _cairo_output_stream_printf (surface->output, "<");
5828 if (utf16 == NULL((void*)0) || utf16_len == 0) {
5829 /* According to the "ToUnicode Mapping File Tutorial"
5830 * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
5831 *
5832 * Glyphs that do not map to a Unicode code point must be
5833 * mapped to 0xfffd "REPLACEMENT CHARACTER".
5834 */
5835 _cairo_output_stream_printf (surface->output,
5836 "fffd");
5837 } else {
5838 for (i = 0; i < utf16_len; i++)
5839 _cairo_output_stream_printf (surface->output,
5840 "%04x", (int) (utf16[i]));
5841 }
5842 _cairo_output_stream_printf (surface->output, ">");
5843
5844 free (utf16);
5845
5846 return CAIRO_STATUS_SUCCESS;
5847}
5848
5849/* Bob Jenkins hash
5850 *
5851 * Public domain code from:
5852 * http://burtleburtle.net/bob/hash/doobs.html
5853 */
5854
5855#define HASH_MIX(a,b,c){ a -= b; a -= c; a ^= (c>>13); b -= c; b -= a; b ^= (a
<<8); c -= a; c -= b; c ^= (b>>13); a -= b; a -= c
; a ^= (c>>12); b -= c; b -= a; b ^= (a<<16); c -=
a; c -= b; c ^= (b>>5); a -= b; a -= c; a ^= (c>>
3); b -= c; b -= a; b ^= (a<<10); c -= a; c -= b; c ^= (
b>>15); }
\
5856{ \
5857 a -= b; a -= c; a ^= (c>>13); \
5858 b -= c; b -= a; b ^= (a<<8); \
5859 c -= a; c -= b; c ^= (b>>13); \
5860 a -= b; a -= c; a ^= (c>>12); \
5861 b -= c; b -= a; b ^= (a<<16); \
5862 c -= a; c -= b; c ^= (b>>5); \
5863 a -= b; a -= c; a ^= (c>>3); \
5864 b -= c; b -= a; b ^= (a<<10); \
5865 c -= a; c -= b; c ^= (b>>15); \
5866}
5867
5868static uint32_t
5869_hash_data (const unsigned char *data, int length, uint32_t initval)
5870{
5871 uint32_t a, b, c, len;
5872
5873 len = length;
5874 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
5875 c = initval; /* the previous hash value */
5876
5877 while (len >= 12) {
5878 a += (data[0] + ((uint32_t)data[1]<<8) + ((uint32_t)data[2]<<16) + ((uint32_t)data[3]<<24));
5879 b += (data[4] + ((uint32_t)data[5]<<8) + ((uint32_t)data[6]<<16) + ((uint32_t)data[7]<<24));
5880 c += (data[8] + ((uint32_t)data[9]<<8) + ((uint32_t)data[10]<<16)+ ((uint32_t)data[11]<<24));
5881 HASH_MIX (a,b,c){ a -= b; a -= c; a ^= (c>>13); b -= c; b -= a; b ^= (a
<<8); c -= a; c -= b; c ^= (b>>13); a -= b; a -= c
; a ^= (c>>12); b -= c; b -= a; b ^= (a<<16); c -=
a; c -= b; c ^= (b>>5); a -= b; a -= c; a ^= (c>>
3); b -= c; b -= a; b ^= (a<<10); c -= a; c -= b; c ^= (
b>>15); }
;
5882 data += 12;
5883 len -= 12;
5884 }
5885
5886 c += length;
5887 switch(len) {
5888 case 11: c+= ((uint32_t) data[10] << 24); /* fall through */
5889 case 10: c+= ((uint32_t) data[9] << 16); /* fall through */
5890 case 9 : c+= ((uint32_t) data[8] << 8); /* fall through */
5891 case 8 : b+= ((uint32_t) data[7] << 24); /* fall through */
5892 case 7 : b+= ((uint32_t) data[6] << 16); /* fall through */
5893 case 6 : b+= ((uint32_t) data[5] << 8); /* fall through */
5894 case 5 : b+= data[4]; /* fall through */
5895 case 4 : a+= ((uint32_t) data[3] << 24); /* fall through */
5896 case 3 : a+= ((uint32_t) data[2] << 16); /* fall through */
5897 case 2 : a+= ((uint32_t) data[1] << 8); /* fall through */
5898 case 1 : a+= data[0];
5899 }
5900 HASH_MIX (a,b,c){ a -= b; a -= c; a ^= (c>>13); b -= c; b -= a; b ^= (a
<<8); c -= a; c -= b; c ^= (b>>13); a -= b; a -= c
; a ^= (c>>12); b -= c; b -= a; b ^= (a<<16); c -=
a; c -= b; c ^= (b>>5); a -= b; a -= c; a ^= (c>>
3); b -= c; b -= a; b ^= (a<<10); c -= a; c -= b; c ^= (
b>>15); }
;
5901
5902 return c;
5903}
5904
5905static void
5906_create_font_subset_tag (cairo_scaled_font_subset_t *font_subset,
5907 const char *font_name,
5908 char *tag)
5909{
5910 uint32_t hash;
5911 int i;
5912
5913 hash = _hash_data ((unsigned char *) font_name, strlen(font_name), 0);
5914 hash = _hash_data ((unsigned char *) (font_subset->glyphs),
5915 font_subset->num_glyphs * sizeof(unsigned long), hash);
5916
5917 for (i = 0; i < 6; i++) {
5918 tag[i] = 'A' + (hash % 26);
5919 hash /= 26;
5920 }
5921 tag[i] = 0;
5922}
5923
5924static cairo_int_status_t
5925_cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
5926 cairo_scaled_font_subset_t *font_subset,
5927 cairo_pdf_resource_t *stream)
5928{
5929 unsigned int i, num_bfchar;
5930 cairo_int_status_t status;
5931
5932 stream->id = 0;
5933
5934 status = _cairo_pdf_surface_open_stream (surface,
5935 NULL((void*)0),
5936 surface->compress_streams,
5937 NULL((void*)0));
5938 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5939 return status;
5940
5941 _cairo_output_stream_printf (surface->output,
5942 "/CIDInit /ProcSet findresource begin\n"
5943 "12 dict begin\n"
5944 "begincmap\n"
5945 "/CIDSystemInfo\n"
5946 "<< /Registry (Adobe)\n"
5947 " /Ordering (UCS)\n"
5948 " /Supplement 0\n"
5949 ">> def\n"
5950 "/CMapName /Adobe-Identity-UCS def\n"
5951 "/CMapType 2 def\n"
5952 "1 begincodespacerange\n");
5953
5954 if (font_subset->is_composite && !font_subset->is_latin) {
5955 _cairo_output_stream_printf (surface->output,
5956 "<0000> <ffff>\n");
5957 } else {
5958 _cairo_output_stream_printf (surface->output,
5959 "<00> <ff>\n");
5960 }
5961
5962 _cairo_output_stream_printf (surface->output,
5963 "endcodespacerange\n");
5964
5965 if (font_subset->is_scaled) {
5966 /* Type 3 fonts include glyph 0 in the subset */
5967 num_bfchar = font_subset->num_glyphs;
5968
5969 /* The CMap specification has a limit of 100 characters per beginbfchar operator */
5970 _cairo_output_stream_printf (surface->output,
5971 "%d beginbfchar\n",
5972 num_bfchar > 100 ? 100 : num_bfchar);
5973
5974 for (i = 0; i < num_bfchar; i++) {
5975 if (i != 0 && i % 100 == 0) {
5976 _cairo_output_stream_printf (surface->output,
5977 "endbfchar\n"
5978 "%d beginbfchar\n",
5979 num_bfchar - i > 100 ? 100 : num_bfchar - i);
5980 }
5981 _cairo_output_stream_printf (surface->output, "<%02x> ", i);
5982 status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
5983 font_subset->utf8[i]);
5984 if (unlikely (status)(__builtin_expect (!!(status), 0)))
5985 return status;
5986
5987 _cairo_output_stream_printf (surface->output,
5988 "\n");
5989 }
5990 } else {
5991 /* Other fonts reserve glyph 0 for .notdef. Omit glyph 0 from the /ToUnicode map */
5992 num_bfchar = font_subset->num_glyphs - 1;
5993
5994 /* The CMap specification has a limit of 100 characters per beginbfchar operator */
5995 _cairo_output_stream_printf (surface->output,
5996 "%d beginbfchar\n",
5997 num_bfchar > 100 ? 100 : num_bfchar);
5998
5999 for (i = 0; i < num_bfchar; i++) {
6000 if (i != 0 && i % 100 == 0) {
6001 _cairo_output_stream_printf (surface->output,
6002 "endbfchar\n"
6003 "%d beginbfchar\n",
6004 num_bfchar - i > 100 ? 100 : num_bfchar - i);
6005 }
6006 if (font_subset->is_latin)
6007 _cairo_output_stream_printf (surface->output, "<%02x> ", font_subset->to_latin_char[i + 1]);
6008 else if (font_subset->is_composite)
6009 _cairo_output_stream_printf (surface->output, "<%04x> ", i + 1);
6010 else
6011 _cairo_output_stream_printf (surface->output, "<%02x> ", i + 1);
6012
6013 status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
6014 font_subset->utf8[i + 1]);
6015 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6016 return status;
6017
6018 _cairo_output_stream_printf (surface->output,
6019 "\n");
6020 }
6021 }
6022
6023 _cairo_output_stream_printf (surface->output,
6024 "endbfchar\n");
6025
6026 _cairo_output_stream_printf (surface->output,
6027 "endcmap\n"
6028 "CMapName currentdict /CMap defineresource pop\n"
6029 "end\n"
6030 "end\n");
6031
6032 *stream = surface->pdf_stream.self;
6033 return _cairo_pdf_surface_close_stream (surface);
6034}
6035
6036#define PDF_UNITS_PER_EM1000 1000
6037
6038static cairo_int_status_t
6039_cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
6040 cairo_scaled_font_subset_t *font_subset,
6041 cairo_cff_subset_t *subset)
6042{
6043 cairo_pdf_resource_t stream, descriptor, cidfont_dict;
6044 cairo_pdf_resource_t subset_resource, to_unicode_stream;
6045 cairo_pdf_font_t font;
6046 unsigned int i, last_glyph;
6047 cairo_int_status_t status;
6048 char tag[10];
6049
6050 _create_font_subset_tag (font_subset, subset->ps_name, tag);
6051
6052 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
6053 font_subset->font_id,
6054 font_subset->subset_id);
6055 if (subset_resource.id == 0)
6056 return CAIRO_STATUS_SUCCESS;
6057
6058 status = _cairo_pdf_surface_open_stream (surface,
6059 NULL((void*)0),
6060 TRUE1,
6061 font_subset->is_latin ?
6062 " /Subtype /Type1C\n" :
6063 " /Subtype /CIDFontType0C\n");
6064 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6065 return status;
6066
6067 stream = surface->pdf_stream.self;
6068 _cairo_output_stream_write (surface->output,
6069 subset->data, subset->data_length);
6070 status = _cairo_pdf_surface_close_stream (surface);
6071 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6072 return status;
6073
6074 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
6075 font_subset,
6076 &to_unicode_stream);
6077 if (_cairo_int_status_is_error (status)((status) != CAIRO_INT_STATUS_SUCCESS && (status) <
CAIRO_INT_STATUS_LAST_STATUS)
)
6078 return status;
6079
6080 descriptor = _cairo_pdf_surface_new_object (surface);
6081 if (descriptor.id == 0)
6082 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6083
6084 _cairo_output_stream_printf (surface->output,
6085 "%d 0 obj\n"
6086 "<< /Type /FontDescriptor\n"
6087 " /FontName /%s+%s\n",
6088 descriptor.id,
6089 tag,
6090 subset->ps_name);
6091
6092 if (subset->family_name_utf8) {
6093 char *pdf_str;
6094
6095 status = _cairo_utf8_to_pdf_string (subset->family_name_utf8, &pdf_str);
6096 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
6097 _cairo_output_stream_printf (surface->output,
6098 " /FontFamily %s\n",
6099 pdf_str);
6100 free (pdf_str);
6101 } else if (status != CAIRO_INT_STATUS_INVALID_STRING) {
6102 return status;
6103 }
6104 }
6105
6106 _cairo_output_stream_printf (surface->output,
6107 " /Flags 4\n"
6108 " /FontBBox [ %ld %ld %ld %ld ]\n"
6109 " /ItalicAngle 0\n"
6110 " /Ascent %ld\n"
6111 " /Descent %ld\n"
6112 " /CapHeight %ld\n"
6113 " /StemV 80\n"
6114 " /StemH 80\n"
6115 " /FontFile3 %u 0 R\n"
6116 ">>\n"
6117 "endobj\n",
6118 (long)(subset->x_min*PDF_UNITS_PER_EM1000),
6119 (long)(subset->y_min*PDF_UNITS_PER_EM1000),
6120 (long)(subset->x_max*PDF_UNITS_PER_EM1000),
6121 (long)(subset->y_max*PDF_UNITS_PER_EM1000),
6122 (long)(subset->ascent*PDF_UNITS_PER_EM1000),
6123 (long)(subset->descent*PDF_UNITS_PER_EM1000),
6124 (long)(subset->y_max*PDF_UNITS_PER_EM1000),
6125 stream.id);
6126
6127 if (font_subset->is_latin) {
6128 /* find last glyph used */
6129 for (i = 255; i >= 32; i--)
6130 if (font_subset->latin_to_subset_glyph_index[i] > 0)
6131 break;
6132
6133 last_glyph = i;
6134 _cairo_pdf_surface_update_object (surface, subset_resource);
6135 _cairo_output_stream_printf (surface->output,
6136 "%d 0 obj\n"
6137 "<< /Type /Font\n"
6138 " /Subtype /Type1\n"
6139 " /BaseFont /%s+%s\n"
6140 " /FirstChar 32\n"
6141 " /LastChar %d\n"
6142 " /FontDescriptor %d 0 R\n"
6143 " /Encoding /WinAnsiEncoding\n"
6144 " /Widths [",
6145 subset_resource.id,
6146 tag,
6147 subset->ps_name,
6148 last_glyph,
6149 descriptor.id);
6150
6151 for (i = 32; i < last_glyph + 1; i++) {
6152 int glyph = font_subset->latin_to_subset_glyph_index[i];
6153 if (glyph > 0) {
6154 _cairo_output_stream_printf (surface->output,
6155 " %f",
6156 (subset->widths[glyph]*PDF_UNITS_PER_EM1000));
6157 } else {
6158 _cairo_output_stream_printf (surface->output, " 0");
6159 }
6160 }
6161
6162 _cairo_output_stream_printf (surface->output,
6163 " ]\n");
6164
6165 if (to_unicode_stream.id != 0)
6166 _cairo_output_stream_printf (surface->output,
6167 " /ToUnicode %d 0 R\n",
6168 to_unicode_stream.id);
6169
6170 _cairo_output_stream_printf (surface->output,
6171 ">>\n"
6172 "endobj\n");
6173 } else {
6174 cidfont_dict = _cairo_pdf_surface_new_object (surface);
6175 if (cidfont_dict.id == 0)
6176 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6177
6178 _cairo_output_stream_printf (surface->output,
6179 "%d 0 obj\n"
6180 "<< /Type /Font\n"
6181 " /Subtype /CIDFontType0\n"
6182 " /BaseFont /%s+%s\n"
6183 " /CIDSystemInfo\n"
6184 " << /Registry (Adobe)\n"
6185 " /Ordering (Identity)\n"
6186 " /Supplement 0\n"
6187 " >>\n"
6188 " /FontDescriptor %d 0 R\n"
6189 " /W [0 [",
6190 cidfont_dict.id,
6191 tag,
6192 subset->ps_name,
6193 descriptor.id);
6194
6195 for (i = 0; i < font_subset->num_glyphs; i++)
6196 _cairo_output_stream_printf (surface->output,
6197 " %f",
6198 (subset->widths[i]*PDF_UNITS_PER_EM1000));
6199
6200 _cairo_output_stream_printf (surface->output,
6201 " ]]\n"
6202 ">>\n"
6203 "endobj\n");
6204
6205 _cairo_pdf_surface_update_object (surface, subset_resource);
6206 _cairo_output_stream_printf (surface->output,
6207 "%d 0 obj\n"
6208 "<< /Type /Font\n"
6209 " /Subtype /Type0\n"
6210 " /BaseFont /%s+%s\n"
6211 " /Encoding /Identity-H\n"
6212 " /DescendantFonts [ %d 0 R]\n",
6213 subset_resource.id,
6214 tag,
6215 subset->ps_name,
6216 cidfont_dict.id);
6217
6218 if (to_unicode_stream.id != 0)
6219 _cairo_output_stream_printf (surface->output,
6220 " /ToUnicode %d 0 R\n",
6221 to_unicode_stream.id);
6222
6223 _cairo_output_stream_printf (surface->output,
6224 ">>\n"
6225 "endobj\n");
6226 }
6227
6228 font.font_id = font_subset->font_id;
6229 font.subset_id = font_subset->subset_id;
6230 font.subset_resource = subset_resource;
6231 status = _cairo_array_append (&surface->fonts, &font);
6232
6233 return status;
6234}
6235
6236static cairo_int_status_t
6237_cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
6238 cairo_scaled_font_subset_t *font_subset)
6239{
6240 cairo_int_status_t status;
6241 cairo_cff_subset_t subset;
6242 char name[64];
6243
6244 snprintf (name, sizeof name, "CairoFont-%d-%d",
6245 font_subset->font_id, font_subset->subset_id);
6246 status = _cairo_cff_subset_init (&subset, name, font_subset);
6247 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6248 return status;
6249
6250 status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
6251
6252 _cairo_cff_subset_fini (&subset);
6253
6254 return status;
6255}
6256
6257static cairo_int_status_t
6258_cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t *surface,
6259 cairo_scaled_font_subset_t *font_subset)
6260{
6261 cairo_int_status_t status;
6262 cairo_cff_subset_t subset;
6263 char name[64];
6264
6265 /* CFF fallback subsetting does not work with 8-bit glyphs unless
6266 * they are a latin subset */
6267 if (!font_subset->is_composite && !font_subset->is_latin)
6268 return CAIRO_INT_STATUS_UNSUPPORTED;
6269
6270 snprintf (name, sizeof name, "CairoFont-%d-%d",
6271 font_subset->font_id, font_subset->subset_id);
6272 status = _cairo_cff_fallback_init (&subset, name, font_subset);
6273 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6274 return status;
6275
6276 status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
6277
6278 _cairo_cff_fallback_fini (&subset);
6279
6280 return status;
6281}
6282
6283static cairo_int_status_t
6284_cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
6285 cairo_scaled_font_subset_t *font_subset,
6286 cairo_type1_subset_t *subset)
6287{
6288 cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
6289 cairo_pdf_font_t font;
6290 cairo_int_status_t status;
6291 unsigned long length;
6292 unsigned int i, last_glyph;
6293 char tag[10];
6294
6295 _create_font_subset_tag (font_subset, subset->base_font, tag);
6296
6297 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
6298 font_subset->font_id,
6299 font_subset->subset_id);
6300 if (subset_resource.id == 0)
6301 return CAIRO_STATUS_SUCCESS;
6302
6303 length = subset->header_length + subset->data_length + subset->trailer_length;
6304 status = _cairo_pdf_surface_open_stream (surface,
6305 NULL((void*)0),
6306 TRUE1,
6307 " /Length1 %lu\n"
6308 " /Length2 %lu\n"
6309 " /Length3 %lu\n",
6310 subset->header_length,
6311 subset->data_length,
6312 subset->trailer_length);
6313 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6314 return status;
6315
6316 stream = surface->pdf_stream.self;
6317 _cairo_output_stream_write (surface->output, subset->data, length);
6318 status = _cairo_pdf_surface_close_stream (surface);
6319 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6320 return status;
6321
6322 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
6323 font_subset,
6324 &to_unicode_stream);
6325 if (_cairo_int_status_is_error (status)((status) != CAIRO_INT_STATUS_SUCCESS && (status) <
CAIRO_INT_STATUS_LAST_STATUS)
)
6326 return status;
6327
6328 last_glyph = font_subset->num_glyphs - 1;
6329 if (font_subset->is_latin) {
6330 /* find last glyph used */
6331 for (i = 255; i >= 32; i--)
6332 if (font_subset->latin_to_subset_glyph_index[i] > 0)
6333 break;
6334
6335 last_glyph = i;
6336 }
6337
6338 descriptor = _cairo_pdf_surface_new_object (surface);
6339 if (descriptor.id == 0)
6340 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6341
6342 _cairo_output_stream_printf (surface->output,
6343 "%d 0 obj\n"
6344 "<< /Type /FontDescriptor\n"
6345 " /FontName /%s+%s\n"
6346 " /Flags 4\n"
6347 " /FontBBox [ %ld %ld %ld %ld ]\n"
6348 " /ItalicAngle 0\n"
6349 " /Ascent %ld\n"
6350 " /Descent %ld\n"
6351 " /CapHeight %ld\n"
6352 " /StemV 80\n"
6353 " /StemH 80\n"
6354 " /FontFile %u 0 R\n"
6355 ">>\n"
6356 "endobj\n",
6357 descriptor.id,
6358 tag,
6359 subset->base_font,
6360 (long)(subset->x_min*PDF_UNITS_PER_EM1000),
6361 (long)(subset->y_min*PDF_UNITS_PER_EM1000),
6362 (long)(subset->x_max*PDF_UNITS_PER_EM1000),
6363 (long)(subset->y_max*PDF_UNITS_PER_EM1000),
6364 (long)(subset->ascent*PDF_UNITS_PER_EM1000),
6365 (long)(subset->descent*PDF_UNITS_PER_EM1000),
6366 (long)(subset->y_max*PDF_UNITS_PER_EM1000),
6367 stream.id);
6368
6369 _cairo_pdf_surface_update_object (surface, subset_resource);
6370 _cairo_output_stream_printf (surface->output,
6371 "%d 0 obj\n"
6372 "<< /Type /Font\n"
6373 " /Subtype /Type1\n"
6374 " /BaseFont /%s+%s\n"
6375 " /FirstChar %d\n"
6376 " /LastChar %d\n"
6377 " /FontDescriptor %d 0 R\n",
6378 subset_resource.id,
6379 tag,
6380 subset->base_font,
6381 font_subset->is_latin ? 32 : 0,
6382 last_glyph,
6383 descriptor.id);
6384
6385 if (font_subset->is_latin)
6386 _cairo_output_stream_printf (surface->output, " /Encoding /WinAnsiEncoding\n");
6387
6388 _cairo_output_stream_printf (surface->output, " /Widths [");
6389 if (font_subset->is_latin) {
6390 for (i = 32; i < last_glyph + 1; i++) {
6391 int glyph = font_subset->latin_to_subset_glyph_index[i];
6392 if (glyph > 0) {
6393 _cairo_output_stream_printf (surface->output,
6394 " %f",
6395 (subset->widths[glyph]*PDF_UNITS_PER_EM1000));
6396 } else {
6397 _cairo_output_stream_printf (surface->output, " 0");
6398 }
6399 }
6400 } else {
6401 for (i = 0; i < font_subset->num_glyphs; i++)
6402 _cairo_output_stream_printf (surface->output,
6403 " %f",
6404 (subset->widths[i]*PDF_UNITS_PER_EM1000));
6405 }
6406
6407 _cairo_output_stream_printf (surface->output,
6408 " ]\n");
6409
6410 if (to_unicode_stream.id != 0)
6411 _cairo_output_stream_printf (surface->output,
6412 " /ToUnicode %d 0 R\n",
6413 to_unicode_stream.id);
6414
6415 _cairo_output_stream_printf (surface->output,
6416 ">>\n"
6417 "endobj\n");
6418
6419 font.font_id = font_subset->font_id;
6420 font.subset_id = font_subset->subset_id;
6421 font.subset_resource = subset_resource;
6422 return _cairo_array_append (&surface->fonts, &font);
6423}
6424
6425static cairo_int_status_t
6426_cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
6427 cairo_scaled_font_subset_t *font_subset)
6428{
6429 cairo_int_status_t status;
6430 cairo_type1_subset_t subset;
6431 char name[64];
6432
6433 /* 16-bit glyphs not compatible with Type 1 fonts */
6434 if (font_subset->is_composite && !font_subset->is_latin)
6435 return CAIRO_INT_STATUS_UNSUPPORTED;
6436
6437 snprintf (name, sizeof name, "CairoFont-%d-%d",
6438 font_subset->font_id, font_subset->subset_id);
6439 status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE0);
6440 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6441 return status;
6442
6443 status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
6444
6445 _cairo_type1_subset_fini (&subset);
6446 return status;
6447}
6448
6449static cairo_int_status_t
6450_cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
6451 cairo_scaled_font_subset_t *font_subset)
6452{
6453 cairo_int_status_t status;
6454 cairo_type1_subset_t subset;
6455 char name[64];
6456
6457 /* 16-bit glyphs not compatible with Type 1 fonts */
6458 if (font_subset->is_composite && !font_subset->is_latin)
6459 return CAIRO_INT_STATUS_UNSUPPORTED;
6460
6461 snprintf (name, sizeof name, "CairoFont-%d-%d",
6462 font_subset->font_id, font_subset->subset_id);
6463 status = _cairo_type1_fallback_init_binary (&subset, name, font_subset);
6464 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6465 return status;
6466
6467 status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
6468
6469 _cairo_type1_fallback_fini (&subset);
6470 return status;
6471}
6472
6473static cairo_int_status_t
6474_cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
6475 cairo_scaled_font_subset_t *font_subset)
6476{
6477 cairo_pdf_resource_t stream, descriptor, cidfont_dict;
6478 cairo_pdf_resource_t subset_resource, to_unicode_stream;
6479 cairo_int_status_t status;
6480 cairo_pdf_font_t font;
6481 cairo_truetype_subset_t subset;
6482 unsigned int i, last_glyph;
6483 char tag[10];
6484
6485 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
6486 font_subset->font_id,
6487 font_subset->subset_id);
6488 if (subset_resource.id == 0)
6489 return CAIRO_STATUS_SUCCESS;
6490
6491 status = _cairo_truetype_subset_init_pdf (&subset, font_subset);
6492 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6493 return status;
6494
6495 _create_font_subset_tag (font_subset, subset.ps_name, tag);
6496
6497 status = _cairo_pdf_surface_open_stream (surface,
6498 NULL((void*)0),
6499 TRUE1,
6500 " /Length1 %lu\n",
6501 subset.data_length);
6502 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
6503 _cairo_truetype_subset_fini (&subset);
6504 return status;
6505 }
6506
6507 stream = surface->pdf_stream.self;
6508 _cairo_output_stream_write (surface->output,
6509 subset.data, subset.data_length);
6510 status = _cairo_pdf_surface_close_stream (surface);
6511 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
6512 _cairo_truetype_subset_fini (&subset);
6513 return status;
6514 }
6515
6516 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
6517 font_subset,
6518 &to_unicode_stream);
6519 if (_cairo_int_status_is_error (status)((status) != CAIRO_INT_STATUS_SUCCESS && (status) <
CAIRO_INT_STATUS_LAST_STATUS)
) {
6520 _cairo_truetype_subset_fini (&subset);
6521 return status;
6522 }
6523
6524 descriptor = _cairo_pdf_surface_new_object (surface);
6525 if (descriptor.id == 0) {
6526 _cairo_truetype_subset_fini (&subset);
6527 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6528 }
6529
6530 _cairo_output_stream_printf (surface->output,
6531 "%d 0 obj\n"
6532 "<< /Type /FontDescriptor\n"
6533 " /FontName /%s+%s\n",
6534 descriptor.id,
6535 tag,
6536 subset.ps_name);
6537
6538 if (subset.family_name_utf8) {
6539 char *pdf_str;
6540
6541 status = _cairo_utf8_to_pdf_string (subset.family_name_utf8, &pdf_str);
6542 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
6543 _cairo_output_stream_printf (surface->output,
6544 " /FontFamily %s\n",
6545 pdf_str);
6546 free (pdf_str);
6547 } else if (status != CAIRO_INT_STATUS_INVALID_STRING) {
6548 return status;
6549 }
6550 }
6551
6552 _cairo_output_stream_printf (surface->output,
6553 " /Flags %d\n"
6554 " /FontBBox [ %ld %ld %ld %ld ]\n"
6555 " /ItalicAngle 0\n"
6556 " /Ascent %ld\n"
6557 " /Descent %ld\n"
6558 " /CapHeight %ld\n"
6559 " /StemV 80\n"
6560 " /StemH 80\n"
6561 " /FontFile2 %u 0 R\n"
6562 ">>\n"
6563 "endobj\n",
6564 font_subset->is_latin ? 32 : 4,
6565 (long)(subset.x_min*PDF_UNITS_PER_EM1000),
6566 (long)(subset.y_min*PDF_UNITS_PER_EM1000),
6567 (long)(subset.x_max*PDF_UNITS_PER_EM1000),
6568 (long)(subset.y_max*PDF_UNITS_PER_EM1000),
6569 (long)(subset.ascent*PDF_UNITS_PER_EM1000),
6570 (long)(subset.descent*PDF_UNITS_PER_EM1000),
6571 (long)(subset.y_max*PDF_UNITS_PER_EM1000),
6572 stream.id);
6573
6574 if (font_subset->is_latin) {
6575 /* find last glyph used */
6576 for (i = 255; i >= 32; i--)
6577 if (font_subset->latin_to_subset_glyph_index[i] > 0)
6578 break;
6579
6580 last_glyph = i;
6581 _cairo_pdf_surface_update_object (surface, subset_resource);
6582 _cairo_output_stream_printf (surface->output,
6583 "%d 0 obj\n"
6584 "<< /Type /Font\n"
6585 " /Subtype /TrueType\n"
6586 " /BaseFont /%s+%s\n"
6587 " /FirstChar 32\n"
6588 " /LastChar %d\n"
6589 " /FontDescriptor %d 0 R\n"
6590 " /Encoding /WinAnsiEncoding\n"
6591 " /Widths [",
6592 subset_resource.id,
6593 tag,
6594 subset.ps_name,
6595 last_glyph,
6596 descriptor.id);
6597
6598 for (i = 32; i < last_glyph + 1; i++) {
6599 int glyph = font_subset->latin_to_subset_glyph_index[i];
6600 if (glyph > 0) {
6601 _cairo_output_stream_printf (surface->output,
6602 " %f",
6603 (subset.widths[glyph]*PDF_UNITS_PER_EM1000));
6604 } else {
6605 _cairo_output_stream_printf (surface->output, " 0");
6606 }
6607 }
6608
6609 _cairo_output_stream_printf (surface->output,
6610 " ]\n");
6611
6612 if (to_unicode_stream.id != 0)
6613 _cairo_output_stream_printf (surface->output,
6614 " /ToUnicode %d 0 R\n",
6615 to_unicode_stream.id);
6616
6617 _cairo_output_stream_printf (surface->output,
6618 ">>\n"
6619 "endobj\n");
6620 } else {
6621 cidfont_dict = _cairo_pdf_surface_new_object (surface);
6622 if (cidfont_dict.id == 0) {
6623 _cairo_truetype_subset_fini (&subset);
6624 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6625 }
6626
6627 _cairo_output_stream_printf (surface->output,
6628 "%d 0 obj\n"
6629 "<< /Type /Font\n"
6630 " /Subtype /CIDFontType2\n"
6631 " /BaseFont /%s+%s\n"
6632 " /CIDSystemInfo\n"
6633 " << /Registry (Adobe)\n"
6634 " /Ordering (Identity)\n"
6635 " /Supplement 0\n"
6636 " >>\n"
6637 " /FontDescriptor %d 0 R\n"
6638 " /W [0 [",
6639 cidfont_dict.id,
6640 tag,
6641 subset.ps_name,
6642 descriptor.id);
6643
6644 for (i = 0; i < font_subset->num_glyphs; i++)
6645 _cairo_output_stream_printf (surface->output,
6646 " %f",
6647 (subset.widths[i]*PDF_UNITS_PER_EM1000));
6648
6649 _cairo_output_stream_printf (surface->output,
6650 " ]]\n"
6651 ">>\n"
6652 "endobj\n");
6653
6654 _cairo_pdf_surface_update_object (surface, subset_resource);
6655 _cairo_output_stream_printf (surface->output,
6656 "%d 0 obj\n"
6657 "<< /Type /Font\n"
6658 " /Subtype /Type0\n"
6659 " /BaseFont /%s+%s\n"
6660 " /Encoding /Identity-H\n"
6661 " /DescendantFonts [ %d 0 R]\n",
6662 subset_resource.id,
6663 tag,
6664 subset.ps_name,
6665 cidfont_dict.id);
6666
6667 if (to_unicode_stream.id != 0)
6668 _cairo_output_stream_printf (surface->output,
6669 " /ToUnicode %d 0 R\n",
6670 to_unicode_stream.id);
6671
6672 _cairo_output_stream_printf (surface->output,
6673 ">>\n"
6674 "endobj\n");
6675 }
6676
6677 font.font_id = font_subset->font_id;
6678 font.subset_id = font_subset->subset_id;
6679 font.subset_resource = subset_resource;
6680 status = _cairo_array_append (&surface->fonts, &font);
6681
6682 _cairo_truetype_subset_fini (&subset);
6683
6684 return status;
6685}
6686
6687static cairo_int_status_t
6688_cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
6689 cairo_output_stream_t *stream)
6690{
6691 uint8_t *byte, output_byte;
6692 int row, col, num_cols;
6693
6694 /* The only image type supported by Type 3 fonts are 1-bit image
6695 * masks */
6696 assert (image->format == CAIRO_FORMAT_A1)((void) sizeof ((image->format == CAIRO_FORMAT_A1) ? 1 : 0
), __extension__ ({ if (image->format == CAIRO_FORMAT_A1) ;
else __assert_fail ("image->format == CAIRO_FORMAT_A1", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 6696, __extension__ __PRETTY_FUNCTION__); }))
;
6697
6698 _cairo_output_stream_printf (stream,
6699 "BI\n"
6700 "/IM true\n"
6701 "/W %d\n"
6702 "/H %d\n"
6703 "/BPC 1\n"
6704 "/D [1 0]\n",
6705 image->width,
6706 image->height);
6707
6708 _cairo_output_stream_printf (stream,
6709 "ID ");
6710
6711 num_cols = (image->width + 7) / 8;
6712 for (row = 0; row < image->height; row++) {
6713 byte = image->data + row * image->stride;
6714 for (col = 0; col < num_cols; col++) {
6715 output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte)((((*byte) * 0x0802LU & 0x22110LU) | ((*byte) * 0x8020LU &
0x88440LU)) * 0x10101LU >> 16)
;
6716 _cairo_output_stream_write (stream, &output_byte, 1);
6717 byte++;
6718 }
6719 }
6720
6721 _cairo_output_stream_printf (stream,
6722 "\nEI\n");
6723
6724 return _cairo_output_stream_get_status (stream);
6725}
6726
6727static cairo_int_status_t
6728cairo_pdf_surface_emit_color_glyph (cairo_pdf_surface_t *surface,
6729 cairo_scaled_font_t *scaled_font,
6730 unsigned long glyph_index,
6731 cairo_box_t *bbox,
6732 double *width)
6733{
6734 cairo_rectangle_int_t extents;
6735 cairo_scaled_glyph_t *scaled_glyph;
6736 cairo_matrix_t mat;
6737 cairo_int_status_t status;
6738 double x_advance, y_advance;
6739 cairo_matrix_t font_matrix_inverse;
6740 cairo_surface_t *analysis;
6741 cairo_rectangle_int_t old_surface_extents;
6742 cairo_bool_t old_surface_bounded;
6743 cairo_paginated_mode_t old_paginated_mode;
6744 cairo_surface_t *glyph_surface = NULL((void*)0);
6745 unsigned int regions_id = 0;
6746 cairo_surface_pattern_t surface_pattern;
6747
6748 _cairo_scaled_font_freeze_cache (scaled_font);
6749 status = _cairo_scaled_glyph_lookup (scaled_font,
6750 glyph_index,
6751 CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
6752 NULL((void*)0), /* foreground color */
6753 &scaled_glyph);
6754 if (status == CAIRO_INT_STATUS_SUCCESS)
6755 glyph_surface = cairo_surface_reference_moz_cairo_surface_reference (scaled_glyph->recording_surface);
6756
6757 _cairo_scaled_font_thaw_cache (scaled_font);
6758 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6759 return status;
6760
6761 analysis = _cairo_analysis_surface_create (&surface->base, TRUE1);
6762 if (unlikely (analysis->status)(__builtin_expect (!!(analysis->status), 0))) {
6763 status = _cairo_surface_set_error (&surface->base, analysis->status);
6764 goto cleanup;
6765 }
6766
6767 extents.x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
6768 extents.y = _cairo_fixed_to_double (scaled_glyph->bbox.p1.y);
6769 extents.width = _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - extents.x;
6770 extents.height = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y) - extents.y;
6771
6772 old_surface_extents = surface->surface_extents;
6773 old_surface_bounded = surface->surface_bounded;
6774 old_paginated_mode = surface->paginated_mode;
6775 surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
6776 surface->type3_replay = TRUE1;
6777 surface->surface_extents = extents;
6778 surface->surface_bounded = TRUE1;
6779
6780 status = _cairo_recording_surface_region_array_attach (glyph_surface, &regions_id);
6781 if (status)
6782 goto cleanup;
6783
6784 status = _cairo_recording_surface_replay_and_create_regions (glyph_surface, regions_id,
6785 NULL((void*)0), analysis, TRUE1, FALSE0);
6786 if (status)
6787 goto cleanup;
6788
6789 surface->surface_extents = old_surface_extents;
6790 surface->surface_bounded = old_surface_bounded;
6791 surface->paginated_mode = old_paginated_mode;
6792 surface->type3_replay = FALSE0;
6793
6794 if (status == CAIRO_INT_STATUS_SUCCESS &&
6795 _cairo_analysis_surface_has_unsupported (analysis))
6796 {
6797 status = CAIRO_INT_STATUS_UNSUPPORTED;
6798 }
6799
6800 cairo_surface_destroy_moz_cairo_surface_destroy (analysis);
6801 if (status)
6802 goto cleanup;
6803
6804 _cairo_pattern_init_for_surface (&surface_pattern, glyph_surface);
6805 surface_pattern.region_array_id = regions_id;
6806
6807 cairo_matrix_init_identity_moz_cairo_matrix_init_identity (&mat);
6808 cairo_matrix_multiply_moz_cairo_matrix_multiply (&mat, &mat, &scaled_font->scale_inverse);
6809
6810 /* transform glyph extents to operation space */
6811 cairo_box_t box;
6812 _cairo_box_from_rectangle (&box, &extents);
6813 _cairo_matrix_transform_bounding_box_fixed (&mat, &box, NULL((void*)0));
6814 _cairo_box_round_to_rectangle (&box, &extents);
6815
6816 status = cairo_matrix_invert_moz_cairo_matrix_invert (&mat);
6817 if (status) {
6818 status = CAIRO_INT_STATUS_UNSUPPORTED;
6819 goto cleanup;
6820 }
6821
6822 cairo_pattern_set_matrix_moz_cairo_pattern_set_matrix (&surface_pattern.base, &mat);
6823
6824 x_advance = scaled_glyph->metrics.x_advance;
6825 y_advance = scaled_glyph->metrics.y_advance;
6826 font_matrix_inverse = scaled_font->font_matrix;
6827 status = cairo_matrix_invert_moz_cairo_matrix_invert (&font_matrix_inverse);
6828 if (status) {
6829 status = CAIRO_INT_STATUS_UNSUPPORTED;
6830 goto cleanup;
6831 }
6832
6833 cairo_matrix_transform_distance_moz_cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance);
6834 *width = x_advance;
6835
6836 *bbox = scaled_glyph->bbox;
6837 _cairo_matrix_transform_bounding_box_fixed (&scaled_font->scale_inverse,
6838 bbox, NULL((void*)0));
6839
6840 _cairo_output_stream_printf (surface->output,
6841 "%f 0 d0\n",
6842 x_advance);
6843
6844 _cairo_pdf_surface_paint_surface_pattern (surface,
6845 CAIRO_OPERATOR_OVER,
6846 &surface_pattern.base,
6847 CAIRO_ANALYSIS_SOURCE_NONE,
6848 &extents,
6849 1.0, /* alpha */
6850 NULL((void*)0), /* smask_res */
6851 FALSE0); /* mask */
6852
6853 cleanup:
6854 cairo_surface_destroy_moz_cairo_surface_destroy (glyph_surface);
6855
6856 return status;
6857}
6858
6859static cairo_int_status_t
6860cairo_pdf_surface_emit_color_glyph_image (cairo_pdf_surface_t *surface,
6861 cairo_scaled_font_t *scaled_font,
6862 unsigned long glyph_index,
6863 cairo_box_t *bbox,
6864 double *width)
6865{
6866 cairo_rectangle_int_t extents;
6867 cairo_pattern_t *image_pattern;
6868 cairo_scaled_glyph_t *scaled_glyph;
6869 cairo_matrix_t mat;
6870 cairo_int_status_t status, status2;
6871 double x_advance, y_advance;
6872 cairo_matrix_t font_matrix_inverse;
6873
6874 _cairo_scaled_font_freeze_cache (scaled_font);
6875 status = _cairo_scaled_glyph_lookup (scaled_font,
6876 glyph_index,
6877 CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
6878 NULL((void*)0), /* foreground color */
6879 &scaled_glyph);
6880 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6881 goto FAIL;
6882
6883 extents.x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
6884 extents.y = _cairo_fixed_to_double (scaled_glyph->bbox.p1.y);
6885 extents.width = _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - extents.x;
6886 extents.height = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y) - extents.y;
6887
6888 image_pattern = cairo_pattern_create_for_surface_moz_cairo_pattern_create_for_surface (&scaled_glyph->color_surface->base);
6889
6890 cairo_matrix_init_translate_moz_cairo_matrix_init_translate (&mat, extents.x, extents.y);
6891 cairo_matrix_multiply_moz_cairo_matrix_multiply (&mat, &mat, &scaled_font->scale_inverse);
6892 status2 = cairo_matrix_invert_moz_cairo_matrix_invert (&mat);
6893 cairo_pattern_set_matrix_moz_cairo_pattern_set_matrix (image_pattern, &mat);
6894
6895 x_advance = scaled_glyph->metrics.x_advance;
6896 y_advance = scaled_glyph->metrics.y_advance;
6897 font_matrix_inverse = scaled_font->font_matrix;
6898 status2 = cairo_matrix_invert_moz_cairo_matrix_invert (&font_matrix_inverse);
6899
6900 /* The invertability of font_matrix is tested in
6901 * pdf_operators_show_glyphs before any glyphs are mapped to the
6902 * subset. */
6903 assert (status2 == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status2 == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0
), __extension__ ({ if (status2 == CAIRO_INT_STATUS_SUCCESS) ;
else __assert_fail ("status2 == CAIRO_INT_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 6903, __extension__ __PRETTY_FUNCTION__); }))
;
6904
6905 cairo_matrix_transform_distance_moz_cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance);
6906 *width = x_advance;
6907
6908 *bbox = scaled_glyph->bbox;
6909 _cairo_matrix_transform_bounding_box_fixed (&scaled_font->scale_inverse,
6910 bbox, NULL((void*)0));
6911
6912 _cairo_output_stream_printf (surface->output,
6913 "%f 0 d0\n",
6914 x_advance);
6915
6916 _cairo_pdf_surface_paint_surface_pattern (surface,
6917 CAIRO_OPERATOR_OVER,
6918 image_pattern,
6919 CAIRO_ANALYSIS_SOURCE_NONE,
6920 &extents,
6921 1.0, /* alpha */
6922 NULL((void*)0), /* smask_res */
6923 FALSE0); /* mask */
6924 cairo_pattern_destroy_moz_cairo_pattern_destroy (image_pattern);
6925 FAIL:
6926 _cairo_scaled_font_thaw_cache (scaled_font);
6927
6928 return status;
6929}
6930
6931static cairo_int_status_t
6932_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
6933 cairo_scaled_font_subset_t *font_subset)
6934{
6935 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
6936 cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
6937 cairo_pdf_font_t font;
6938 double *widths;
6939 unsigned int i;
6940 cairo_box_t font_bbox = {{0,0},{0,0}};
6941 cairo_box_t bbox = {{0,0},{0,0}};
6942 cairo_surface_t *type3_surface;
6943
6944 if (font_subset->num_glyphs == 0)
6945 return CAIRO_STATUS_SUCCESS;
6946
6947 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
6948 font_subset->font_id,
6949 font_subset->subset_id);
6950 if (subset_resource.id == 0)
6951 return CAIRO_STATUS_SUCCESS;
6952
6953 glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
6954 if (unlikely (glyphs == NULL)(__builtin_expect (!!(glyphs == ((void*)0)), 0)))
6955 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6956
6957 widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
6958 if (unlikely (widths == NULL)(__builtin_expect (!!(widths == ((void*)0)), 0))) {
6959 free (glyphs);
6960 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6961 }
6962
6963 _cairo_pdf_group_resources_clear (&surface->resources);
6964 type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
6965 NULL((void*)0),
6966 _cairo_pdf_emit_imagemask,
6967 surface->font_subsets,
6968 FALSE0);
6969 if (unlikely (type3_surface->status)(__builtin_expect (!!(type3_surface->status), 0))) {
6970 free (glyphs);
6971 free (widths);
6972 return type3_surface->status;
6973 }
6974
6975 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
6976 _cairo_pdf_surface_add_font,
6977 surface);
6978
6979 for (i = 0; i < font_subset->num_glyphs; i++) {
6980 status = _cairo_pdf_surface_open_stream (surface,
6981 NULL((void*)0),
6982 surface->compress_streams,
6983 NULL((void*)0));
6984 if (unlikely (status)(__builtin_expect (!!(status), 0)))
6985 break;
6986
6987 glyphs[i] = surface->pdf_stream.self;
6988 status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
6989 surface->output,
6990 font_subset->glyphs[i],
6991 &bbox,
6992 &widths[i]);
6993 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
6994 status = cairo_pdf_surface_emit_color_glyph (surface,
6995 font_subset->scaled_font,
6996 font_subset->glyphs[i],
6997 &bbox,
6998 &widths[i]);
6999 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
7000 status = cairo_pdf_surface_emit_color_glyph_image (surface,
7001 font_subset->scaled_font,
7002 font_subset->glyphs[i],
7003 &bbox,
7004 &widths[i]);
7005 }
7006 }
7007 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7008 break;
7009
7010 status = _cairo_pdf_surface_close_stream (surface);
7011 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7012 break;
7013
7014 if (i == 0) {
7015 font_bbox.p1.x = bbox.p1.x;
7016 font_bbox.p1.y = bbox.p1.y;
7017 font_bbox.p2.x = bbox.p2.x;
7018 font_bbox.p2.y = bbox.p2.y;
7019 } else {
7020 if (bbox.p1.x < font_bbox.p1.x)
7021 font_bbox.p1.x = bbox.p1.x;
7022 if (bbox.p1.y < font_bbox.p1.y)
7023 font_bbox.p1.y = bbox.p1.y;
7024 if (bbox.p2.x > font_bbox.p2.x)
7025 font_bbox.p2.x = bbox.p2.x;
7026 if (bbox.p2.y > font_bbox.p2.y)
7027 font_bbox.p2.y = bbox.p2.y;
7028 }
7029 }
7030 cairo_surface_destroy_moz_cairo_surface_destroy (type3_surface);
7031 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
7032 free (glyphs);
7033 free (widths);
7034 return status;
7035 }
7036
7037 encoding = _cairo_pdf_surface_new_object (surface);
7038 if (encoding.id == 0) {
7039 free (glyphs);
7040 free (widths);
7041 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
7042 }
7043
7044 _cairo_output_stream_printf (surface->output,
7045 "%d 0 obj\n"
7046 "<< /Type /Encoding\n"
7047 " /Differences [0", encoding.id);
7048 for (i = 0; i < font_subset->num_glyphs; i++)
7049 _cairo_output_stream_printf (surface->output,
7050 " /%d", i);
7051 _cairo_output_stream_printf (surface->output,
7052 "]\n"
7053 ">>\n"
7054 "endobj\n");
7055
7056 char_procs = _cairo_pdf_surface_new_object (surface);
7057 if (char_procs.id == 0) {
7058 free (glyphs);
7059 free (widths);
7060 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
7061 }
7062
7063 _cairo_output_stream_printf (surface->output,
7064 "%d 0 obj\n"
7065 "<<\n", char_procs.id);
7066 for (i = 0; i < font_subset->num_glyphs; i++)
7067 _cairo_output_stream_printf (surface->output,
7068 " /%d %d 0 R\n",
7069 i, glyphs[i].id);
7070 _cairo_output_stream_printf (surface->output,
7071 ">>\n"
7072 "endobj\n");
7073
7074 free (glyphs);
7075
7076 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
7077 font_subset,
7078 &to_unicode_stream);
7079 if (_cairo_int_status_is_error (status)((status) != CAIRO_INT_STATUS_SUCCESS && (status) <
CAIRO_INT_STATUS_LAST_STATUS)
) {
7080 free (widths);
7081 return status;
7082 }
7083
7084 _cairo_pdf_surface_update_object (surface, subset_resource);
7085 _cairo_output_stream_printf (surface->output,
7086 "%d 0 obj\n"
7087 "<< /Type /Font\n"
7088 " /Subtype /Type3\n"
7089 " /FontBBox [%f %f %f %f]\n"
7090 " /FontMatrix [ 1 0 0 -1 0 0 ]\n"
7091 " /Encoding %d 0 R\n"
7092 " /CharProcs %d 0 R\n"
7093 " /FirstChar 0\n"
7094 " /LastChar %d\n",
7095 subset_resource.id,
7096 _cairo_fixed_to_double (font_bbox.p1.x),
7097 _cairo_fixed_to_double (font_bbox.p1.y),
7098 _cairo_fixed_to_double (font_bbox.p2.x),
7099 _cairo_fixed_to_double (font_bbox.p2.y),
7100 encoding.id,
7101 char_procs.id,
7102 font_subset->num_glyphs - 1);
7103
7104 _cairo_output_stream_printf (surface->output,
7105 " /Widths [");
7106 for (i = 0; i < font_subset->num_glyphs; i++)
7107 _cairo_output_stream_printf (surface->output, " %f", widths[i]);
7108 _cairo_output_stream_printf (surface->output,
7109 "]\n");
7110 free (widths);
7111
7112 _cairo_output_stream_printf (surface->output,
7113 " /Resources\n");
7114 _cairo_pdf_surface_emit_group_resources (surface, &surface->resources, FALSE0);
7115
7116 if (to_unicode_stream.id != 0)
7117 _cairo_output_stream_printf (surface->output,
7118 " /ToUnicode %d 0 R\n",
7119 to_unicode_stream.id);
7120
7121 _cairo_output_stream_printf (surface->output,
7122 ">>\n"
7123 "endobj\n");
7124
7125 font.font_id = font_subset->font_id;
7126 font.subset_id = font_subset->subset_id;
7127 font.subset_resource = subset_resource;
7128 return _cairo_array_append (&surface->fonts, &font);
7129}
7130
7131static cairo_int_status_t
7132_cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
7133 void *closure)
7134{
7135 cairo_pdf_surface_t *surface = closure;
7136 cairo_int_status_t status;
7137
7138 status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
7139 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
7140 return status;
7141
7142 status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
7143 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
7144 return status;
7145
7146 status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
7147 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
7148 return status;
7149
7150 status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
7151 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
7152 return status;
7153
7154 status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
7155 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
7156 return status;
7157
7158 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 7158, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
7159 return CAIRO_INT_STATUS_SUCCESS;
7160}
7161
7162static cairo_int_status_t
7163_cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
7164 void *closure)
7165{
7166 cairo_pdf_surface_t *surface = closure;
7167 cairo_int_status_t status;
7168
7169 status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
7170 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
7171 return status;
7172
7173 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 7173, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
7174 return CAIRO_INT_STATUS_SUCCESS;
7175}
7176
7177static cairo_int_status_t
7178_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
7179{
7180 cairo_int_status_t status;
7181
7182 status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
7183 _cairo_pdf_surface_emit_unscaled_font_subset,
7184 surface);
7185 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7186 goto BAIL;
7187
7188 status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
7189 _cairo_pdf_surface_emit_scaled_font_subset,
7190 surface);
7191
7192BAIL:
7193 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
7194 surface->font_subsets = NULL((void*)0);
7195
7196 return status;
7197}
7198
7199static cairo_int_status_t
7200_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface,
7201 cairo_pdf_resource_t catalog)
7202{
7203 cairo_status_t status;
7204
7205 status = _cairo_pdf_surface_object_begin (surface, catalog);
7206 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7207 return status;
7208
7209 _cairo_output_stream_printf (surface->object_stream.stream,
7210 "<< /Type /Catalog\n"
7211 " /Pages %d 0 R\n",
7212 surface->pages_resource.id);
7213
7214 if (surface->struct_tree_root.id != 0) {
7215 _cairo_output_stream_printf (surface->object_stream.stream,
7216 " /StructTreeRoot %d 0 R\n",
7217 surface->struct_tree_root.id);
7218 if (surface->tagged) {
7219 _cairo_output_stream_printf (surface->object_stream.stream,
7220 " /MarkInfo << /Marked true >>\n");
7221 }
7222 }
7223
7224 if (surface->outlines_dict_res.id != 0) {
7225 _cairo_output_stream_printf (surface->object_stream.stream,
7226 " /Outlines %d 0 R\n",
7227 surface->outlines_dict_res.id);
7228 }
7229
7230 if (surface->page_labels_res.id != 0) {
7231 _cairo_output_stream_printf (surface->object_stream.stream,
7232 " /PageLabels %d 0 R\n",
7233 surface->page_labels_res.id);
7234 }
7235
7236 if (surface->names_dict_res.id != 0) {
7237 _cairo_output_stream_printf (surface->object_stream.stream,
7238 " /Names %d 0 R\n",
7239 surface->names_dict_res.id);
7240 }
7241
7242 _cairo_output_stream_printf (surface->object_stream.stream,
7243 ">>\n");
7244 _cairo_pdf_surface_object_end (surface);
7245
7246 return status;
7247}
7248
7249static long long
7250_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
7251{
7252 cairo_pdf_object_t *object;
7253 int num_objects, i;
7254 long long offset;
7255
7256 num_objects = _cairo_array_num_elements (&surface->objects);
7257
7258 offset = _cairo_output_stream_get_position (surface->output);
7259 _cairo_output_stream_printf (surface->output,
7260 "xref\n"
7261 "%d %d\n",
7262 0, num_objects + 1);
7263
7264 _cairo_output_stream_printf (surface->output,
7265 "0000000000 65535 f \n");
7266 for (i = 0; i < num_objects; i++) {
7267 object = _cairo_array_index (&surface->objects, i);
7268 _cairo_output_stream_printf (surface->output,
7269 "%010lld 00000 n \n", object->u.offset);
7270 }
7271
7272 return offset;
7273}
7274
7275static void
7276_cairo_write_xref_stream_entry (cairo_output_stream_t *stream,
7277 int id,
7278 int type,
7279 int field2_size,
7280 long long field2,
7281 int field3,
7282 cairo_bool_t write_as_comments)
7283{
7284 char buf[20];
7285 int i;
7286
7287 if (write_as_comments) {
7288 _cairo_output_stream_printf (stream, "%% %5d %2d %10lld %d\n", id, type, field2, field3);
7289 } else {
7290 /* Each field is big endian */
7291 buf[0] = type; /* field 1 */
7292 for (i = field2_size - 1; i >= 0; i--) {
7293 buf[i + 1] = field2 & 0xff;
7294 field2 >>= 8;
7295 }
7296 buf[field2_size + 1] = field3 >> 8;
7297 buf[field2_size + 2] = field3 & 0xff;
7298 _cairo_output_stream_write (stream, buf, field2_size + 3);
7299 }
7300}
7301
7302static void
7303_cairo_write_xref_stream_entries (cairo_pdf_surface_t *surface,
7304 cairo_output_stream_t *stream,
7305 int field2_size,
7306 cairo_bool_t write_as_comments)
7307{
7308 cairo_pdf_object_t *object;
7309 int num_objects, i;
7310
7311 /* PDF requires this to be first entry */
7312 _cairo_write_xref_stream_entry (stream,
7313 0,
7314 PDF_OBJECT_FREE,
7315 field2_size,
7316 0, /* next free object number */
7317 0xffff, /* next generation number */
7318 write_as_comments);
7319
7320 num_objects = _cairo_array_num_elements (&surface->objects);
7321 for (i = 0; i < num_objects; i++) {
7322 object = _cairo_array_index (&surface->objects, i);
7323 if (object->type == PDF_OBJECT_UNCOMPRESSED) {
7324 _cairo_write_xref_stream_entry (stream,
7325 i + 1,
7326 object->type,
7327 field2_size,
7328 object->u.offset,
7329 0, /* generation number */
7330 write_as_comments);
7331 } else if (object->type == PDF_OBJECT_COMPRESSED) {
7332 _cairo_write_xref_stream_entry (stream,
7333 i + 1,
7334 object->type,
7335 field2_size,
7336 object->u.compressed_obj.xref_stream.id,
7337 object->u.compressed_obj.index,
7338 write_as_comments);
7339 } else {
7340 _cairo_write_xref_stream_entry (stream,
7341 i + 1,
7342 PDF_OBJECT_FREE,
7343 field2_size,
7344 0,
7345 0xffff,
7346 write_as_comments);
7347 }
7348 }
7349}
7350
7351static cairo_int_status_t
7352_cairo_pdf_surface_write_xref_stream (cairo_pdf_surface_t *surface,
7353 cairo_pdf_resource_t xref_res,
7354 cairo_pdf_resource_t root_res,
7355 cairo_pdf_resource_t info_res,
7356 long long *xref_offset)
7357{
7358 cairo_output_stream_t *mem_stream;
7359 cairo_output_stream_t *xref_stream;
7360 long long offset;
7361 int offset_bytes;
7362 cairo_status_t status;
7363
7364 *xref_offset = _cairo_output_stream_get_position (surface->output);
7365
7366 /* Find the minimum number of bytes required to represent offsets in the generated file (up to this point). */
7367 offset_bytes = 0;
7368 offset = *xref_offset;
7369 while (offset > 0) {
7370 offset >>= 8;
7371 offset_bytes++;
7372 }
7373
7374 mem_stream = _cairo_memory_stream_create ();
7375 xref_stream = _cairo_deflate_stream_create (mem_stream);
7376 _cairo_write_xref_stream_entries (surface, xref_stream, offset_bytes, FALSE0);
7377
7378 status = _cairo_output_stream_destroy (xref_stream);
7379 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7380 return status;
7381
7382 _cairo_pdf_surface_update_object (surface, xref_res);
7383 _cairo_output_stream_printf (surface->output,
7384 "%d 0 obj\n"
7385 "<< /Type /XRef\n"
7386 " /Length %d\n"
7387 " /Filter /FlateDecode\n"
7388 " /Size %d\n"
7389 " /W [1 %d 2]\n"
7390 " /Root %d 0 R\n"
7391 " /Info %d 0 R\n"
7392 ">>\n",
7393 xref_res.id,
7394 _cairo_memory_stream_length (mem_stream),
7395 surface->next_available_resource.id,
7396 offset_bytes,
7397 root_res.id,
7398 info_res.id);
7399
7400 if (!surface->compress_streams) {
7401 /* Adobe Reader requires xref streams to be flate encoded (PDF
7402 * Reference 1.7, implementation note 20). This means
7403 * compression must always be enabled on this stream. To
7404 * facilitate debugging when compress_stream is disabled, emit
7405 * a human readable format of the xref stream as PDF comments.
7406 */
7407 _cairo_output_stream_printf (surface->output,
7408 "%% id type offset/obj gen/index\n");
7409 _cairo_write_xref_stream_entries (surface, surface->output, offset_bytes, TRUE1);
7410 }
7411
7412 _cairo_output_stream_printf (surface->output,
7413 "stream\n");
7414 _cairo_memory_stream_copy (mem_stream, surface->output);
7415 status = _cairo_output_stream_destroy (mem_stream);
7416 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7417 return status;
7418
7419 _cairo_output_stream_printf (surface->output,
7420 "\n"
7421 "endstream\n"
7422 "endobj\n");
7423
7424 return _cairo_output_stream_get_status (surface->output);
7425}
7426
7427static cairo_int_status_t
7428_cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
7429 cairo_pdf_smask_group_t *group)
7430{
7431 cairo_pdf_resource_t mask_group;
7432 cairo_pdf_resource_t smask;
7433 cairo_pdf_smask_group_t *smask_group;
7434 cairo_pdf_resource_t pattern_res, gstate_res;
7435 cairo_int_status_t status;
7436 cairo_box_double_t bbox;
7437
7438 /* Create mask group */
7439 _get_bbox_from_extents (&group->extents, &bbox);
7440 status = _cairo_pdf_surface_open_group (surface, &bbox, NULL((void*)0));
7441 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7442 return status;
7443
7444 if (_can_paint_pattern (group->mask)) {
7445 _cairo_output_stream_printf (surface->output, "q\n");
7446 status = _cairo_pdf_surface_paint_pattern (surface,
7447 CAIRO_OPERATOR_OVER,
7448 group->mask,
7449 CAIRO_ANALYSIS_MASK_MASK,
7450 &group->extents,
7451 1.0, /* alpha */
7452 FALSE0); /* mask */
7453 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7454 return status;
7455
7456 _cairo_output_stream_printf (surface->output, "Q\n");
7457 } else {
7458 pattern_res.id = 0;
7459 gstate_res.id = 0;
7460 status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask,
7461 CAIRO_OPERATOR_OVER,
7462 CAIRO_ANALYSIS_MASK_MASK,
7463 NULL((void*)0),
7464 &pattern_res, &gstate_res);
7465 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7466 return status;
7467
7468 if (gstate_res.id != 0) {
7469 smask_group = _cairo_pdf_surface_create_smask_group (surface, &group->extents);
7470 if (unlikely (smask_group == NULL)(__builtin_expect (!!(smask_group == ((void*)0)), 0)))
7471 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
7472
7473 smask_group->width = group->width;
7474 smask_group->height = group->height;
7475 smask_group->operation = PDF_PAINT;
7476 smask_group->source = cairo_pattern_reference_moz_cairo_pattern_reference (group->mask);
7477 smask_group->source_res = pattern_res;
7478 status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
7479 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
7480 _cairo_pdf_smask_group_destroy (smask_group);
7481 return status;
7482 }
7483
7484 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
7485 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7486 return status;
7487
7488 status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
7489 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7490 return status;
7491
7492 _cairo_output_stream_printf (surface->output,
7493 "q /s%d gs /x%d Do Q\n",
7494 gstate_res.id,
7495 smask_group->group_res.id);
7496 } else {
7497 status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE0);
7498 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7499 return status;
7500
7501 _cairo_output_stream_printf (surface->output,
7502 "%f %f %f %f re f\n",
7503 bbox.p1.x,
7504 bbox.p1.y,
7505 bbox.p2.x - bbox.p1.x,
7506 bbox.p2.y - bbox.p1.y);
7507
7508 status = _cairo_pdf_surface_unselect_pattern (surface);
7509 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7510 return status;
7511 }
7512 }
7513
7514 status = _cairo_pdf_surface_close_group (surface, &mask_group);
7515 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7516 return status;
7517
7518 /* Create source group */
7519 status = _cairo_pdf_surface_open_group (surface, &bbox, &group->source_res);
7520 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7521 return status;
7522
7523 if (_can_paint_pattern (group->source)) {
7524 _cairo_output_stream_printf (surface->output, "q\n");
7525 status = _cairo_pdf_surface_paint_pattern (surface,
7526 CAIRO_OPERATOR_OVER,
7527 group->source,
7528 CAIRO_ANALYSIS_MASK_MASK,
7529 &group->extents,
7530 1.0, /* alpha */
7531 FALSE0); /* mask */
7532 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7533 return status;
7534
7535 _cairo_output_stream_printf (surface->output, "Q\n");
7536 } else {
7537 pattern_res.id = 0;
7538 gstate_res.id = 0;
7539 status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source,
7540 CAIRO_OPERATOR_OVER,
7541 CAIRO_ANALYSIS_MASK_MASK,
7542 NULL((void*)0),
7543 &pattern_res, &gstate_res);
7544 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7545 return status;
7546
7547 if (gstate_res.id != 0) {
7548 smask_group = _cairo_pdf_surface_create_smask_group (surface, &group->extents);
7549 if (unlikely (smask_group == NULL)(__builtin_expect (!!(smask_group == ((void*)0)), 0)))
7550 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
7551
7552 smask_group->operation = PDF_PAINT;
7553 smask_group->source = cairo_pattern_reference_moz_cairo_pattern_reference (group->source);
7554 smask_group->source_res = pattern_res;
7555 status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
7556 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
7557 _cairo_pdf_smask_group_destroy (smask_group);
7558 return status;
7559 }
7560
7561 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
7562 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7563 return status;
7564
7565 status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
7566 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7567 return status;
7568
7569 _cairo_output_stream_printf (surface->output,
7570 "q /s%d gs /x%d Do Q\n",
7571 gstate_res.id,
7572 smask_group->group_res.id);
7573 } else {
7574 status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE0);
7575 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7576 return status;
7577
7578 _cairo_output_stream_printf (surface->output,
7579 "%f %f %f %f re f\n",
7580 bbox.p1.x,
7581 bbox.p1.y,
7582 bbox.p2.x - bbox.p1.x,
7583 bbox.p2.y - bbox.p1.y);
7584
7585 status = _cairo_pdf_surface_unselect_pattern (surface);
7586 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7587 return status;
7588 }
7589 }
7590
7591 status = _cairo_pdf_surface_close_group (surface, NULL((void*)0));
7592 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7593 return status;
7594
7595 /* Create an smask based on the alpha component of mask_group */
7596 smask = _cairo_pdf_surface_new_object (surface);
7597 if (smask.id == 0)
7598 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
7599
7600 _cairo_output_stream_printf (surface->output,
7601 "%d 0 obj\n"
7602 "<< /Type /Mask\n"
7603 " /S /Alpha\n"
7604 " /G %d 0 R\n"
7605 ">>\n"
7606 "endobj\n",
7607 smask.id,
7608 mask_group.id);
7609
7610 /* Create a GState that uses the smask */
7611 _cairo_pdf_surface_update_object (surface, group->group_res);
7612 _cairo_output_stream_printf (surface->output,
7613 "%d 0 obj\n"
7614 "<< /Type /ExtGState\n"
7615 " /SMask %d 0 R\n"
7616 " /ca 1\n"
7617 " /CA 1\n"
7618 " /AIS false\n"
7619 ">>\n"
7620 "endobj\n",
7621 group->group_res.id,
7622 smask.id);
7623
7624 return _cairo_output_stream_get_status (surface->output);
7625}
7626
7627static cairo_int_status_t
7628_cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
7629 cairo_pdf_smask_group_t *group)
7630{
7631 double old_width, old_height;
7632 cairo_bool_t old_in_xobject;
7633 cairo_int_status_t status;
7634 cairo_box_double_t bbox;
7635 cairo_rectangle_int_t old_surface_extents;
7636
7637 old_width = surface->width;
7638 old_height = surface->height;
7639 old_surface_extents = surface->surface_extents;
7640 old_in_xobject = surface->in_xobject;
7641 surface->in_xobject = TRUE1;
7642 _cairo_pdf_surface_set_size_internal (surface,
7643 group->width,
7644 group->height);
7645 _cairo_pdf_operators_reset (&surface->pdf_operators);
7646 /* _mask is a special case that requires two groups - source
7647 * and mask as well as a smask and gstate dictionary */
7648 if (group->operation == PDF_MASK) {
7649 status = _cairo_pdf_surface_write_mask_group (surface, group);
7650 goto RESTORE_SIZE;
7651 }
7652
7653 _get_bbox_from_extents (&group->extents, &bbox);
7654 status = _cairo_pdf_surface_open_group (surface, &bbox, &group->group_res);
7655 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7656 return status;
7657
7658 status = _cairo_pdf_surface_select_pattern (surface,
7659 group->source,
7660 group->source_res,
7661 group->operation == PDF_STROKE);
7662 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7663 return status;
7664
7665 switch (group->operation) {
7666 case PDF_PAINT:
7667 _cairo_output_stream_printf (surface->output,
7668 "0 0 %f %f re f\n",
7669 surface->width, surface->height);
7670 break;
7671 case PDF_MASK:
7672 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 7672, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
7673 break;
7674 case PDF_FILL:
7675 status = _cairo_pdf_operators_fill (&surface->pdf_operators,
7676 &group->path,
7677 group->fill_rule);
7678 break;
7679 case PDF_STROKE:
7680 status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
7681 &group->path,
7682 &group->style,
7683 &group->ctm,
7684 &group->ctm_inverse);
7685 break;
7686 case PDF_SHOW_GLYPHS:
7687 status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
7688 group->utf8, group->utf8_len,
7689 group->glyphs, group->num_glyphs,
7690 group->clusters, group->num_clusters,
7691 group->cluster_flags,
7692 group->scaled_font);
7693 break;
7694 }
7695 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7696 return status;
7697
7698 status = _cairo_pdf_surface_unselect_pattern (surface);
7699 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7700 return status;
7701
7702 status = _cairo_pdf_surface_close_group (surface, NULL((void*)0));
7703
7704RESTORE_SIZE:
7705 surface->in_xobject = old_in_xobject;
7706 _cairo_pdf_surface_set_size_internal (surface,
7707 old_width,
7708 old_height);
7709 surface->surface_extents = old_surface_extents;
7710 _cairo_pdf_operators_reset (&surface->pdf_operators);
7711
7712 return status;
7713}
7714
7715static cairo_int_status_t
7716_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface,
7717 cairo_bool_t finish)
7718{
7719 cairo_pdf_pattern_t pattern;
7720 cairo_pdf_smask_group_t *group;
7721 cairo_pdf_source_surface_t src_surface;
7722 unsigned int pattern_index, group_index, surface_index, doc_surface_index;
7723 cairo_int_status_t status;
7724 cairo_bool_t is_image;
7725
7726 /* Writing out PDF_MASK groups will cause additional smask groups
7727 * to be appended to surface->smask_groups. Additional patterns
7728 * may also be appended to surface->patterns.
7729 *
7730 * Writing recording surface patterns will cause additional patterns
7731 * and groups to be appended.
7732 */
7733 pattern_index = 0;
7734 group_index = 0;
7735 surface_index = 0;
7736 doc_surface_index = 0;
7737 while ((pattern_index < _cairo_array_num_elements (&surface->page_patterns)) ||
7738 (group_index < _cairo_array_num_elements (&surface->smask_groups)) ||
7739 (surface_index < _cairo_array_num_elements (&surface->page_surfaces)) ||
7740 (finish && (doc_surface_index < _cairo_array_num_elements (&surface->doc_surfaces))))
7741 {
7742 for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) {
7743 _cairo_array_copy_element (&surface->smask_groups, group_index, &group);
7744 status = _cairo_pdf_surface_write_smask_group (surface, group);
7745 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7746 return status;
7747 }
7748
7749 for (; pattern_index < _cairo_array_num_elements (&surface->page_patterns); pattern_index++) {
7750 _cairo_array_copy_element (&surface->page_patterns, pattern_index, &pattern);
7751 status = _cairo_pdf_surface_emit_pattern (surface, &pattern);
7752 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7753 return status;
7754 }
7755
7756 for (; surface_index < _cairo_array_num_elements (&surface->page_surfaces); surface_index++) {
7757 _cairo_array_copy_element (&surface->page_surfaces, surface_index, &src_surface);
7758 status = _cairo_pdf_surface_emit_surface (surface, &src_surface, FALSE0, &is_image);
7759 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7760 return status;
7761 }
7762
7763 if (finish) {
7764 for (; doc_surface_index < _cairo_array_num_elements (&surface->doc_surfaces); doc_surface_index++) {
7765 _cairo_array_copy_element (&surface->doc_surfaces, doc_surface_index, &src_surface);
7766 status = _cairo_pdf_surface_emit_surface (surface, &src_surface, FALSE0, &is_image);
7767 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7768 return status;
7769 }
7770 }
7771 }
7772
7773 return CAIRO_STATUS_SUCCESS;
7774}
7775
7776static cairo_int_status_t
7777_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
7778{
7779 cairo_pdf_resource_t knockout, res;
7780 cairo_int_status_t status;
7781 unsigned int i, len;
7782 cairo_pdf_page_info_t *page_info;
7783
7784 page_info = _cairo_array_last_element (&surface->pages);
7785
7786 status = _cairo_pdf_surface_open_object_stream (surface);
7787 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7788 return status;
7789
7790 status = _cairo_pdf_interchange_write_page_objects (surface);
7791 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7792 return status;
7793
7794 _cairo_pdf_group_resources_clear (&surface->resources);
7795 if (surface->has_fallback_images) {
7796 cairo_rectangle_int_t extents;
7797 cairo_box_double_t bbox;
7798
7799 extents.x = 0;
7800 extents.y = 0;
7801 extents.width = ceil (surface->width);
7802 extents.height = ceil (surface->height);
7803 _get_bbox_from_extents (&extents, &bbox);
7804 status = _cairo_pdf_surface_open_knockout_group (surface, &bbox);
7805 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7806 return status;
7807
7808 len = _cairo_array_num_elements (&surface->knockout_group);
7809 for (i = 0; i < len; i++) {
7810 _cairo_array_copy_element (&surface->knockout_group, i, &res);
7811 _cairo_output_stream_printf (surface->output,
7812 "/x%d Do\n",
7813 res.id);
7814 status = _cairo_pdf_surface_add_xobject (surface, res);
7815 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7816 return status;
7817 }
7818 _cairo_output_stream_printf (surface->output,
7819 "/x%d Do\n",
7820 surface->content.id);
7821 status = _cairo_pdf_surface_add_xobject (surface, surface->content);
7822 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7823 return status;
7824
7825 status = _cairo_pdf_surface_close_group (surface, &knockout);
7826 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7827 return status;
7828
7829 _cairo_pdf_group_resources_clear (&surface->resources);
7830 status = _cairo_pdf_surface_open_content_stream (surface, NULL((void*)0), NULL((void*)0), FALSE0, FALSE0, -1);
7831 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7832 return status;
7833
7834 _cairo_output_stream_printf (surface->output,
7835 "/x%d Do\n",
7836 knockout.id);
7837 status = _cairo_pdf_surface_add_xobject (surface, knockout);
7838 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7839 return status;
7840
7841 status = _cairo_pdf_surface_close_content_stream (surface, FALSE0);
7842 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7843 return status;
7844 }
7845
7846 if (surface->thumbnail_image) {
7847 cairo_pdf_source_surface_entry_t entry;
7848
7849 memset (&entry, 0, sizeof (entry));
7850 page_info->thumbnail = _cairo_pdf_surface_new_object (surface);
7851 entry.surface_res = page_info->thumbnail;
7852 _cairo_pdf_surface_emit_image (surface, surface->thumbnail_image, &entry);
7853 }
7854
7855 page_info->content = surface->content;
7856 page_info->resources = surface->content_resources;
7857 page_info->struct_parents = surface->page_parent_tree;
7858
7859 status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface, FALSE0);
7860 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7861 return status;
7862
7863 return _cairo_pdf_surface_close_object_stream (surface);
7864}
7865
7866static cairo_int_status_t
7867_cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t *surface,
7868 cairo_surface_pattern_t *pattern)
7869{
7870 cairo_image_surface_t *image;
7871 void *image_extra;
7872 cairo_int_status_t status;
7873 cairo_image_transparency_t transparency;
7874
7875 status = _cairo_surface_acquire_source_image (pattern->surface,
7876 &image,
7877 &image_extra);
7878 if (unlikely (status)(__builtin_expect (!!(status), 0)))
7879 return status;
7880
7881 if (image->base.status)
7882 return image->base.status;
7883
7884 transparency = _cairo_image_analyze_transparency (image);
7885 if (transparency == CAIRO_IMAGE_IS_OPAQUE)
7886 status = CAIRO_STATUS_SUCCESS;
7887 else
7888 status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
7889
7890 _cairo_surface_release_source_image (pattern->surface, image, image_extra);
7891
7892 return status;
7893}
7894
7895static cairo_bool_t
7896_surface_pattern_supported (cairo_surface_pattern_t *pattern)
7897{
7898 cairo_extend_t extend;
7899
7900 if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
7901 return TRUE1;
7902
7903 if (pattern->surface->backend->acquire_source_image == NULL((void*)0))
7904 return FALSE0;
7905
7906 /* Does an ALPHA-only source surface even make sense? Maybe, but I
7907 * don't think it's worth the extra code to support it. */
7908
7909/* XXX: Need to write this function here...
7910 if (pattern->surface->content == CAIRO_CONTENT_ALPHA)
7911 return FALSE;
7912*/
7913
7914 extend = cairo_pattern_get_extend_moz_cairo_pattern_get_extend (&pattern->base);
7915 switch (extend) {
7916 case CAIRO_EXTEND_NONE:
7917 case CAIRO_EXTEND_REPEAT:
7918 case CAIRO_EXTEND_REFLECT:
7919 /* There's no point returning FALSE for EXTEND_PAD, as the image
7920 * surface does not currently implement it either */
7921 case CAIRO_EXTEND_PAD:
7922 return TRUE1;
7923 }
7924
7925 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 7925, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
7926 return FALSE0;
7927}
7928
7929static cairo_bool_t
7930_pattern_supported (const cairo_pattern_t *pattern)
7931{
7932 switch (pattern->type) {
7933 case CAIRO_PATTERN_TYPE_SOLID:
7934 case CAIRO_PATTERN_TYPE_LINEAR:
7935 case CAIRO_PATTERN_TYPE_RADIAL:
7936 case CAIRO_PATTERN_TYPE_MESH:
7937 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
7938 return TRUE1;
7939
7940 case CAIRO_PATTERN_TYPE_SURFACE:
7941 return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
7942
7943 default:
7944 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 7944, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
7945 return FALSE0;
7946 }
7947}
7948
7949static cairo_bool_t
7950_pdf_operator_supported (cairo_operator_t op)
7951{
7952 switch (op) {
7953 case CAIRO_OPERATOR_OVER:
7954 case CAIRO_OPERATOR_MULTIPLY:
7955 case CAIRO_OPERATOR_SCREEN:
7956 case CAIRO_OPERATOR_OVERLAY:
7957 case CAIRO_OPERATOR_DARKEN:
7958 case CAIRO_OPERATOR_LIGHTEN:
7959 case CAIRO_OPERATOR_COLOR_DODGE:
7960 case CAIRO_OPERATOR_COLOR_BURN:
7961 case CAIRO_OPERATOR_HARD_LIGHT:
7962 case CAIRO_OPERATOR_SOFT_LIGHT:
7963 case CAIRO_OPERATOR_DIFFERENCE:
7964 case CAIRO_OPERATOR_EXCLUSION:
7965 case CAIRO_OPERATOR_HSL_HUE:
7966 case CAIRO_OPERATOR_HSL_SATURATION:
7967 case CAIRO_OPERATOR_HSL_COLOR:
7968 case CAIRO_OPERATOR_HSL_LUMINOSITY:
7969 return TRUE1;
7970
7971 default:
7972 case CAIRO_OPERATOR_CLEAR:
7973 case CAIRO_OPERATOR_SOURCE:
7974 case CAIRO_OPERATOR_IN:
7975 case CAIRO_OPERATOR_OUT:
7976 case CAIRO_OPERATOR_ATOP:
7977 case CAIRO_OPERATOR_DEST:
7978 case CAIRO_OPERATOR_DEST_OVER:
7979 case CAIRO_OPERATOR_DEST_IN:
7980 case CAIRO_OPERATOR_DEST_OUT:
7981 case CAIRO_OPERATOR_DEST_ATOP:
7982 case CAIRO_OPERATOR_XOR:
7983 case CAIRO_OPERATOR_ADD:
7984 case CAIRO_OPERATOR_SATURATE:
7985 return FALSE0;
7986 }
7987}
7988
7989static cairo_int_status_t
7990_cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
7991 cairo_operator_t op,
7992 const cairo_pattern_t *pattern,
7993 const cairo_rectangle_int_t *extents)
7994{
7995 if (surface->force_fallbacks &&
7996 surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
7997 {
7998 return CAIRO_INT_STATUS_UNSUPPORTED;
7999 }
8000
8001 if (! _pattern_supported (pattern))
8002 return CAIRO_INT_STATUS_UNSUPPORTED;
8003
8004 if (_pdf_operator_supported (op)) {
8005 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
8006 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
8007
8008 if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
8009 if (pattern->extend == CAIRO_EXTEND_PAD) {
8010 cairo_box_t box;
8011 cairo_rectangle_int_t rect;
8012 cairo_rectangle_int_t rec_extents;
8013
8014 /* get the operation extents in pattern space */
8015 _cairo_box_from_rectangle (&box, extents);
8016 _cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &box, NULL((void*)0));
8017 _cairo_box_round_to_rectangle (&box, &rect);
8018
8019 /* Check if surface needs padding to fill extents */
8020 if (_cairo_surface_get_extents (surface_pattern->surface, &rec_extents)) {
8021 if (_cairo_fixed_integer_ceil(box.p1.x) < rec_extents.x ||
8022 _cairo_fixed_integer_ceil(box.p1.y) < rec_extents.y ||
8023 _cairo_fixed_integer_floor(box.p2.x) > rec_extents.x + rec_extents.width ||
8024 _cairo_fixed_integer_floor(box.p2.y) > rec_extents.y + rec_extents.height)
8025 {
8026 return CAIRO_INT_STATUS_UNSUPPORTED;
8027 }
8028 }
8029 }
8030 return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
8031 }
8032 }
8033
8034 return CAIRO_STATUS_SUCCESS;
8035 }
8036
8037
8038 /* The SOURCE operator is supported if the pattern is opaque or if
8039 * there is nothing painted underneath. */
8040 if (op == CAIRO_OPERATOR_SOURCE) {
8041 if (surface->type3_replay)
8042 return CAIRO_INT_STATUS_UNSUPPORTED;
8043
8044 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
8045 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
8046
8047 if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
8048 if (_cairo_pattern_is_opaque (pattern, extents)) {
8049 return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
8050 } else {
8051 /* FIXME: The analysis surface does not yet have
8052 * the capability to analyze a non opaque recording
8053 * surface and mark it supported if there is
8054 * nothing underneath. For now recording surfaces of
8055 * type CONTENT_COLOR_ALPHA painted with
8056 * OPERATOR_SOURCE will result in a fallback
8057 * image. */
8058
8059 return CAIRO_INT_STATUS_UNSUPPORTED;
8060 }
8061 } else {
8062 return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
8063 surface_pattern);
8064 }
8065 }
8066
8067 if (_cairo_pattern_is_opaque (pattern, extents))
8068 return CAIRO_STATUS_SUCCESS;
8069 else
8070 return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
8071 }
8072
8073 return CAIRO_INT_STATUS_UNSUPPORTED;
8074}
8075
8076static cairo_bool_t
8077_cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
8078 cairo_operator_t op,
8079 const cairo_pattern_t *pattern,
8080 const cairo_rectangle_int_t *extents)
8081{
8082 return _cairo_pdf_surface_analyze_operation (surface, op, pattern, extents) != CAIRO_INT_STATUS_UNSUPPORTED;
8083}
8084
8085static cairo_int_status_t
8086_cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
8087{
8088 cairo_box_double_t bbox;
8089 cairo_int_status_t status;
8090
8091 status = _cairo_pdf_surface_close_content_stream (surface, FALSE0);
8092 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8093 return status;
8094
8095 status = _cairo_array_append (&surface->knockout_group, &surface->content);
8096 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8097 return status;
8098
8099 _cairo_pdf_group_resources_clear (&surface->resources);
8100 bbox.p1.x = 0;
8101 bbox.p1.y = 0;
8102 bbox.p2.x = surface->width;
8103 bbox.p2.y = surface->height;
8104 status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL((void*)0), TRUE1, TRUE1, -1);
8105 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8106 return status;
8107
8108 return _cairo_pdf_interchange_begin_page_content (surface);
8109}
8110
8111/* If source is an opaque image and mask is an image and both images
8112 * have the same bounding box we can emit them as a image/smask pair.
8113 */
8114static cairo_int_status_t
8115_cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface,
8116 cairo_operator_t op,
8117 const cairo_pattern_t *source,
8118 const cairo_pattern_t *mask,
8119 const cairo_rectangle_int_t *extents)
8120{
8121 cairo_int_status_t status;
8122 cairo_image_surface_t *image;
8123 void *image_extra;
23
'image_extra' declared without an initial value
8124 cairo_image_transparency_t transparency;
8125 int src_width, src_height;
8126 int mask_width, mask_height;
8127 double src_x_offset, src_y_offset;
8128 double mask_x_offset, mask_y_offset;
8129 double src_x1, src_y1, src_x2, src_y2;
8130 double mask_x1, mask_y1, mask_x2, mask_y2;
8131 cairo_matrix_t p2u;
8132 double src_radius, mask_radius, e;
8133 cairo_bool_t need_smask;
8134 cairo_pdf_source_surface_entry_t *pdf_source;
8135
8136 /* Check that source and mask are images */
8137
8138 if (!((source->type
23.1
Field 'type' is not equal to CAIRO_PATTERN_TYPE_SURFACE
== CAIRO_PATTERN_TYPE_SURFACE || source->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) &&
24
Assuming field 'type' is equal to CAIRO_PATTERN_TYPE_RASTER_SOURCE
8139 (mask->type
24.1
Field 'type' is not equal to CAIRO_PATTERN_TYPE_SURFACE
== CAIRO_PATTERN_TYPE_SURFACE || mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)))
25
Assuming field 'type' is equal to CAIRO_PATTERN_TYPE_RASTER_SOURCE
8140 return CAIRO_INT_STATUS_UNSUPPORTED;
8141
8142 if (source->type
25.1
Field 'type' is not equal to CAIRO_PATTERN_TYPE_SURFACE
== CAIRO_PATTERN_TYPE_SURFACE &&
8143 ((cairo_surface_pattern_t *) source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
8144 {
8145 return CAIRO_INT_STATUS_UNSUPPORTED;
8146 }
8147
8148 if (mask->type
25.2
Field 'type' is not equal to CAIRO_PATTERN_TYPE_SURFACE
== CAIRO_PATTERN_TYPE_SURFACE &&
8149 ((cairo_surface_pattern_t *) mask)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
8150 {
8151 return CAIRO_INT_STATUS_UNSUPPORTED;
8152 }
8153
8154 if (source->extend != CAIRO_EXTEND_NONE || mask->extend != CAIRO_EXTEND_NONE)
26
Assuming field 'extend' is equal to CAIRO_EXTEND_NONE
27
Assuming field 'extend' is equal to CAIRO_EXTEND_NONE
28
Taking false branch
8155 return CAIRO_INT_STATUS_UNSUPPORTED;
8156
8157 /* Check that source is opaque and get image sizes */
8158
8159 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source,
29
Calling '_cairo_pdf_surface_acquire_source_image_from_pattern'
37
Returning from '_cairo_pdf_surface_acquire_source_image_from_pattern'
8160 &image, &image_extra);
8161 if (unlikely (status)(__builtin_expect (!!(status), 0)))
38
Taking false branch
8162 return status;
8163
8164 if (image->base.status)
39
Assuming field 'status' is 0
40
Taking false branch
8165 return image->base.status;
8166
8167 src_width = image->width;
8168 src_height = image->height;
8169 if (source->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
41
Assuming field 'type' is not equal to CAIRO_PATTERN_TYPE_RASTER_SOURCE
42
Taking false branch
8170 cairo_surface_get_device_offset_moz_cairo_surface_get_device_offset (&image->base, &src_x_offset, &src_y_offset);
8171 } else {
8172 src_x_offset = 0;
8173 src_y_offset = 0;
8174 }
8175
8176 transparency = _cairo_image_analyze_transparency (image);
8177 _cairo_pdf_surface_release_source_image_from_pattern (surface, source, image, image_extra);
43
4th function call argument is an uninitialized value
8178
8179 if (transparency != CAIRO_IMAGE_IS_OPAQUE)
8180 return CAIRO_INT_STATUS_UNSUPPORTED;
8181
8182 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, mask,
8183 &image, &image_extra);
8184 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8185 return status;
8186
8187 if (image->base.status)
8188 return image->base.status;
8189
8190 mask_width = image->width;
8191 mask_height = image->height;
8192 if (mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
8193 cairo_surface_get_device_offset_moz_cairo_surface_get_device_offset (&image->base, &mask_x_offset, &mask_y_offset);
8194 } else {
8195 mask_x_offset = 0;
8196 mask_y_offset = 0;
8197 }
8198
8199 transparency = _cairo_image_analyze_transparency (image);
8200 need_smask = transparency != CAIRO_IMAGE_IS_OPAQUE;
8201
8202 _cairo_pdf_surface_release_source_image_from_pattern (surface, mask, image, image_extra);
8203
8204 /* Check that both images have the same extents with a tolerance
8205 * of half the smallest source pixel. */
8206
8207 p2u = source->matrix;
8208 status = cairo_matrix_invert_moz_cairo_matrix_invert (&p2u);
8209 /* cairo_pattern_set_matrix ensures the matrix is invertible */
8210 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-pdf-surface.c"
, 8210, __extension__ __PRETTY_FUNCTION__); }))
;
8211 src_x1 = 0;
8212 src_y1 = 0;
8213 src_x2 = src_width;
8214 src_y2 = src_height;
8215 cairo_matrix_transform_point_moz_cairo_matrix_transform_point (&p2u, &src_x1, &src_y1);
8216 cairo_matrix_transform_point_moz_cairo_matrix_transform_point (&p2u, &src_x2, &src_y2);
8217 src_radius = _cairo_matrix_transformed_circle_major_axis (&p2u, 0.5);
8218
8219 p2u = mask->matrix;
8220 status = cairo_matrix_invert_moz_cairo_matrix_invert (&p2u);
8221 /* cairo_pattern_set_matrix ensures the matrix is invertible */
8222 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-pdf-surface.c"
, 8222, __extension__ __PRETTY_FUNCTION__); }))
;
8223 mask_x1 = 0;
8224 mask_y1 = 0;
8225 mask_x2 = mask_width;
8226 mask_y2 = mask_height;
8227 cairo_matrix_transform_point_moz_cairo_matrix_transform_point (&p2u, &mask_x1, &mask_y1);
8228 cairo_matrix_transform_point_moz_cairo_matrix_transform_point (&p2u, &mask_x2, &mask_y2);
8229 mask_radius = _cairo_matrix_transformed_circle_major_axis (&p2u, 0.5);
8230
8231 if (src_radius < mask_radius)
8232 e = src_radius;
8233 else
8234 e = mask_radius;
8235
8236 if (fabs(src_x1 - mask_x1) > e ||
8237 fabs(src_x2 - mask_x2) > e ||
8238 fabs(src_y1 - mask_y1) > e ||
8239 fabs(src_y2 - mask_y2) > e)
8240 return CAIRO_INT_STATUS_UNSUPPORTED;
8241
8242 /* Check both images have same device offset */
8243 if (fabs(src_x_offset - mask_x_offset) > e ||
8244 fabs(src_y_offset - mask_y_offset) > e)
8245 return CAIRO_INT_STATUS_UNSUPPORTED;
8246
8247 if (need_smask) {
8248 status = _cairo_pdf_surface_add_source_surface (surface,
8249 NULL((void*)0),
8250 mask,
8251 -1, /* node_surface_index */
8252 op,
8253 source->filter,
8254 FALSE0, /* stencil mask */
8255 TRUE1, /* smask */
8256 FALSE0, /* need_transp_group */
8257 extents,
8258 NULL((void*)0), /* smask_res */
8259 &pdf_source,
8260 NULL((void*)0),
8261 NULL((void*)0),
8262 NULL((void*)0));
8263 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8264 return status;
8265 }
8266
8267 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8268 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8269 return status;
8270
8271 _cairo_output_stream_printf (surface->output, "q\n");
8272 status = _cairo_pdf_surface_paint_surface_pattern (surface, op, source,
8273 CAIRO_ANALYSIS_SOURCE_NONE,
8274 extents,
8275 1.0, /* alpha */
8276 need_smask ? &pdf_source->surface_res : NULL((void*)0),
8277 FALSE0);
8278 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8279 return status;
8280
8281 _cairo_output_stream_printf (surface->output, "Q\n");
8282
8283 status = _cairo_output_stream_get_status (surface->output);
8284
8285
8286 return status;
8287}
8288
8289/* A PDF stencil mask is an A1 mask used with the current color */
8290static cairo_int_status_t
8291_cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface,
8292 cairo_operator_t op,
8293 const cairo_pattern_t *source,
8294 const cairo_pattern_t *mask,
8295 const cairo_rectangle_int_t *extents)
8296{
8297 cairo_int_status_t status;
8298 cairo_image_surface_t *image;
8299 void *image_extra;
8300 cairo_image_transparency_t transparency;
8301 cairo_pdf_resource_t pattern_res = {0};
8302
8303 if (! (source->type == CAIRO_PATTERN_TYPE_SOLID &&
8304 (mask->type == CAIRO_PATTERN_TYPE_SURFACE || mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)))
8305 return CAIRO_INT_STATUS_UNSUPPORTED;
8306
8307 if (mask->type == CAIRO_PATTERN_TYPE_SURFACE &&
8308 ((cairo_surface_pattern_t *) mask)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
8309 {
8310 return CAIRO_INT_STATUS_UNSUPPORTED;
8311 }
8312
8313 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, mask,
8314 &image, &image_extra);
8315 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8316 return status;
8317
8318 if (image->base.status)
8319 return image->base.status;
8320
8321 transparency = _cairo_image_analyze_transparency (image);
8322 if (transparency != CAIRO_IMAGE_IS_OPAQUE &&
8323 transparency != CAIRO_IMAGE_HAS_BILEVEL_ALPHA)
8324 {
8325 status = CAIRO_INT_STATUS_UNSUPPORTED;
8326 goto cleanup;
8327 }
8328
8329 status = _cairo_pdf_surface_select_pattern (surface, source,
8330 pattern_res, FALSE0);
8331 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8332 return status;
8333
8334 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8335 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8336 return status;
8337
8338 _cairo_output_stream_printf (surface->output, "q\n");
8339 status = _cairo_pdf_surface_paint_surface_pattern (surface, op, mask,
8340 CAIRO_ANALYSIS_SOURCE_NONE,
8341 extents, 1.0, NULL((void*)0), TRUE1);
8342 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8343 return status;
8344
8345 _cairo_output_stream_printf (surface->output, "Q\n");
8346
8347 status = _cairo_output_stream_get_status (surface->output);
8348
8349cleanup:
8350 _cairo_pdf_surface_release_source_image_from_pattern (surface, mask, image, image_extra);
8351
8352 return status;
8353}
8354
8355static cairo_int_status_t
8356_cairo_pdf_surface_set_clip (cairo_pdf_surface_t *surface,
8357 cairo_composite_rectangles_t *composite)
8358{
8359 cairo_clip_t *clip = composite->clip;
8360
8361 if (_cairo_composite_rectangles_can_reduce_clip (composite, clip))
8362 clip = NULL((void*)0);
8363
8364 if (clip == NULL((void*)0)) {
8365 if (_cairo_composite_rectangles_can_reduce_clip (composite,
8366 surface->clipper.clip))
8367 return CAIRO_STATUS_SUCCESS;
8368 }
8369
8370 return _cairo_surface_clipper_set_clip (&surface->clipper, clip);
8371}
8372
8373static cairo_int_status_t
8374_cairo_pdf_surface_paint (void *abstract_surface,
8375 cairo_operator_t op,
8376 const cairo_pattern_t *source,
8377 const cairo_clip_t *clip)
8378{
8379 cairo_pdf_surface_t *surface = abstract_surface;
8380 cairo_pdf_smask_group_t *group;
8381 cairo_pdf_resource_t pattern_res, gstate_res;
8382 cairo_composite_rectangles_t extents;
8383 cairo_int_status_t status;
8384
8385 status = _cairo_composite_rectangles_init_for_paint (&extents,
8386 &surface->base,
8387 op, source, clip);
8388 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8389 return status;
8390
8391 status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
8392 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8393 return status;
8394
8395 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
8396 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
8397 goto cleanup;
8398 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
8399 status = _cairo_pdf_surface_start_fallback (surface);
8400 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8401 goto cleanup;
8402 }
8403
8404 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded))((void) sizeof ((_cairo_pdf_surface_operation_supported (surface
, op, source, &extents.bounded)) ? 1 : 0), __extension__ (
{ if (_cairo_pdf_surface_operation_supported (surface, op, source
, &extents.bounded)) ; else __assert_fail ("_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded)"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 8404, __extension__ __PRETTY_FUNCTION__); }))
;
8405
8406 status = _cairo_pdf_surface_set_clip (surface, &extents);
8407 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8408 goto cleanup;
8409
8410 status = _cairo_pdf_surface_select_operator (surface, op);
8411 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8412 goto cleanup;
8413
8414 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8415 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8416 goto cleanup;
8417
8418 if (_can_paint_pattern (source)) {
8419 _cairo_output_stream_printf (surface->output, "q\n");
8420 status = _cairo_pdf_surface_paint_pattern (surface,
8421 op,
8422 source,
8423 CAIRO_ANALYSIS_SOURCE_PAINT,
8424 &extents.bounded,
8425 1.0, /* alpha */
8426 FALSE0); /* mask */
8427 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8428 goto cleanup;
8429
8430 _cairo_output_stream_printf (surface->output, "Q\n");
8431 _cairo_composite_rectangles_fini (&extents);
8432 return _cairo_output_stream_get_status (surface->output);
8433 }
8434
8435 pattern_res.id = 0;
8436 gstate_res.id = 0;
8437 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
8438 CAIRO_ANALYSIS_SOURCE_PAINT,
8439 &extents.bounded,
8440 &pattern_res, &gstate_res);
8441 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8442 goto cleanup;
8443
8444 if (gstate_res.id != 0) {
8445 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
8446 if (unlikely (group == NULL)(__builtin_expect (!!(group == ((void*)0)), 0))) {
8447 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8448 goto cleanup;
8449 }
8450
8451 group->operation = PDF_PAINT;
8452 status = _cairo_pattern_create_copy (&group->source, source);
8453 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
8454 _cairo_pdf_smask_group_destroy (group);
8455 goto cleanup;
8456 }
8457 group->source_res = pattern_res;
8458 status = _cairo_pdf_surface_add_smask_group (surface, group);
8459 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
8460 _cairo_pdf_smask_group_destroy (group);
8461 goto cleanup;
8462 }
8463
8464 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
8465 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8466 goto cleanup;
8467
8468 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
8469 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8470 goto cleanup;
8471
8472 _cairo_output_stream_printf (surface->output,
8473 "q /s%d gs /x%d Do Q\n",
8474 gstate_res.id,
8475 group->group_res.id);
8476 } else {
8477 status = _cairo_pdf_surface_select_pattern (surface, source,
8478 pattern_res, FALSE0);
8479 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8480 goto cleanup;
8481
8482 _cairo_output_stream_printf (surface->output,
8483 "%d %d %d %d re f\n",
8484 surface->surface_extents.x,
8485 surface->surface_extents.y,
8486 surface->surface_extents.width,
8487 surface->surface_extents.height);
8488
8489 status = _cairo_pdf_surface_unselect_pattern (surface);
8490 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8491 goto cleanup;
8492 }
8493
8494 _cairo_composite_rectangles_fini (&extents);
8495 return _cairo_output_stream_get_status (surface->output);
8496
8497cleanup:
8498 _cairo_composite_rectangles_fini (&extents);
8499 return status;
8500}
8501
8502static cairo_int_status_t
8503_cairo_pdf_surface_mask (void *abstract_surface,
8504 cairo_operator_t op,
8505 const cairo_pattern_t *source,
8506 const cairo_pattern_t *mask,
8507 const cairo_clip_t *clip)
8508{
8509 cairo_pdf_surface_t *surface = abstract_surface;
8510 cairo_pdf_smask_group_t *group;
8511 cairo_composite_rectangles_t extents;
8512 cairo_int_status_t status;
8513 cairo_rectangle_int_t r;
8514 cairo_box_t box;
8515 double alpha;
8516
8517 status = _cairo_composite_rectangles_init_for_mask (&extents,
8518 &surface->base,
8519 op, source, mask, clip);
8520 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1
Assuming 'status' is 0
2
Taking false branch
8521 return status;
8522
8523 status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
8524 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3
Assuming 'status' is 0
4
Taking false branch
8525 return status;
8526
8527 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
5
Assuming field 'paginated_mode' is not equal to CAIRO_PAGINATED_MODE_ANALYZE
6
Taking false branch
8528 cairo_int_status_t source_status, mask_status;
8529
8530 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
8531 if (_cairo_int_status_is_error (status)((status) != CAIRO_INT_STATUS_SUCCESS && (status) <
CAIRO_INT_STATUS_LAST_STATUS)
)
8532 goto cleanup;
8533 source_status = status;
8534
8535 if (mask->has_component_alpha) {
8536 status = CAIRO_INT_STATUS_UNSUPPORTED;
8537 } else {
8538 status = _cairo_pdf_surface_analyze_operation (surface, op, mask, &extents.bounded);
8539 if (_cairo_int_status_is_error (status)((status) != CAIRO_INT_STATUS_SUCCESS && (status) <
CAIRO_INT_STATUS_LAST_STATUS)
)
8540 goto cleanup;
8541 }
8542 mask_status = status;
8543
8544 _cairo_composite_rectangles_fini (&extents);
8545 return _cairo_analysis_surface_merge_status (source_status,
8546 mask_status);
8547 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
7
Assuming field 'paginated_mode' is not equal to CAIRO_PAGINATED_MODE_FALLBACK
8
Taking false branch
8548 status = _cairo_pdf_surface_start_fallback (surface);
8549 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8550 goto cleanup;
8551 }
8552
8553 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded))((void) sizeof ((_cairo_pdf_surface_operation_supported (surface
, op, source, &extents.bounded)) ? 1 : 0), __extension__ (
{ if (_cairo_pdf_surface_operation_supported (surface, op, source
, &extents.bounded)) ; else __assert_fail ("_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded)"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 8553, __extension__ __PRETTY_FUNCTION__); }))
;
9
Taking true branch
8554 assert (_cairo_pdf_surface_operation_supported (surface, op, mask, &extents.bounded))((void) sizeof ((_cairo_pdf_surface_operation_supported (surface
, op, mask, &extents.bounded)) ? 1 : 0), __extension__ ({
if (_cairo_pdf_surface_operation_supported (surface, op, mask
, &extents.bounded)) ; else __assert_fail ("_cairo_pdf_surface_operation_supported (surface, op, mask, &extents.bounded)"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 8554, __extension__ __PRETTY_FUNCTION__); }))
;
10
Taking true branch
8555
8556 /* get the accurate extents */
8557 status = _cairo_pattern_get_ink_extents (source, &r);
8558 if (unlikely (status)(__builtin_expect (!!(status), 0)))
11
Assuming 'status' is 0
12
Taking false branch
8559 goto cleanup;
8560
8561 /* XXX slight impedance mismatch */
8562 _cairo_box_from_rectangle (&box, &r);
8563 status = _cairo_composite_rectangles_intersect_source_extents (&extents,
8564 &box);
8565 if (unlikely (status)(__builtin_expect (!!(status), 0)))
13
Assuming 'status' is 0
14
Taking false branch
8566 goto cleanup;
8567
8568 status = _cairo_pattern_get_ink_extents (mask, &r);
8569 if (unlikely (status)(__builtin_expect (!!(status), 0)))
15
Assuming 'status' is 0
16
Taking false branch
8570 goto cleanup;
8571
8572 _cairo_box_from_rectangle (&box, &r);
8573 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
8574 &box);
8575 if (unlikely (status)(__builtin_expect (!!(status), 0)))
17
Assuming 'status' is 0
18
Taking false branch
8576 goto cleanup;
8577
8578 status = _cairo_pdf_surface_set_clip (surface, &extents);
8579 if (unlikely (status)(__builtin_expect (!!(status), 0)))
19
Assuming 'status' is 0
20
Taking false branch
8580 goto cleanup;
8581
8582 status = _cairo_pdf_surface_select_operator (surface, op);
8583 if (unlikely (status)(__builtin_expect (!!(status), 0)))
21
Taking false branch
8584 goto cleanup;
8585
8586 /* Check if we can combine source and mask into a smask image */
8587 status = _cairo_pdf_surface_emit_combined_smask (surface, op, source, mask, &extents.bounded);
22
Calling '_cairo_pdf_surface_emit_combined_smask'
8588 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
8589 goto cleanup;
8590
8591 /* Check if we can use a stencil mask */
8592 status = _cairo_pdf_surface_emit_stencil_mask (surface, op, source, mask, &extents.bounded);
8593 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
8594 goto cleanup;
8595
8596 /* Check if we can set ca/CA instead of an smask. We could handle
8597 * other source patterns as well but for now this is the easiest,
8598 * and most common, case to handle. */
8599 if (_cairo_pattern_is_constant_alpha (mask, &extents.bounded, &alpha) &&
8600 _can_paint_pattern (source)) {
8601
8602 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8603 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8604 goto cleanup;
8605
8606 _cairo_output_stream_printf (surface->output, "q\n");
8607 status = _cairo_pdf_surface_paint_pattern (surface,
8608 op,
8609 source,
8610 CAIRO_ANALYSIS_SOURCE_MASK,
8611 &extents.bounded,
8612 alpha,
8613 FALSE0); /* mask */
8614 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8615 goto cleanup;
8616
8617 _cairo_output_stream_printf (surface->output, "Q\n");
8618 _cairo_composite_rectangles_fini (&extents);
8619 return _cairo_output_stream_get_status (surface->output);
8620 }
8621
8622 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
8623 if (unlikely (group == NULL)(__builtin_expect (!!(group == ((void*)0)), 0))) {
8624 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8625 goto cleanup;
8626 }
8627
8628 group->operation = PDF_MASK;
8629 status = _cairo_pattern_create_copy (&group->source, source);
8630 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
8631 _cairo_pdf_smask_group_destroy (group);
8632 goto cleanup;
8633 }
8634 status = _cairo_pattern_create_copy (&group->mask, mask);
8635 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
8636 _cairo_pdf_smask_group_destroy (group);
8637 goto cleanup;
8638 }
8639 group->source_res = _cairo_pdf_surface_new_object (surface);
8640 if (group->source_res.id == 0) {
8641 _cairo_pdf_smask_group_destroy (group);
8642 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8643 goto cleanup;
8644 }
8645
8646 status = _cairo_pdf_surface_add_smask_group (surface, group);
8647 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
8648 _cairo_pdf_smask_group_destroy (group);
8649 goto cleanup;
8650 }
8651
8652 status = _cairo_pdf_surface_add_smask (surface, group->group_res);
8653 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8654 goto cleanup;
8655
8656 status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
8657 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8658 goto cleanup;
8659
8660 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8661 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8662 goto cleanup;
8663
8664 _cairo_output_stream_printf (surface->output,
8665 "q /s%d gs /x%d Do Q\n",
8666 group->group_res.id,
8667 group->source_res.id);
8668
8669 _cairo_composite_rectangles_fini (&extents);
8670 return _cairo_output_stream_get_status (surface->output);
8671
8672cleanup:
8673 _cairo_composite_rectangles_fini (&extents);
8674 return status;
8675}
8676
8677static cairo_int_status_t
8678_cairo_pdf_surface_stroke (void *abstract_surface,
8679 cairo_operator_t op,
8680 const cairo_pattern_t *source,
8681 const cairo_path_fixed_t *path,
8682 const cairo_stroke_style_t *style,
8683 const cairo_matrix_t *ctm,
8684 const cairo_matrix_t *ctm_inverse,
8685 double tolerance,
8686 cairo_antialias_t antialias,
8687 const cairo_clip_t *clip)
8688{
8689 cairo_pdf_surface_t *surface = abstract_surface;
8690 cairo_pdf_smask_group_t *group;
8691 cairo_pdf_resource_t pattern_res, gstate_res;
8692 cairo_composite_rectangles_t extents;
8693 cairo_int_status_t status;
8694
8695 status = _cairo_composite_rectangles_init_for_stroke (&extents,
8696 &surface->base,
8697 op, source,
8698 path, style, ctm,
8699 clip);
8700 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8701 return status;
8702
8703 /* use the more accurate extents */
8704 if (extents.is_bounded) {
8705 cairo_rectangle_int_t mask;
8706 cairo_box_t box;
8707
8708 status = _cairo_path_fixed_stroke_extents (path, style,
8709 ctm, ctm_inverse,
8710 tolerance,
8711 &mask);
8712 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8713 goto cleanup;
8714
8715 _cairo_box_from_rectangle (&box, &mask);
8716 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
8717 &box);
8718 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8719 goto cleanup;
8720 }
8721
8722 status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
8723 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8724 goto cleanup;
8725
8726 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
8727 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
8728 goto cleanup;
8729 }
8730
8731 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded))((void) sizeof ((_cairo_pdf_surface_operation_supported (surface
, op, source, &extents.bounded)) ? 1 : 0), __extension__ (
{ if (_cairo_pdf_surface_operation_supported (surface, op, source
, &extents.bounded)) ; else __assert_fail ("_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded)"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 8731, __extension__ __PRETTY_FUNCTION__); }))
;
8732
8733 status = _cairo_pdf_surface_set_clip (surface, &extents);
8734 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8735 goto cleanup;
8736
8737 pattern_res.id = 0;
8738 gstate_res.id = 0;
8739 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
8740 CAIRO_ANALYSIS_SOURCE_STROKE,
8741 &extents.bounded,
8742 &pattern_res, &gstate_res);
8743 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8744 goto cleanup;
8745
8746 status = _cairo_pdf_surface_select_operator (surface, op);
8747 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8748 goto cleanup;
8749
8750 if (gstate_res.id != 0) {
8751 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
8752 if (unlikely (group == NULL)(__builtin_expect (!!(group == ((void*)0)), 0))) {
8753 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8754 goto cleanup;
8755 }
8756
8757 group->operation = PDF_STROKE;
8758 status = _cairo_pattern_create_copy (&group->source, source);
8759 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
8760 _cairo_pdf_smask_group_destroy (group);
8761 goto cleanup;
8762 }
8763 group->source_res = pattern_res;
8764 status = _cairo_path_fixed_init_copy (&group->path, path);
8765 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
8766 _cairo_pdf_smask_group_destroy (group);
8767 goto cleanup;
8768 }
8769
8770 group->style = *style;
8771 group->ctm = *ctm;
8772 group->ctm_inverse = *ctm_inverse;
8773 status = _cairo_pdf_surface_add_smask_group (surface, group);
8774 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
8775 _cairo_pdf_smask_group_destroy (group);
8776 goto cleanup;
8777 }
8778
8779 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
8780 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8781 goto cleanup;
8782
8783 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
8784 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8785 goto cleanup;
8786
8787 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8788 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8789 goto cleanup;
8790
8791 _cairo_output_stream_printf (surface->output,
8792 "q /s%d gs /x%d Do Q\n",
8793 gstate_res.id,
8794 group->group_res.id);
8795 } else {
8796 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE1);
8797 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8798 goto cleanup;
8799
8800 status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
8801 path,
8802 style,
8803 ctm,
8804 ctm_inverse);
8805 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8806 goto cleanup;
8807
8808 status = _cairo_pdf_surface_unselect_pattern (surface);
8809 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8810 goto cleanup;
8811 }
8812
8813 _cairo_composite_rectangles_fini (&extents);
8814 return _cairo_output_stream_get_status (surface->output);
8815
8816cleanup:
8817 _cairo_composite_rectangles_fini (&extents);
8818 return status;
8819}
8820
8821static cairo_int_status_t
8822_cairo_pdf_surface_fill (void *abstract_surface,
8823 cairo_operator_t op,
8824 const cairo_pattern_t *source,
8825 const cairo_path_fixed_t*path,
8826 cairo_fill_rule_t fill_rule,
8827 double tolerance,
8828 cairo_antialias_t antialias,
8829 const cairo_clip_t *clip)
8830{
8831 cairo_pdf_surface_t *surface = abstract_surface;
8832 cairo_int_status_t status;
8833 cairo_pdf_smask_group_t *group;
8834 cairo_pdf_resource_t pattern_res, gstate_res;
8835 cairo_composite_rectangles_t extents;
8836
8837 status = _cairo_composite_rectangles_init_for_fill (&extents,
8838 &surface->base,
8839 op, source, path,
8840 clip);
8841 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8842 return status;
8843
8844 /* use the more accurate extents */
8845 if (extents.is_bounded) {
8846 cairo_rectangle_int_t mask;
8847 cairo_box_t box;
8848
8849 _cairo_path_fixed_fill_extents (path,
8850 fill_rule,
8851 tolerance,
8852 &mask);
8853
8854 _cairo_box_from_rectangle (&box, &mask);
8855 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
8856 &box);
8857 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8858 goto cleanup;
8859 }
8860
8861 status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
8862 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8863 goto cleanup;
8864
8865 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
8866 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
8867 goto cleanup;
8868 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
8869 status = _cairo_pdf_surface_start_fallback (surface);
8870 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8871 goto cleanup;
8872 }
8873
8874 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded))((void) sizeof ((_cairo_pdf_surface_operation_supported (surface
, op, source, &extents.bounded)) ? 1 : 0), __extension__ (
{ if (_cairo_pdf_surface_operation_supported (surface, op, source
, &extents.bounded)) ; else __assert_fail ("_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded)"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 8874, __extension__ __PRETTY_FUNCTION__); }))
;
8875
8876 status = _cairo_pdf_surface_set_clip (surface, &extents);
8877 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8878 goto cleanup;
8879
8880 status = _cairo_pdf_surface_select_operator (surface, op);
8881 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8882 goto cleanup;
8883
8884 if (_can_paint_pattern (source)) {
8885 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8886 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8887 goto cleanup;
8888
8889 _cairo_output_stream_printf (surface->output, "q\n");
8890 status = _cairo_pdf_operators_clip (&surface->pdf_operators,
8891 path,
8892 fill_rule);
8893 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8894 goto cleanup;
8895
8896 status = _cairo_pdf_surface_paint_pattern (surface,
8897 op,
8898 source,
8899 CAIRO_ANALYSIS_SOURCE_FILL,
8900 &extents.bounded,
8901 1.0, /* alpha */
8902 FALSE0); /* mask */
8903 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8904 goto cleanup;
8905
8906 _cairo_output_stream_printf (surface->output, "Q\n");
8907 status = _cairo_output_stream_get_status (surface->output);
8908 goto cleanup;
8909 }
8910
8911 pattern_res.id = 0;
8912 gstate_res.id = 0;
8913 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
8914 CAIRO_ANALYSIS_SOURCE_FILL,
8915 &extents.bounded,
8916 &pattern_res, &gstate_res);
8917 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8918 goto cleanup;
8919
8920 if (gstate_res.id != 0) {
8921 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
8922 if (unlikely (group == NULL)(__builtin_expect (!!(group == ((void*)0)), 0))) {
8923 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8924 goto cleanup;
8925 }
8926
8927 group->operation = PDF_FILL;
8928 status = _cairo_pattern_create_copy (&group->source, source);
8929 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
8930 _cairo_pdf_smask_group_destroy (group);
8931 goto cleanup;
8932 }
8933 group->source_res = pattern_res;
8934 status = _cairo_path_fixed_init_copy (&group->path, path);
8935 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
8936 _cairo_pdf_smask_group_destroy (group);
8937 goto cleanup;
8938 }
8939
8940 group->fill_rule = fill_rule;
8941 status = _cairo_pdf_surface_add_smask_group (surface, group);
8942 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
8943 _cairo_pdf_smask_group_destroy (group);
8944 goto cleanup;
8945 }
8946
8947 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
8948 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8949 goto cleanup;
8950
8951 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
8952 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8953 goto cleanup;
8954
8955 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8956 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8957 goto cleanup;
8958
8959 _cairo_output_stream_printf (surface->output,
8960 "q /s%d gs /x%d Do Q\n",
8961 gstate_res.id,
8962 group->group_res.id);
8963 } else {
8964 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE0);
8965 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8966 goto cleanup;
8967
8968 status = _cairo_pdf_operators_fill (&surface->pdf_operators,
8969 path,
8970 fill_rule);
8971 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8972 goto cleanup;
8973
8974 status = _cairo_pdf_surface_unselect_pattern (surface);
8975 if (unlikely (status)(__builtin_expect (!!(status), 0)))
8976 goto cleanup;
8977 }
8978
8979 _cairo_composite_rectangles_fini (&extents);
8980 return _cairo_output_stream_get_status (surface->output);
8981
8982cleanup:
8983 _cairo_composite_rectangles_fini (&extents);
8984 return status;
8985}
8986
8987static cairo_int_status_t
8988_cairo_pdf_surface_fill_stroke (void *abstract_surface,
8989 cairo_operator_t fill_op,
8990 const cairo_pattern_t *fill_source,
8991 cairo_fill_rule_t fill_rule,
8992 double fill_tolerance,
8993 cairo_antialias_t fill_antialias,
8994 const cairo_path_fixed_t*path,
8995 cairo_operator_t stroke_op,
8996 const cairo_pattern_t *stroke_source,
8997 const cairo_stroke_style_t *stroke_style,
8998 const cairo_matrix_t *stroke_ctm,
8999 const cairo_matrix_t *stroke_ctm_inverse,
9000 double stroke_tolerance,
9001 cairo_antialias_t stroke_antialias,
9002 const cairo_clip_t *clip)
9003{
9004 cairo_pdf_surface_t *surface = abstract_surface;
9005 cairo_int_status_t status;
9006 cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res;
9007 cairo_composite_rectangles_t extents;
9008
9009 /* During analysis we return unsupported and let the _fill and
9010 * _stroke functions that are on the fallback path do the analysis
9011 * for us. During render we may still encounter unsupported
9012 * combinations of fill/stroke patterns. However we can return
9013 * unsupported anytime to let the _fill and _stroke functions take
9014 * over.
9015 */
9016 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
9017 return CAIRO_INT_STATUS_UNSUPPORTED;
9018
9019 /* PDF rendering of fill-stroke is not the same as cairo when
9020 * either the fill or stroke is not opaque.
9021 */
9022 if ( !_cairo_pattern_is_opaque (fill_source, NULL((void*)0)) ||
9023 !_cairo_pattern_is_opaque (stroke_source, NULL((void*)0)))
9024 {
9025 return CAIRO_INT_STATUS_UNSUPPORTED;
9026 }
9027
9028 if (fill_op != stroke_op)
9029 return CAIRO_INT_STATUS_UNSUPPORTED;
9030
9031 /* Compute the operation extents using the stroke which will naturally
9032 * be larger than the fill extents.
9033 */
9034 status = _cairo_composite_rectangles_init_for_stroke (&extents,
9035 &surface->base,
9036 stroke_op, stroke_source,
9037 path, stroke_style, stroke_ctm,
9038 clip);
9039 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9040 return status;
9041
9042 /* use the more accurate extents */
9043 if (extents.is_bounded) {
9044 cairo_rectangle_int_t mask;
9045 cairo_box_t box;
9046
9047 status = _cairo_path_fixed_stroke_extents (path, stroke_style,
9048 stroke_ctm, stroke_ctm_inverse,
9049 stroke_tolerance,
9050 &mask);
9051 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9052 goto cleanup;
9053
9054 _cairo_box_from_rectangle (&box, &mask);
9055 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
9056 &box);
9057 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9058 goto cleanup;
9059 }
9060
9061 status = _cairo_pdf_surface_set_clip (surface, &extents);
9062 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9063 goto cleanup;
9064
9065 status = _cairo_pdf_surface_select_operator (surface, fill_op);
9066 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9067 goto cleanup;
9068
9069 /* use the more accurate extents */
9070 if (extents.is_bounded) {
9071 cairo_rectangle_int_t mask;
9072 cairo_box_t box;
9073
9074 _cairo_path_fixed_fill_extents (path,
9075 fill_rule,
9076 fill_tolerance,
9077 &mask);
9078
9079 _cairo_box_from_rectangle (&box, &mask);
9080 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
9081 &box);
9082 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9083 goto cleanup;
9084 }
9085
9086 status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
9087 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9088 goto cleanup;
9089
9090 fill_pattern_res.id = 0;
9091 gstate_res.id = 0;
9092 status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
9093 fill_op,
9094 CAIRO_ANALYSIS_SOURCE_FILL,
9095 &extents.bounded,
9096 &fill_pattern_res,
9097 &gstate_res);
9098 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9099 goto cleanup;
9100
9101 assert (gstate_res.id == 0)((void) sizeof ((gstate_res.id == 0) ? 1 : 0), __extension__ (
{ if (gstate_res.id == 0) ; else __assert_fail ("gstate_res.id == 0"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 9101, __extension__ __PRETTY_FUNCTION__); }))
;
9102
9103 stroke_pattern_res.id = 0;
9104 gstate_res.id = 0;
9105 status = _cairo_pdf_surface_add_pdf_pattern (surface,
9106 stroke_source,
9107 stroke_op,
9108 CAIRO_ANALYSIS_SOURCE_STROKE,
9109 &extents.bounded,
9110 &stroke_pattern_res,
9111 &gstate_res);
9112 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9113 goto cleanup;
9114
9115 assert (gstate_res.id == 0)((void) sizeof ((gstate_res.id == 0) ? 1 : 0), __extension__ (
{ if (gstate_res.id == 0) ; else __assert_fail ("gstate_res.id == 0"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 9115, __extension__ __PRETTY_FUNCTION__); }))
;
9116
9117 /* As PDF has separate graphics state for fill and stroke we can
9118 * select both at the same time */
9119 status = _cairo_pdf_surface_select_pattern (surface, fill_source,
9120 fill_pattern_res, FALSE0);
9121 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9122 goto cleanup;
9123
9124 status = _cairo_pdf_surface_select_pattern (surface, stroke_source,
9125 stroke_pattern_res, TRUE1);
9126 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9127 goto cleanup;
9128
9129 status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators,
9130 path,
9131 fill_rule,
9132 stroke_style,
9133 stroke_ctm,
9134 stroke_ctm_inverse);
9135 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9136 goto cleanup;
9137
9138 status = _cairo_pdf_surface_unselect_pattern (surface);
9139 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9140 goto cleanup;
9141
9142 _cairo_composite_rectangles_fini (&extents);
9143 return _cairo_output_stream_get_status (surface->output);
9144
9145cleanup:
9146 _cairo_composite_rectangles_fini (&extents);
9147 return status;
9148}
9149
9150static cairo_bool_t
9151_cairo_pdf_surface_has_show_text_glyphs (void *abstract_surface)
9152{
9153 return TRUE1;
9154}
9155
9156static cairo_int_status_t
9157_cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
9158 cairo_operator_t op,
9159 const cairo_pattern_t *source,
9160 const char *utf8,
9161 int utf8_len,
9162 cairo_glyph_t *glyphs,
9163 int num_glyphs,
9164 const cairo_text_cluster_t *clusters,
9165 int num_clusters,
9166 cairo_text_cluster_flags_t cluster_flags,
9167 cairo_scaled_font_t *scaled_font,
9168 const cairo_clip_t *clip)
9169{
9170 cairo_pdf_surface_t *surface = abstract_surface;
9171 cairo_pdf_smask_group_t *group;
9172 cairo_pdf_resource_t pattern_res, gstate_res;
9173 cairo_composite_rectangles_t extents;
9174 cairo_bool_t overlap;
9175 cairo_int_status_t status;
9176
9177 status = _cairo_composite_rectangles_init_for_glyphs (&extents,
9178 &surface->base,
9179 op, source,
9180 scaled_font,
9181 glyphs, num_glyphs,
9182 clip,
9183 &overlap);
9184 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9185 return status;
9186
9187 status = _cairo_pdf_interchange_add_content (surface);
9188 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9189 return status;
9190
9191 status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
9192 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9193 return status;
9194
9195 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
9196 /* Enabling text in Type 3 fonts currently crashes cairo. Most
9197 * PDF viewers don't seem to suport text in Type 3 so we let
9198 * this go to image fallback.
9199 */
9200 if (surface->type3_replay)
9201 return CAIRO_INT_STATUS_UNSUPPORTED;
9202
9203 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
9204 goto cleanup;
9205 }
9206
9207 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded))((void) sizeof ((_cairo_pdf_surface_operation_supported (surface
, op, source, &extents.bounded)) ? 1 : 0), __extension__ (
{ if (_cairo_pdf_surface_operation_supported (surface, op, source
, &extents.bounded)) ; else __assert_fail ("_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded)"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c"
, 9207, __extension__ __PRETTY_FUNCTION__); }))
;
9208
9209 status = _cairo_pdf_surface_set_clip (surface, &extents);
9210 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9211 goto cleanup;
9212
9213 pattern_res.id = 0;
9214 gstate_res.id = 0;
9215 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
9216 CAIRO_ANALYSIS_SOURCE_SHOW_GLYPHS,
9217 &extents.bounded,
9218 &pattern_res, &gstate_res);
9219 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9220 goto cleanup;
9221
9222 status = _cairo_pdf_surface_select_operator (surface, op);
9223 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9224 goto cleanup;
9225
9226 if (gstate_res.id != 0) {
9227 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
9228 if (unlikely (group == NULL)(__builtin_expect (!!(group == ((void*)0)), 0))) {
9229 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
9230 goto cleanup;
9231 }
9232
9233 group->operation = PDF_SHOW_GLYPHS;
9234 status = _cairo_pattern_create_copy (&group->source, source);
9235 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
9236 _cairo_pdf_smask_group_destroy (group);
9237 goto cleanup;
9238 }
9239 group->source_res = pattern_res;
9240
9241 if (utf8_len) {
9242 group->utf8 = _cairo_malloc (utf8_len)((utf8_len) != 0 ? malloc(utf8_len) : ((void*)0));
9243 if (unlikely (group->utf8 == NULL)(__builtin_expect (!!(group->utf8 == ((void*)0)), 0))) {
9244 _cairo_pdf_smask_group_destroy (group);
9245 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
9246 goto cleanup;
9247 }
9248 memcpy (group->utf8, utf8, utf8_len);
9249 }
9250 group->utf8_len = utf8_len;
9251
9252 if (num_glyphs) {
9253 group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
9254 if (unlikely (group->glyphs == NULL)(__builtin_expect (!!(group->glyphs == ((void*)0)), 0))) {
9255 _cairo_pdf_smask_group_destroy (group);
9256 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
9257 goto cleanup;
9258 }
9259 memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
9260 }
9261 group->num_glyphs = num_glyphs;
9262
9263 if (num_clusters) {
9264 group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
9265 if (unlikely (group->clusters == NULL)(__builtin_expect (!!(group->clusters == ((void*)0)), 0))) {
9266 _cairo_pdf_smask_group_destroy (group);
9267 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
9268 goto cleanup;
9269 }
9270 memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
9271 }
9272 group->num_clusters = num_clusters;
9273
9274 group->scaled_font = cairo_scaled_font_reference_moz_cairo_scaled_font_reference (scaled_font);
9275 status = _cairo_pdf_surface_add_smask_group (surface, group);
9276 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
9277 _cairo_pdf_smask_group_destroy (group);
9278 goto cleanup;
9279 }
9280
9281 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
9282 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9283 goto cleanup;
9284
9285 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
9286 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9287 goto cleanup;
9288
9289 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
9290 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9291 goto cleanup;
9292
9293 _cairo_output_stream_printf (surface->output,
9294 "q /s%d gs /x%d Do Q\n",
9295 gstate_res.id,
9296 group->group_res.id);
9297 } else {
9298 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE0);
9299 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9300 goto cleanup;
9301
9302 /* Each call to show_glyphs() with a transclucent pattern must
9303 * be in a separate text object otherwise overlapping text
9304 * from separate calls to show_glyphs will not composite with
9305 * each other. */
9306 if (! _cairo_pattern_is_opaque (source, &extents.bounded)) {
9307 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
9308 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9309 goto cleanup;
9310 }
9311
9312 status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
9313 utf8, utf8_len,
9314 glyphs, num_glyphs,
9315 clusters, num_clusters,
9316 cluster_flags,
9317 scaled_font);
9318 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9319 goto cleanup;
9320
9321 status = _cairo_pdf_surface_unselect_pattern (surface);
9322 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9323 goto cleanup;
9324 }
9325
9326 _cairo_composite_rectangles_fini (&extents);
9327 return _cairo_output_stream_get_status (surface->output);
9328
9329cleanup:
9330 _cairo_composite_rectangles_fini (&extents);
9331 return status;
9332}
9333
9334static const char **
9335_cairo_pdf_surface_get_supported_mime_types (void *abstract_surface)
9336{
9337 return _cairo_pdf_supported_mime_types;
9338}
9339
9340static cairo_int_status_t
9341_cairo_pdf_surface_tag (void *abstract_surface,
9342 cairo_bool_t begin,
9343 const char *tag_name,
9344 const char *attributes)
9345
9346{
9347 cairo_pdf_surface_t *surface = abstract_surface;
9348 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
9349
9350 if (begin)
9351 status = _cairo_pdf_interchange_tag_begin (surface, tag_name, attributes);
9352 else
9353 status = _cairo_pdf_interchange_tag_end (surface, tag_name);
9354
9355 return status;
9356}
9357
9358static cairo_int_status_t
9359_cairo_pdf_surface_command_id (void *abstract_surface,
9360 unsigned int recording_id,
9361 unsigned int command_id)
9362{
9363 cairo_pdf_surface_t *surface = abstract_surface;
9364
9365 return _cairo_pdf_interchange_command_id (surface, recording_id, command_id);
9366}
9367
9368/* The Type 3 font subset support will the embed the
9369 * CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE image if vector operations
9370 * are not supported. The only case we don't currently handle is if a
9371 * foreground color is used.
9372 */
9373static cairo_bool_t
9374_cairo_pdf_surface_supports_color_glyph (void *abstract_surface,
9375 cairo_scaled_font_t *scaled_font,
9376 unsigned long glyph_index)
9377{
9378 cairo_pdf_surface_t *surface = abstract_surface;
9379 cairo_pdf_color_glyph_t glyph_key;
9380 cairo_pdf_color_glyph_t *glyph_entry;
9381 cairo_scaled_glyph_t *scaled_glyph;
9382 cairo_status_t status;
9383
9384 glyph_key.scaled_font = scaled_font;
9385 glyph_key.glyph_index = glyph_index;
9386
9387 _cairo_pdf_color_glyph_init_key (&glyph_key);
9388 glyph_entry = _cairo_hash_table_lookup (surface->color_glyphs, &glyph_key.base);
9389 if (glyph_entry)
9390 return glyph_entry->supported;
9391
9392 glyph_entry = _cairo_malloc (sizeof (cairo_pdf_color_glyph_t))((sizeof (cairo_pdf_color_glyph_t)) != 0 ? malloc(sizeof (cairo_pdf_color_glyph_t
)) : ((void*)0))
;
9393 if (glyph_entry == NULL((void*)0)) {
9394 status = _cairo_surface_set_error (&surface->base,
9395 _cairo_error (CAIRO_STATUS_NO_MEMORY));
9396 return FALSE0;
9397 }
9398
9399 glyph_entry->scaled_font = cairo_scaled_font_reference_moz_cairo_scaled_font_reference (scaled_font);
9400 glyph_entry->glyph_index = glyph_index;
9401 _cairo_pdf_color_glyph_init_key (glyph_entry);
9402
9403 glyph_entry->supported = FALSE0;
9404 _cairo_scaled_font_freeze_cache (scaled_font);
9405 status = _cairo_scaled_glyph_lookup (scaled_font,
9406 glyph_index,
9407 CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
9408 NULL((void*)0), /* foreground color */
9409 &scaled_glyph);
9410 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9411 goto done;
9412
9413 glyph_entry->supported = !(scaled_glyph->recording_uses_foreground_color ||
9414 scaled_glyph->recording_uses_foreground_marker);
9415
9416 done:
9417 _cairo_scaled_font_thaw_cache (scaled_font);
9418
9419 status = _cairo_hash_table_insert (surface->color_glyphs,
9420 &glyph_entry->base);
9421 if (unlikely(status)(__builtin_expect (!!(status), 0))) {
9422 status = _cairo_surface_set_error (&surface->base,
9423 _cairo_error (CAIRO_STATUS_NO_MEMORY));
9424 return FALSE0;
9425 }
9426
9427 return glyph_entry->supported;
9428}
9429
9430static cairo_int_status_t
9431_cairo_pdf_surface_analyze_recording_surface(void *abstract_surface,
9432 const cairo_surface_pattern_t *recording_surface_pattern,
9433 unsigned int region_id,
9434 cairo_analysis_source_t source_type,
9435 cairo_bool_t begin)
9436{
9437 cairo_pdf_surface_t *surface = abstract_surface;
9438 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
9439
9440 if (begin) {
9441 status = _cairo_pdf_interchange_recording_source_surface_begin (
9442 surface,
9443 recording_surface_pattern,
9444 region_id,
9445 source_type);
9446 } else {
9447 status = _cairo_pdf_interchange_recording_source_surface_end (
9448 surface,
9449 recording_surface_pattern,
9450 region_id,
9451 source_type);
9452 }
9453
9454 return status;
9455}
9456
9457static cairo_int_status_t
9458_cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
9459 cairo_paginated_mode_t paginated_mode)
9460{
9461 cairo_pdf_surface_t *surface = abstract_surface;
9462 cairo_int_status_t status;
9463
9464 surface->paginated_mode = paginated_mode;
9465
9466 status = _cairo_pdf_interchange_begin_page_content (surface);
9467 if (unlikely (status)(__builtin_expect (!!(status), 0)))
9468 return status;
9469
9470 if (paginated_mode == CAIRO_PAGINATED_MODE_RENDER) {
9471 surface->surface_extents.x = 0;
9472 surface->surface_extents.y = 0;
9473 surface->surface_extents.width = ceil (surface->width);
9474 surface->surface_extents.height = ceil (surface->height);
9475 }
9476
9477 return CAIRO_INT_STATUS_SUCCESS;
9478}
9479
9480static const cairo_surface_backend_t cairo_pdf_surface_backend = {
9481 CAIRO_SURFACE_TYPE_PDF,
9482 _cairo_pdf_surface_finish,
9483
9484 _cairo_default_context_create,
9485
9486 NULL((void*)0), /* create similar: handled by wrapper */
9487 NULL((void*)0), /* create similar image */
9488 NULL((void*)0), /* map to image */
9489 NULL((void*)0), /* unmap image */
9490
9491 _cairo_surface_default_source,
9492 NULL((void*)0), /* acquire_source_image */
9493 NULL((void*)0), /* release_source_image */
9494 NULL((void*)0), /* snapshot */
9495
9496 NULL((void*)0), /* _cairo_pdf_surface_copy_page */
9497 _cairo_pdf_surface_show_page,
9498
9499 _cairo_pdf_surface_get_extents,
9500 _cairo_pdf_surface_get_font_options,
9501
9502 NULL((void*)0), /* flush */
9503 NULL((void*)0), /* mark_dirty_rectangle */
9504
9505 /* Here are the drawing functions */
9506 _cairo_pdf_surface_paint,
9507 _cairo_pdf_surface_mask,
9508 _cairo_pdf_surface_stroke,
9509 _cairo_pdf_surface_fill,
9510 _cairo_pdf_surface_fill_stroke,
9511 NULL((void*)0), /* show_glyphs */
9512 _cairo_pdf_surface_has_show_text_glyphs,
9513 _cairo_pdf_surface_show_text_glyphs,
9514 _cairo_pdf_surface_get_supported_mime_types,
9515 _cairo_pdf_surface_tag,
9516 _cairo_pdf_surface_supports_color_glyph,
9517 _cairo_pdf_surface_analyze_recording_surface,
9518 _cairo_pdf_surface_command_id,
9519};
9520
9521static const cairo_paginated_surface_backend_t
9522cairo_pdf_surface_paginated_backend = {
9523 _cairo_pdf_surface_start_page,
9524 _cairo_pdf_surface_set_paginated_mode,
9525 NULL((void*)0), /* set_bounding_box */
9526 _cairo_pdf_surface_has_fallback_images,
9527 _cairo_pdf_surface_supports_fine_grained_fallbacks,
9528 _cairo_pdf_surface_requires_thumbnail_image,
9529 _cairo_pdf_surface_set_thumbnail_image,
9530};