Bug Summary

File:root/firefox-clang/gfx/cairo/cairo/src/cairo-pdf-surface.c
Warning:line 1802, column 12
Dereference of null pointer (loaded from variable 'y_offset')

Annotated Source Code

Press '?' to see keyboard shortcuts

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