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
4 * Copyright © 2004 Red Hat, Inc
5 * Copyright © 2006 Red Hat, Inc
6 * Copyright © 2007, 2008 Adrian Johnson
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.
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
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/
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.
31 * The Original Code is the cairo graphics library.
33 * The Initial Developer of the Original Code is University of Southern
37 * Kristian Høgsberg <krh@redhat.com>
38 * Carl Worth <cworth@cworth.org>
39 * Adrian Johnson <ajohnson@redneon.com>
42 #define _BSD_SOURCE /* for snprintf() */
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"
50 #include "cairo-array-private.h"
51 #include "cairo-analysis-surface-private.h"
52 #include "cairo-composite-rectangles-private.h"
53 #include "cairo-default-context-private.h"
54 #include "cairo-error-private.h"
55 #include "cairo-image-surface-inline.h"
56 #include "cairo-image-info-private.h"
57 #include "cairo-recording-surface-private.h"
58 #include "cairo-output-stream-private.h"
59 #include "cairo-paginated-private.h"
60 #include "cairo-scaled-font-subsets-private.h"
61 #include "cairo-surface-clipper-private.h"
62 #include "cairo-surface-snapshot-inline.h"
63 #include "cairo-surface-subsurface-private.h"
64 #include "cairo-type3-glyph-surface-private.h"
71 * - We embed an image in the stream each time it's composited. We
72 * could add generation counters to surfaces and remember the stream
73 * ID for a particular generation for a particular surface.
75 * - Backend specific meta data.
79 * Page Structure of the Generated PDF:
81 * Each page requiring fallbacks images contains a knockout group at
82 * the top level. The first operation of the knockout group paints a
83 * group containing all the supported drawing operations. Fallback
84 * images (if any) are painted in the knockout group. This ensures
85 * that fallback images do not composite with any content under the
90 * This PDF surface has three types of streams:
95 * Calling _cairo_output_stream_printf (surface->output, ...) will
96 * write to the currently open stream.
99 * A PDF Stream may be opened and closed with the following functions:
100 * _cairo_pdf_surface_open stream ()
101 * _cairo_pdf_surface_close_stream ()
103 * PDF Streams are written directly to the PDF file. They are used for
104 * fonts, images and patterns.
107 * The Content Stream is opened and closed with the following functions:
108 * _cairo_pdf_surface_open_content_stream ()
109 * _cairo_pdf_surface_close_content_stream ()
111 * The Content Stream contains the text and graphics operators.
114 * A Group Stream may be opened and closed with the following functions:
115 * _cairo_pdf_surface_open_group ()
116 * _cairo_pdf_surface_close_group ()
118 * A Group Stream is a Form XObject. It is used for short sequences
119 * of operators. As the content is very short the group is stored in
120 * memory until it is closed. This allows some optimization such as
121 * including the Resource dictionary and stream length inside the
122 * XObject instead of using an indirect object.
127 * @Title: PDF Surfaces
128 * @Short_Description: Rendering PDF documents
129 * @See_Also: #cairo_surface_t
131 * The PDF surface is used to render cairo graphics to Adobe
132 * PDF files and is a multi-page vector surface backend.
134 * The following mime types are supported: %CAIRO_MIME_TYPE_JPEG,
135 * %CAIRO_MIME_TYPE_JP2, %CAIRO_MIME_TYPE_UNIQUE_ID,
136 * %CAIRO_MIME_TYPE_JBIG2, %CAIRO_MIME_TYPE_JBIG2_GLOBAL,
137 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
139 * JBIG2 data in PDF must be in the embedded format as descibed in
140 * ISO/IEC 11544. Image specific JBIG2 data must be in
141 * %CAIRO_MIME_TYPE_JBIG2. Any global segments in the JBIG2 data
142 * (segments with page association field set to 0) must be in
143 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data may be shared by
144 * multiple images. All images sharing the same global data must set
145 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID to a unique identifer. At least
146 * one of the images must provide the global data using
147 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data will only be
148 * embedded once but shared by all JBIG2 images with the same
149 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
153 _cairo_pdf_surface_get_extents (void *abstract_surface,
154 cairo_rectangle_int_t *rectangle);
157 * CAIRO_HAS_PDF_SURFACE:
159 * Defined if the PDF surface backend is available.
160 * This macro can be used to conditionally compile backend-specific code.
165 static const cairo_pdf_version_t _cairo_pdf_versions[] =
167 CAIRO_PDF_VERSION_1_4,
168 CAIRO_PDF_VERSION_1_5
171 #define CAIRO_PDF_VERSION_LAST ARRAY_LENGTH (_cairo_pdf_versions)
173 static const char * _cairo_pdf_version_strings[CAIRO_PDF_VERSION_LAST] =
179 static const char *_cairo_pdf_supported_mime_types[] =
181 CAIRO_MIME_TYPE_JPEG,
183 CAIRO_MIME_TYPE_UNIQUE_ID,
184 CAIRO_MIME_TYPE_JBIG2,
185 CAIRO_MIME_TYPE_JBIG2_GLOBAL,
186 CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
190 typedef struct _cairo_pdf_object {
192 } cairo_pdf_object_t;
194 typedef struct _cairo_pdf_font {
195 unsigned int font_id;
196 unsigned int subset_id;
197 cairo_pdf_resource_t subset_resource;
200 typedef struct _cairo_pdf_rgb_linear_function {
201 cairo_pdf_resource_t resource;
204 } cairo_pdf_rgb_linear_function_t;
206 typedef struct _cairo_pdf_alpha_linear_function {
207 cairo_pdf_resource_t resource;
210 } cairo_pdf_alpha_linear_function_t;
212 static cairo_pdf_resource_t
213 _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
216 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
219 _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
221 static cairo_int_status_t
222 _cairo_pdf_surface_add_font (unsigned int font_id,
223 unsigned int subset_id,
227 _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
229 static cairo_int_status_t
230 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
231 cairo_pdf_resource_t *resource,
232 cairo_bool_t compressed,
234 ...) CAIRO_PRINTF_FORMAT(4, 5);
235 static cairo_int_status_t
236 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface);
238 static cairo_int_status_t
239 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
242 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
244 static cairo_pdf_resource_t
245 _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface);
247 static cairo_pdf_resource_t
248 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface);
251 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
253 static cairo_int_status_t
254 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
256 static cairo_int_status_t
257 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
260 _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b);
262 static const cairo_surface_backend_t cairo_pdf_surface_backend;
263 static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
265 static cairo_pdf_resource_t
266 _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
268 cairo_pdf_resource_t resource;
269 cairo_int_status_t status;
270 cairo_pdf_object_t object;
272 object.offset = _cairo_output_stream_get_position (surface->output);
274 status = _cairo_array_append (&surface->objects, &object);
275 if (unlikely (status)) {
280 resource = surface->next_available_resource;
281 surface->next_available_resource.id++;
287 _cairo_pdf_surface_update_object (cairo_pdf_surface_t *surface,
288 cairo_pdf_resource_t resource)
290 cairo_pdf_object_t *object;
292 object = _cairo_array_index (&surface->objects, resource.id - 1);
294 object->offset = _cairo_output_stream_get_position (surface->output);
298 _cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
302 surface->width = width;
303 surface->height = height;
304 cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
305 _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
306 &surface->cairo_to_pdf);
310 _path_covers_bbox (cairo_pdf_surface_t *surface,
311 cairo_path_fixed_t *path)
315 return _cairo_path_fixed_is_box (path, &box) &&
318 box.p2.x >= _cairo_fixed_from_double (surface->width) &&
319 box.p2.y >= _cairo_fixed_from_double (surface->height);
322 static cairo_status_t
323 _cairo_pdf_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
324 cairo_path_fixed_t *path,
325 cairo_fill_rule_t fill_rule,
327 cairo_antialias_t antialias)
329 cairo_pdf_surface_t *surface = cairo_container_of (clipper,
332 cairo_int_status_t status;
334 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
335 if (unlikely (status))
339 _cairo_output_stream_printf (surface->output, "Q q\n");
341 surface->current_pattern_is_solid_color = FALSE;
342 _cairo_pdf_operators_reset (&surface->pdf_operators);
344 return CAIRO_STATUS_SUCCESS;
347 if (_path_covers_bbox (surface, path))
348 return CAIRO_STATUS_SUCCESS;
350 return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
353 static cairo_surface_t *
354 _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
358 cairo_pdf_surface_t *surface;
359 cairo_status_t status, status_ignored;
361 surface = malloc (sizeof (cairo_pdf_surface_t));
362 if (unlikely (surface == NULL)) {
363 /* destroy stream on behalf of caller */
364 status = _cairo_output_stream_destroy (output);
365 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
368 _cairo_surface_init (&surface->base,
369 &cairo_pdf_surface_backend,
371 CAIRO_CONTENT_COLOR_ALPHA);
373 surface->output = output;
374 surface->width = width;
375 surface->height = height;
376 cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
378 _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
379 _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
380 _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
381 _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
382 _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
383 _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
384 _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t));
386 _cairo_array_init (&surface->page_patterns, sizeof (cairo_pdf_pattern_t));
387 _cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t));
388 _cairo_array_init (&surface->jbig2_global, sizeof (cairo_pdf_jbig2_global_t));
389 surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal);
390 if (unlikely (surface->all_surfaces == NULL)) {
391 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
395 _cairo_pdf_group_resources_init (&surface->resources);
397 surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
398 if (! surface->font_subsets) {
399 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
403 _cairo_scaled_font_subsets_enable_latin_subset (surface->font_subsets, TRUE);
405 surface->next_available_resource.id = 1;
406 surface->pages_resource = _cairo_pdf_surface_new_object (surface);
407 if (surface->pages_resource.id == 0) {
408 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
412 surface->pdf_version = CAIRO_PDF_VERSION_1_5;
413 surface->compress_content = TRUE;
414 surface->pdf_stream.active = FALSE;
415 surface->pdf_stream.old_output = NULL;
416 surface->group_stream.active = FALSE;
417 surface->group_stream.stream = NULL;
418 surface->group_stream.mem_stream = NULL;
420 surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
422 surface->force_fallbacks = FALSE;
423 surface->select_pattern_gstate_saved = FALSE;
424 surface->current_pattern_is_solid_color = FALSE;
425 surface->current_operator = CAIRO_OPERATOR_OVER;
426 surface->header_emitted = FALSE;
428 _cairo_surface_clipper_init (&surface->clipper,
429 _cairo_pdf_surface_clipper_intersect_clip_path);
431 _cairo_pdf_operators_init (&surface->pdf_operators,
433 &surface->cairo_to_pdf,
434 surface->font_subsets,
436 _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
437 _cairo_pdf_surface_add_font,
439 _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators, TRUE);
441 surface->paginated_surface = _cairo_paginated_surface_create (
443 CAIRO_CONTENT_COLOR_ALPHA,
444 &cairo_pdf_surface_paginated_backend);
446 status = surface->paginated_surface->status;
447 if (status == CAIRO_STATUS_SUCCESS) {
448 /* paginated keeps the only reference to surface now, drop ours */
449 cairo_surface_destroy (&surface->base);
450 return surface->paginated_surface;
454 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
456 _cairo_hash_table_destroy (surface->all_surfaces);
458 _cairo_array_fini (&surface->objects);
461 /* destroy stream on behalf of caller */
462 status_ignored = _cairo_output_stream_destroy (output);
464 return _cairo_surface_create_in_error (status);
468 * cairo_pdf_surface_create_for_stream:
469 * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
470 * to indicate a no-op @write_func. With a no-op @write_func,
471 * the surface may be queried or used as a source without
472 * generating any temporary files.
473 * @closure: the closure argument for @write_func
474 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
475 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
477 * Creates a PDF surface of the specified size in points to be written
478 * incrementally to the stream represented by @write_func and @closure.
480 * Return value: a pointer to the newly created surface. The caller
481 * owns the surface and should call cairo_surface_destroy() when done
484 * This function always returns a valid pointer, but it will return a
485 * pointer to a "nil" surface if an error such as out of memory
486 * occurs. You can use cairo_surface_status() to check for this.
491 cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func,
493 double width_in_points,
494 double height_in_points)
496 cairo_output_stream_t *output;
498 output = _cairo_output_stream_create (write_func, NULL, closure);
499 if (_cairo_output_stream_get_status (output))
500 return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
502 return _cairo_pdf_surface_create_for_stream_internal (output,
508 * cairo_pdf_surface_create:
509 * @filename: a filename for the PDF output (must be writable), %NULL may be
510 * used to specify no output. This will generate a PDF surface that
511 * may be queried and used as a source, without generating a
513 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
514 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
516 * Creates a PDF surface of the specified size in points to be written
519 * Return value: a pointer to the newly created surface. The caller
520 * owns the surface and should call cairo_surface_destroy() when done
523 * This function always returns a valid pointer, but it will return a
524 * pointer to a "nil" surface if an error such as out of memory
525 * occurs. You can use cairo_surface_status() to check for this.
530 cairo_pdf_surface_create (const char *filename,
531 double width_in_points,
532 double height_in_points)
534 cairo_output_stream_t *output;
536 output = _cairo_output_stream_create_for_filename (filename);
537 if (_cairo_output_stream_get_status (output))
538 return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
540 return _cairo_pdf_surface_create_for_stream_internal (output,
546 _cairo_surface_is_pdf (cairo_surface_t *surface)
548 return surface->backend == &cairo_pdf_surface_backend;
551 /* If the abstract_surface is a paginated surface, and that paginated
552 * surface's target is a pdf_surface, then set pdf_surface to that
553 * target. Otherwise return FALSE.
556 _extract_pdf_surface (cairo_surface_t *surface,
557 cairo_pdf_surface_t **pdf_surface)
559 cairo_surface_t *target;
560 cairo_status_t status_ignored;
564 if (surface->finished) {
565 status_ignored = _cairo_surface_set_error (surface,
566 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
570 if (! _cairo_surface_is_paginated (surface)) {
571 status_ignored = _cairo_surface_set_error (surface,
572 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
576 target = _cairo_paginated_surface_get_target (surface);
577 if (target->status) {
578 status_ignored = _cairo_surface_set_error (surface,
582 if (target->finished) {
583 status_ignored = _cairo_surface_set_error (surface,
584 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
588 if (! _cairo_surface_is_pdf (target)) {
589 status_ignored = _cairo_surface_set_error (surface,
590 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
594 *pdf_surface = (cairo_pdf_surface_t *) target;
599 * cairo_pdf_surface_restrict_to_version:
600 * @surface: a PDF #cairo_surface_t
601 * @version: PDF version
603 * Restricts the generated PDF file to @version. See cairo_pdf_get_versions()
604 * for a list of available version values that can be used here.
606 * This function should only be called before any drawing operations
607 * have been performed on the given surface. The simplest way to do
608 * this is to call this function immediately after creating the
614 cairo_pdf_surface_restrict_to_version (cairo_surface_t *abstract_surface,
615 cairo_pdf_version_t version)
617 cairo_pdf_surface_t *surface = NULL; /* hide compiler warning */
619 if (! _extract_pdf_surface (abstract_surface, &surface))
622 if (version < CAIRO_PDF_VERSION_LAST)
623 surface->pdf_version = version;
625 _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators,
626 version >= CAIRO_PDF_VERSION_1_5);
630 * cairo_pdf_get_versions:
631 * @versions: supported version list
632 * @num_versions: list length
634 * Used to retrieve the list of supported versions. See
635 * cairo_pdf_surface_restrict_to_version().
640 cairo_pdf_get_versions (cairo_pdf_version_t const **versions,
643 if (versions != NULL)
644 *versions = _cairo_pdf_versions;
646 if (num_versions != NULL)
647 *num_versions = CAIRO_PDF_VERSION_LAST;
651 * cairo_pdf_version_to_string:
652 * @version: a version id
654 * Get the string representation of the given @version id. This function
655 * will return %NULL if @version isn't valid. See cairo_pdf_get_versions()
656 * for a way to get the list of valid version ids.
658 * Return value: the string associated to given version.
663 cairo_pdf_version_to_string (cairo_pdf_version_t version)
665 if (version >= CAIRO_PDF_VERSION_LAST)
668 return _cairo_pdf_version_strings[version];
672 * cairo_pdf_surface_set_size:
673 * @surface: a PDF #cairo_surface_t
674 * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
675 * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
677 * Changes the size of a PDF surface for the current (and
680 * This function should only be called before any drawing operations
681 * have been performed on the current page. The simplest way to do
682 * this is to call this function immediately after creating the
683 * surface or immediately after completing a page with either
684 * cairo_show_page() or cairo_copy_page().
689 cairo_pdf_surface_set_size (cairo_surface_t *surface,
690 double width_in_points,
691 double height_in_points)
693 cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
694 cairo_status_t status;
696 if (! _extract_pdf_surface (surface, &pdf_surface))
699 _cairo_pdf_surface_set_size_internal (pdf_surface,
702 status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
706 status = _cairo_surface_set_error (surface, status);
710 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
713 cairo_pdf_pattern_t *pattern;
714 cairo_pdf_source_surface_t *src_surface;
715 cairo_pdf_smask_group_t *group;
717 size = _cairo_array_num_elements (&surface->page_patterns);
718 for (i = 0; i < size; i++) {
719 pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->page_patterns, i);
721 cairo_pattern_destroy (pattern->pattern);
723 _cairo_array_truncate (&surface->page_patterns, 0);
725 size = _cairo_array_num_elements (&surface->page_surfaces);
726 for (i = 0; i < size; i++) {
727 src_surface = (cairo_pdf_source_surface_t *) _cairo_array_index (&surface->page_surfaces, i);
729 cairo_surface_destroy (src_surface->surface);
731 _cairo_array_truncate (&surface->page_surfaces, 0);
733 size = _cairo_array_num_elements (&surface->smask_groups);
734 for (i = 0; i < size; i++) {
735 _cairo_array_copy_element (&surface->smask_groups, i, &group);
736 _cairo_pdf_smask_group_destroy (group);
738 _cairo_array_truncate (&surface->smask_groups, 0);
739 _cairo_array_truncate (&surface->knockout_group, 0);
743 _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
747 for (i = 0; i < CAIRO_NUM_OPERATORS; i++)
748 res->operators[i] = FALSE;
750 _cairo_array_init (&res->alphas, sizeof (double));
751 _cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t));
752 _cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t));
753 _cairo_array_init (&res->shadings, sizeof (cairo_pdf_resource_t));
754 _cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t));
755 _cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t));
759 _cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
761 _cairo_array_fini (&res->alphas);
762 _cairo_array_fini (&res->smasks);
763 _cairo_array_fini (&res->patterns);
764 _cairo_array_fini (&res->shadings);
765 _cairo_array_fini (&res->xobjects);
766 _cairo_array_fini (&res->fonts);
770 _cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
774 for (i = 0; i < CAIRO_NUM_OPERATORS; i++)
775 res->operators[i] = FALSE;
777 _cairo_array_truncate (&res->alphas, 0);
778 _cairo_array_truncate (&res->smasks, 0);
779 _cairo_array_truncate (&res->patterns, 0);
780 _cairo_array_truncate (&res->shadings, 0);
781 _cairo_array_truncate (&res->xobjects, 0);
782 _cairo_array_truncate (&res->fonts, 0);
786 _cairo_pdf_surface_add_operator (cairo_pdf_surface_t *surface,
789 cairo_pdf_group_resources_t *res = &surface->resources;
791 res->operators[op] = TRUE;
794 static cairo_int_status_t
795 _cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
801 cairo_int_status_t status;
802 cairo_pdf_group_resources_t *res = &surface->resources;
804 num_alphas = _cairo_array_num_elements (&res->alphas);
805 for (i = 0; i < num_alphas; i++) {
806 _cairo_array_copy_element (&res->alphas, i, &other);
807 if (alpha == other) {
809 return CAIRO_STATUS_SUCCESS;
813 status = _cairo_array_append (&res->alphas, &alpha);
814 if (unlikely (status))
817 *index = _cairo_array_num_elements (&res->alphas) - 1;
819 return CAIRO_STATUS_SUCCESS;
822 static cairo_int_status_t
823 _cairo_pdf_surface_add_smask (cairo_pdf_surface_t *surface,
824 cairo_pdf_resource_t smask)
826 return _cairo_array_append (&(surface->resources.smasks), &smask);
829 static cairo_int_status_t
830 _cairo_pdf_surface_add_pattern (cairo_pdf_surface_t *surface,
831 cairo_pdf_resource_t pattern)
833 return _cairo_array_append (&(surface->resources.patterns), &pattern);
836 static cairo_int_status_t
837 _cairo_pdf_surface_add_shading (cairo_pdf_surface_t *surface,
838 cairo_pdf_resource_t shading)
840 return _cairo_array_append (&(surface->resources.shadings), &shading);
844 static cairo_int_status_t
845 _cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface,
846 cairo_pdf_resource_t xobject)
848 return _cairo_array_append (&(surface->resources.xobjects), &xobject);
851 static cairo_int_status_t
852 _cairo_pdf_surface_add_font (unsigned int font_id,
853 unsigned int subset_id,
856 cairo_pdf_surface_t *surface = closure;
857 cairo_pdf_font_t font;
859 cairo_int_status_t status;
860 cairo_pdf_group_resources_t *res = &surface->resources;
862 num_fonts = _cairo_array_num_elements (&res->fonts);
863 for (i = 0; i < num_fonts; i++) {
864 _cairo_array_copy_element (&res->fonts, i, &font);
865 if (font.font_id == font_id &&
866 font.subset_id == subset_id)
867 return CAIRO_STATUS_SUCCESS;
870 num_fonts = _cairo_array_num_elements (&surface->fonts);
871 for (i = 0; i < num_fonts; i++) {
872 _cairo_array_copy_element (&surface->fonts, i, &font);
873 if (font.font_id == font_id &&
874 font.subset_id == subset_id)
875 return _cairo_array_append (&res->fonts, &font);
878 font.font_id = font_id;
879 font.subset_id = subset_id;
880 font.subset_resource = _cairo_pdf_surface_new_object (surface);
881 if (font.subset_resource.id == 0)
882 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
884 status = _cairo_array_append (&surface->fonts, &font);
885 if (unlikely (status))
888 return _cairo_array_append (&res->fonts, &font);
891 static cairo_pdf_resource_t
892 _cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface,
893 unsigned int font_id,
894 unsigned int subset_id)
896 cairo_pdf_font_t font;
899 num_fonts = _cairo_array_num_elements (&surface->fonts);
900 for (i = 0; i < num_fonts; i++) {
901 _cairo_array_copy_element (&surface->fonts, i, &font);
902 if (font.font_id == font_id && font.subset_id == subset_id)
903 return font.subset_resource;
906 font.subset_resource.id = 0;
907 return font.subset_resource;
911 _cairo_operator_to_pdf_blend_mode (cairo_operator_t op)
914 /* The extend blend mode operators */
915 case CAIRO_OPERATOR_MULTIPLY: return "Multiply";
916 case CAIRO_OPERATOR_SCREEN: return "Screen";
917 case CAIRO_OPERATOR_OVERLAY: return "Overlay";
918 case CAIRO_OPERATOR_DARKEN: return "Darken";
919 case CAIRO_OPERATOR_LIGHTEN: return "Lighten";
920 case CAIRO_OPERATOR_COLOR_DODGE: return "ColorDodge";
921 case CAIRO_OPERATOR_COLOR_BURN: return "ColorBurn";
922 case CAIRO_OPERATOR_HARD_LIGHT: return "HardLight";
923 case CAIRO_OPERATOR_SOFT_LIGHT: return "SoftLight";
924 case CAIRO_OPERATOR_DIFFERENCE: return "Difference";
925 case CAIRO_OPERATOR_EXCLUSION: return "Exclusion";
926 case CAIRO_OPERATOR_HSL_HUE: return "Hue";
927 case CAIRO_OPERATOR_HSL_SATURATION: return "Saturation";
928 case CAIRO_OPERATOR_HSL_COLOR: return "Color";
929 case CAIRO_OPERATOR_HSL_LUMINOSITY: return "Luminosity";
932 /* The original Porter-Duff set */
933 case CAIRO_OPERATOR_CLEAR:
934 case CAIRO_OPERATOR_SOURCE:
935 case CAIRO_OPERATOR_OVER:
936 case CAIRO_OPERATOR_IN:
937 case CAIRO_OPERATOR_OUT:
938 case CAIRO_OPERATOR_ATOP:
939 case CAIRO_OPERATOR_DEST:
940 case CAIRO_OPERATOR_DEST_OVER:
941 case CAIRO_OPERATOR_DEST_IN:
942 case CAIRO_OPERATOR_DEST_OUT:
943 case CAIRO_OPERATOR_DEST_ATOP:
944 case CAIRO_OPERATOR_XOR:
945 case CAIRO_OPERATOR_ADD:
946 case CAIRO_OPERATOR_SATURATE:
952 _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface,
953 cairo_pdf_group_resources_t *res)
955 int num_alphas, num_smasks, num_resources, i;
957 cairo_pdf_resource_t *smask, *pattern, *shading, *xobject;
958 cairo_pdf_font_t *font;
960 _cairo_output_stream_printf (surface->output, "<<\n");
962 num_alphas = _cairo_array_num_elements (&res->alphas);
963 num_smasks = _cairo_array_num_elements (&res->smasks);
964 if (num_alphas > 0 || num_smasks > 0) {
965 _cairo_output_stream_printf (surface->output,
968 for (i = 0; i < CAIRO_NUM_OPERATORS; i++) {
969 if (res->operators[i]) {
970 _cairo_output_stream_printf (surface->output,
971 " /b%d << /BM /%s >>\n",
972 i, _cairo_operator_to_pdf_blend_mode(i));
976 for (i = 0; i < num_alphas; i++) {
977 _cairo_array_copy_element (&res->alphas, i, &alpha);
978 _cairo_output_stream_printf (surface->output,
979 " /a%d << /CA %f /ca %f >>\n",
983 for (i = 0; i < num_smasks; i++) {
984 smask = _cairo_array_index (&res->smasks, i);
987 _cairo_output_stream_printf (surface->output,
989 smask->id, smask->id);
992 _cairo_output_stream_printf (surface->output,
996 num_resources = _cairo_array_num_elements (&res->patterns);
997 if (num_resources > 0) {
998 _cairo_output_stream_printf (surface->output,
1000 for (i = 0; i < num_resources; i++) {
1001 pattern = _cairo_array_index (&res->patterns, i);
1002 if (pattern == NULL)
1004 _cairo_output_stream_printf (surface->output,
1006 pattern->id, pattern->id);
1009 _cairo_output_stream_printf (surface->output,
1013 num_resources = _cairo_array_num_elements (&res->shadings);
1014 if (num_resources > 0) {
1015 _cairo_output_stream_printf (surface->output,
1017 for (i = 0; i < num_resources; i++) {
1018 shading = _cairo_array_index (&res->shadings, i);
1019 if (shading == NULL)
1021 _cairo_output_stream_printf (surface->output,
1023 shading->id, shading->id);
1026 _cairo_output_stream_printf (surface->output,
1030 num_resources = _cairo_array_num_elements (&res->xobjects);
1031 if (num_resources > 0) {
1032 _cairo_output_stream_printf (surface->output,
1035 for (i = 0; i < num_resources; i++) {
1036 xobject = _cairo_array_index (&res->xobjects, i);
1037 if (xobject == NULL)
1039 _cairo_output_stream_printf (surface->output,
1041 xobject->id, xobject->id);
1044 _cairo_output_stream_printf (surface->output,
1048 num_resources = _cairo_array_num_elements (&res->fonts);
1049 if (num_resources > 0) {
1050 _cairo_output_stream_printf (surface->output," /Font <<\n");
1051 for (i = 0; i < num_resources; i++) {
1052 font = _cairo_array_index (&res->fonts, i);
1056 _cairo_output_stream_printf (surface->output,
1057 " /f-%d-%d %d 0 R\n",
1060 font->subset_resource.id);
1062 _cairo_output_stream_printf (surface->output, " >>\n");
1065 _cairo_output_stream_printf (surface->output,
1069 static cairo_pdf_smask_group_t *
1070 _cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t *surface,
1071 const cairo_rectangle_int_t *extents)
1073 cairo_pdf_smask_group_t *group;
1075 group = calloc (1, sizeof (cairo_pdf_smask_group_t));
1076 if (unlikely (group == NULL)) {
1077 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1081 group->group_res = _cairo_pdf_surface_new_object (surface);
1082 if (group->group_res.id == 0) {
1083 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1087 group->width = surface->width;
1088 group->height = surface->height;
1089 if (extents != NULL) {
1090 group->extents = *extents;
1092 group->extents.x = 0;
1093 group->extents.y = 0;
1094 group->extents.width = surface->width;
1095 group->extents.height = surface->height;
1102 _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
1106 if (group->operation == PDF_FILL || group->operation == PDF_STROKE)
1107 _cairo_path_fixed_fini (&group->path);
1109 cairo_pattern_destroy (group->source);
1111 cairo_pattern_destroy (group->mask);
1113 free (group->glyphs);
1114 free (group->clusters);
1115 if (group->scaled_font)
1116 cairo_scaled_font_destroy (group->scaled_font);
1121 static cairo_int_status_t
1122 _cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t *surface,
1123 cairo_pdf_smask_group_t *group)
1125 return _cairo_array_append (&surface->smask_groups, &group);
1129 _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b)
1131 const cairo_pdf_source_surface_entry_t *a = key_a;
1132 const cairo_pdf_source_surface_entry_t *b = key_b;
1134 if (a->interpolate != b->interpolate)
1137 if (a->unique_id && b->unique_id && a->unique_id_length == b->unique_id_length)
1138 return (memcmp (a->unique_id, b->unique_id, a->unique_id_length) == 0);
1140 return (a->id == b->id);
1144 _cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key)
1146 if (key->unique_id && key->unique_id_length > 0) {
1147 key->base.hash = _cairo_hash_bytes (_CAIRO_HASH_INIT_VALUE,
1148 key->unique_id, key->unique_id_length);
1150 key->base.hash = key->id;
1154 static cairo_int_status_t
1155 _cairo_pdf_surface_acquire_source_image_from_pattern (cairo_pdf_surface_t *surface,
1156 const cairo_pattern_t *pattern,
1157 cairo_image_surface_t **image,
1160 switch (pattern->type) {
1161 case CAIRO_PATTERN_TYPE_SURFACE: {
1162 cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
1163 return _cairo_surface_acquire_source_image (surf_pat->surface, image, image_extra);
1166 case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
1167 cairo_surface_t *surf;
1168 surf = _cairo_raster_source_pattern_acquire (pattern, &surface->base, NULL);
1170 return CAIRO_INT_STATUS_UNSUPPORTED;
1171 assert (_cairo_surface_is_image (surf));
1172 *image = (cairo_image_surface_t *) surf;
1175 case CAIRO_PATTERN_TYPE_SOLID:
1176 case CAIRO_PATTERN_TYPE_LINEAR:
1177 case CAIRO_PATTERN_TYPE_RADIAL:
1178 case CAIRO_PATTERN_TYPE_MESH:
1184 return CAIRO_STATUS_SUCCESS;
1188 _cairo_pdf_surface_release_source_image_from_pattern (cairo_pdf_surface_t *surface,
1189 const cairo_pattern_t *pattern,
1190 cairo_image_surface_t *image,
1193 switch (pattern->type) {
1194 case CAIRO_PATTERN_TYPE_SURFACE: {
1195 cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
1196 _cairo_surface_release_source_image (surf_pat->surface, image, image_extra);
1199 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1200 _cairo_raster_source_pattern_release (pattern, &image->base);
1203 case CAIRO_PATTERN_TYPE_SOLID:
1204 case CAIRO_PATTERN_TYPE_LINEAR:
1205 case CAIRO_PATTERN_TYPE_RADIAL:
1206 case CAIRO_PATTERN_TYPE_MESH:
1214 static cairo_int_status_t
1215 _get_jbig2_image_info (cairo_surface_t *source,
1216 cairo_image_info_t *info,
1217 const unsigned char **mime_data,
1218 unsigned long *mime_data_length)
1220 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2,
1221 mime_data, mime_data_length);
1222 if (*mime_data == NULL)
1223 return CAIRO_INT_STATUS_UNSUPPORTED;
1225 return _cairo_image_info_get_jbig2_info (info, *mime_data, *mime_data_length);
1228 static cairo_int_status_t
1229 _get_jpx_image_info (cairo_surface_t *source,
1230 cairo_image_info_t *info,
1231 const unsigned char **mime_data,
1232 unsigned long *mime_data_length)
1234 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
1235 mime_data, mime_data_length);
1236 if (*mime_data == NULL)
1237 return CAIRO_INT_STATUS_UNSUPPORTED;
1239 return _cairo_image_info_get_jpx_info (info, *mime_data, *mime_data_length);
1242 static cairo_int_status_t
1243 _get_jpeg_image_info (cairo_surface_t *source,
1244 cairo_image_info_t *info,
1245 const unsigned char **mime_data,
1246 unsigned long *mime_data_length)
1248 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
1249 mime_data, mime_data_length);
1250 if (*mime_data == NULL)
1251 return CAIRO_INT_STATUS_UNSUPPORTED;
1253 return _cairo_image_info_get_jpeg_info (info, *mime_data, *mime_data_length);
1256 static cairo_int_status_t
1257 _get_source_surface_size (cairo_surface_t *source,
1260 cairo_rectangle_int_t *extents)
1262 cairo_int_status_t status;
1263 cairo_image_info_t info;
1264 const unsigned char *mime_data;
1265 unsigned long mime_data_length;
1267 if (source->type == CAIRO_SURFACE_TYPE_RECORDING) {
1268 if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1269 cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
1271 *extents = sub->extents;
1272 *width = extents->width;
1273 *height = extents->height;
1275 cairo_surface_t *free_me = NULL;
1276 cairo_rectangle_int_t surf_extents;
1278 cairo_bool_t bounded;
1280 if (_cairo_surface_is_snapshot (source))
1281 free_me = source = _cairo_surface_snapshot_get_target (source);
1283 status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)source,
1285 if (unlikely (status)) {
1286 cairo_surface_destroy (free_me);
1290 bounded = _cairo_surface_get_extents (source, &surf_extents);
1291 cairo_surface_destroy (free_me);
1293 *width = surf_extents.width;
1294 *height = surf_extents.height;
1296 _cairo_box_round_to_rectangle (&box, extents);
1299 return CAIRO_STATUS_SUCCESS;
1305 status = _get_jbig2_image_info (source, &info, &mime_data, &mime_data_length);
1306 if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
1307 *width = info.width;
1308 *height = info.height;
1309 extents->width = info.width;
1310 extents->height = info.height;
1314 status = _get_jpx_image_info (source, &info, &mime_data, &mime_data_length);
1315 if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
1316 *width = info.width;
1317 *height = info.height;
1318 extents->width = info.width;
1319 extents->height = info.height;
1323 status = _get_jpeg_image_info (source, &info, &mime_data, &mime_data_length);
1324 if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
1325 *width = info.width;
1326 *height = info.height;
1327 extents->width = info.width;
1328 extents->height = info.height;
1332 if (! _cairo_surface_get_extents (source, extents))
1333 return CAIRO_INT_STATUS_UNSUPPORTED;
1335 *width = extents->width;
1336 *height = extents->height;
1338 return CAIRO_STATUS_SUCCESS;
1342 * _cairo_pdf_surface_add_source_surface:
1343 * @surface: the pdf surface
1344 * @source_surface: A #cairo_surface_t to use as the source surface
1345 * @source_pattern: A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source
1346 * @op: the operator used to composite this source
1347 * @filter: filter type of the source pattern
1348 * @stencil_mask: if true, the surface will be written to the PDF as an /ImageMask
1349 * @smask: if true, only the alpha channel will be written (images only)
1350 * @extents: extents of the operation that is using this source
1351 * @smask_res: if not NULL, the image written will specify this resource as the smask for the image (images only)
1352 * @surface_res: return PDF resource number of the surface
1353 * @width: returns width of surface
1354 * @height: returns height of surface
1355 * @x_offset: x offset of surface
1356 * @t_offset: y offset of surface
1357 * @source_extents: returns extents of source (either ink extents or extents needed to cover @extents)
1359 * Add surface or raster_source pattern to list of surfaces to be
1360 * written to the PDF file when the current page is finished. Returns
1361 * a PDF resource to reference the image. A hash table of all images
1362 * in the PDF files (keyed by CAIRO_MIME_TYPE_UNIQUE_ID or surface
1363 * unique_id) to ensure surfaces with the same id are only written
1364 * once to the PDF file.
1366 * Only one of @source_pattern or @source_surface is to be
1367 * specified. Set the other to NULL.
1369 static cairo_int_status_t
1370 _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
1371 cairo_surface_t *source_surface,
1372 const cairo_pattern_t *source_pattern,
1373 cairo_operator_t op,
1374 cairo_filter_t filter,
1375 cairo_bool_t stencil_mask,
1377 const cairo_rectangle_int_t *extents,
1378 cairo_pdf_resource_t *smask_res,
1379 cairo_pdf_resource_t *surface_res,
1384 cairo_rectangle_int_t *source_extents)
1386 cairo_pdf_source_surface_t src_surface;
1387 cairo_pdf_source_surface_entry_t surface_key;
1388 cairo_pdf_source_surface_entry_t *surface_entry;
1389 cairo_int_status_t status;
1390 cairo_bool_t interpolate;
1391 unsigned char *unique_id = NULL;
1392 unsigned long unique_id_length = 0;
1393 cairo_image_surface_t *image;
1398 case CAIRO_FILTER_GOOD:
1399 case CAIRO_FILTER_BEST:
1400 case CAIRO_FILTER_BILINEAR:
1403 case CAIRO_FILTER_FAST:
1404 case CAIRO_FILTER_NEAREST:
1405 case CAIRO_FILTER_GAUSSIAN:
1406 interpolate = FALSE;
1412 if (source_pattern) {
1413 if (source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1414 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source_pattern,
1415 &image, &image_extra);
1416 if (unlikely (status))
1418 source_surface = &image->base;
1419 cairo_surface_get_device_offset (source_surface, x_offset, y_offset);
1421 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source_pattern;
1422 source_surface = surface_pattern->surface;
1426 surface_key.id = source_surface->unique_id;
1427 surface_key.interpolate = interpolate;
1428 cairo_surface_get_mime_data (source_surface, CAIRO_MIME_TYPE_UNIQUE_ID,
1429 (const unsigned char **) &surface_key.unique_id,
1430 &surface_key.unique_id_length);
1431 _cairo_pdf_source_surface_init_key (&surface_key);
1432 surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base);
1433 if (surface_entry) {
1434 *surface_res = surface_entry->surface_res;
1435 *width = surface_entry->width;
1436 *height = surface_entry->height;
1437 *source_extents = surface_entry->extents;
1438 status = CAIRO_STATUS_SUCCESS;
1440 status = _get_source_surface_size (source_surface,
1444 if (unlikely(status))
1445 goto release_source;
1447 if (surface_key.unique_id && surface_key.unique_id_length > 0) {
1448 unique_id = _cairo_malloc (surface_key.unique_id_length);
1449 if (unique_id == NULL) {
1450 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1451 goto release_source;
1454 unique_id_length = surface_key.unique_id_length;
1455 memcpy (unique_id, surface_key.unique_id, unique_id_length);
1458 unique_id_length = 0;
1463 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1464 _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra);
1466 if (status || surface_entry)
1469 surface_entry = malloc (sizeof (cairo_pdf_source_surface_entry_t));
1470 if (surface_entry == NULL) {
1471 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1475 surface_entry->id = surface_key.id;
1476 surface_entry->operator = op;
1477 surface_entry->interpolate = interpolate;
1478 surface_entry->stencil_mask = stencil_mask;
1479 surface_entry->smask = smask;
1480 surface_entry->unique_id_length = unique_id_length;
1481 surface_entry->unique_id = unique_id;
1482 surface_entry->width = *width;
1483 surface_entry->height = *height;
1484 surface_entry->extents = *source_extents;
1486 surface_entry->smask_res = *smask_res;
1488 surface_entry->smask_res.id = 0;
1489 _cairo_pdf_source_surface_init_key (surface_entry);
1491 src_surface.hash_entry = surface_entry;
1492 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1493 src_surface.type = CAIRO_PATTERN_TYPE_RASTER_SOURCE;
1494 src_surface.surface = NULL;
1495 status = _cairo_pattern_create_copy (&src_surface.raster_pattern, source_pattern);
1496 if (unlikely (status))
1500 src_surface.type = CAIRO_PATTERN_TYPE_SURFACE;
1501 src_surface.surface = cairo_surface_reference (source_surface);
1502 src_surface.raster_pattern = NULL;
1505 surface_entry->surface_res = _cairo_pdf_surface_new_object (surface);
1506 if (surface_entry->surface_res.id == 0) {
1507 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1511 status = _cairo_array_append (&surface->page_surfaces, &src_surface);
1512 if (unlikely (status))
1515 status = _cairo_hash_table_insert (surface->all_surfaces,
1516 &surface_entry->base);
1517 if (unlikely(status))
1520 *surface_res = surface_entry->surface_res;
1525 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1526 cairo_pattern_destroy (src_surface.raster_pattern);
1528 cairo_surface_destroy (src_surface.surface);
1531 free (surface_entry);
1539 static cairo_int_status_t
1540 _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface,
1541 const cairo_pattern_t *pattern,
1542 cairo_operator_t op,
1543 const cairo_rectangle_int_t *extents,
1544 cairo_bool_t is_shading,
1545 cairo_pdf_resource_t *pattern_res,
1546 cairo_pdf_resource_t *gstate_res)
1548 cairo_pdf_pattern_t pdf_pattern;
1549 cairo_int_status_t status;
1551 pdf_pattern.is_shading = is_shading;
1552 pdf_pattern.operator = op;
1554 /* Solid colors are emitted into the content stream */
1555 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
1556 pattern_res->id = 0;
1558 return CAIRO_INT_STATUS_SUCCESS;
1561 status = _cairo_pattern_create_copy (&pdf_pattern.pattern, pattern);
1562 if (unlikely (status))
1565 pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface);
1566 if (pdf_pattern.pattern_res.id == 0) {
1567 cairo_pattern_destroy (pdf_pattern.pattern);
1568 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1571 pdf_pattern.gstate_res.id = 0;
1573 /* gradient patterns require an smask object to implement transparency */
1574 if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
1575 pattern->type == CAIRO_PATTERN_TYPE_RADIAL ||
1576 pattern->type == CAIRO_PATTERN_TYPE_MESH)
1580 _cairo_pattern_alpha_range (pattern, &min_alpha, NULL);
1581 if (! CAIRO_ALPHA_IS_OPAQUE (min_alpha)) {
1582 pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
1583 if (pdf_pattern.gstate_res.id == 0) {
1584 cairo_pattern_destroy (pdf_pattern.pattern);
1585 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1590 pdf_pattern.width = surface->width;
1591 pdf_pattern.height = surface->height;
1592 if (extents != NULL) {
1593 pdf_pattern.extents = *extents;
1595 pdf_pattern.extents.x = 0;
1596 pdf_pattern.extents.y = 0;
1597 pdf_pattern.extents.width = surface->width;
1598 pdf_pattern.extents.height = surface->height;
1601 *pattern_res = pdf_pattern.pattern_res;
1602 *gstate_res = pdf_pattern.gstate_res;
1604 status = _cairo_array_append (&surface->page_patterns, &pdf_pattern);
1605 if (unlikely (status)) {
1606 cairo_pattern_destroy (pdf_pattern.pattern);
1610 return CAIRO_INT_STATUS_SUCCESS;
1613 /* Get BBox in PDF coordinates from extents in cairo coordinates */
1615 _get_bbox_from_extents (double surface_height,
1616 const cairo_rectangle_int_t *extents,
1617 cairo_box_double_t *bbox)
1619 bbox->p1.x = extents->x;
1620 bbox->p1.y = surface_height - (extents->y + extents->height);
1621 bbox->p2.x = extents->x + extents->width;
1622 bbox->p2.y = surface_height - extents->y;
1625 static cairo_int_status_t
1626 _cairo_pdf_surface_add_pdf_shading (cairo_pdf_surface_t *surface,
1627 const cairo_pattern_t *pattern,
1628 cairo_operator_t op,
1629 const cairo_rectangle_int_t *extents,
1630 cairo_pdf_resource_t *shading_res,
1631 cairo_pdf_resource_t *gstate_res)
1633 return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
1642 static cairo_int_status_t
1643 _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
1644 const cairo_pattern_t *pattern,
1645 cairo_operator_t op,
1646 const cairo_rectangle_int_t *extents,
1647 cairo_pdf_resource_t *pattern_res,
1648 cairo_pdf_resource_t *gstate_res)
1650 return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
1659 static cairo_int_status_t
1660 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
1661 cairo_pdf_resource_t *resource,
1662 cairo_bool_t compressed,
1667 cairo_pdf_resource_t self, length;
1668 cairo_output_stream_t *output = NULL;
1672 _cairo_pdf_surface_update_object (surface, self);
1674 self = _cairo_pdf_surface_new_object (surface);
1676 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1679 length = _cairo_pdf_surface_new_object (surface);
1681 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1684 output = _cairo_deflate_stream_create (surface->output);
1685 if (_cairo_output_stream_get_status (output))
1686 return _cairo_output_stream_destroy (output);
1689 surface->pdf_stream.active = TRUE;
1690 surface->pdf_stream.self = self;
1691 surface->pdf_stream.length = length;
1692 surface->pdf_stream.compressed = compressed;
1693 surface->current_pattern_is_solid_color = FALSE;
1694 surface->current_operator = CAIRO_OPERATOR_OVER;
1695 _cairo_pdf_operators_reset (&surface->pdf_operators);
1697 _cairo_output_stream_printf (surface->output,
1699 "<< /Length %d 0 R\n",
1700 surface->pdf_stream.self.id,
1701 surface->pdf_stream.length.id);
1703 _cairo_output_stream_printf (surface->output,
1704 " /Filter /FlateDecode\n");
1708 _cairo_output_stream_vprintf (surface->output, fmt, ap);
1712 _cairo_output_stream_printf (surface->output,
1716 surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
1719 assert (surface->pdf_stream.old_output == NULL);
1720 surface->pdf_stream.old_output = surface->output;
1721 surface->output = output;
1722 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1725 return _cairo_output_stream_get_status (surface->output);
1728 static cairo_int_status_t
1729 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
1731 cairo_int_status_t status;
1734 if (! surface->pdf_stream.active)
1735 return CAIRO_INT_STATUS_SUCCESS;
1737 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1739 if (surface->pdf_stream.compressed) {
1740 cairo_int_status_t status2;
1742 status2 = _cairo_output_stream_destroy (surface->output);
1743 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
1746 surface->output = surface->pdf_stream.old_output;
1747 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1748 surface->pdf_stream.old_output = NULL;
1751 length = _cairo_output_stream_get_position (surface->output) -
1752 surface->pdf_stream.start_offset;
1753 _cairo_output_stream_printf (surface->output,
1758 _cairo_pdf_surface_update_object (surface,
1759 surface->pdf_stream.length);
1760 _cairo_output_stream_printf (surface->output,
1764 surface->pdf_stream.length.id,
1767 surface->pdf_stream.active = FALSE;
1769 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
1770 status = _cairo_output_stream_get_status (surface->output);
1776 _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface,
1777 cairo_output_stream_t *mem_stream,
1778 cairo_pdf_resource_t resource,
1779 cairo_pdf_group_resources_t *resources,
1780 cairo_bool_t is_knockout_group,
1781 const cairo_box_double_t *bbox)
1783 _cairo_pdf_surface_update_object (surface, resource);
1785 _cairo_output_stream_printf (surface->output,
1787 "<< /Type /XObject\n"
1790 _cairo_memory_stream_length (mem_stream));
1792 if (surface->compress_content) {
1793 _cairo_output_stream_printf (surface->output,
1794 " /Filter /FlateDecode\n");
1797 _cairo_output_stream_printf (surface->output,
1799 " /BBox [ %f %f %f %f ]\n"
1802 " /S /Transparency\n"
1804 " /CS /DeviceRGB\n",
1805 bbox->p1.x, bbox->p1.y, bbox->p2.x, bbox->p2.y);
1807 if (is_knockout_group)
1808 _cairo_output_stream_printf (surface->output,
1811 _cairo_output_stream_printf (surface->output,
1814 _cairo_pdf_surface_emit_group_resources (surface, resources);
1815 _cairo_output_stream_printf (surface->output,
1818 _cairo_memory_stream_copy (mem_stream, surface->output);
1819 _cairo_output_stream_printf (surface->output,
1824 static cairo_int_status_t
1825 _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
1826 const cairo_box_double_t *bbox,
1827 cairo_pdf_resource_t *resource)
1829 cairo_int_status_t status;
1831 assert (surface->pdf_stream.active == FALSE);
1832 assert (surface->group_stream.active == FALSE);
1834 surface->group_stream.active = TRUE;
1835 surface->current_pattern_is_solid_color = FALSE;
1836 surface->current_operator = CAIRO_OPERATOR_OVER;
1837 _cairo_pdf_operators_reset (&surface->pdf_operators);
1839 surface->group_stream.mem_stream = _cairo_memory_stream_create ();
1841 if (surface->compress_content) {
1842 surface->group_stream.stream =
1843 _cairo_deflate_stream_create (surface->group_stream.mem_stream);
1845 surface->group_stream.stream = surface->group_stream.mem_stream;
1847 status = _cairo_output_stream_get_status (surface->group_stream.stream);
1849 surface->group_stream.old_output = surface->output;
1850 surface->output = surface->group_stream.stream;
1851 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1852 _cairo_pdf_group_resources_clear (&surface->resources);
1855 surface->group_stream.resource = *resource;
1857 surface->group_stream.resource = _cairo_pdf_surface_new_object (surface);
1858 if (surface->group_stream.resource.id == 0)
1859 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1861 surface->group_stream.is_knockout = FALSE;
1862 surface->group_stream.bbox = *bbox;
1867 static cairo_int_status_t
1868 _cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface,
1869 const cairo_box_double_t *bbox)
1871 cairo_int_status_t status;
1873 status = _cairo_pdf_surface_open_group (surface, bbox, NULL);
1874 if (unlikely (status))
1877 surface->group_stream.is_knockout = TRUE;
1879 return CAIRO_INT_STATUS_SUCCESS;
1882 static cairo_int_status_t
1883 _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
1884 cairo_pdf_resource_t *group)
1886 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS, status2;
1888 assert (surface->pdf_stream.active == FALSE);
1889 assert (surface->group_stream.active == TRUE);
1891 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1892 if (unlikely (status))
1895 if (surface->compress_content) {
1896 status = _cairo_output_stream_destroy (surface->group_stream.stream);
1897 surface->group_stream.stream = NULL;
1899 _cairo_output_stream_printf (surface->group_stream.mem_stream,
1902 surface->output = surface->group_stream.old_output;
1903 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1904 surface->group_stream.active = FALSE;
1905 _cairo_pdf_surface_write_memory_stream (surface,
1906 surface->group_stream.mem_stream,
1907 surface->group_stream.resource,
1908 &surface->resources,
1909 surface->group_stream.is_knockout,
1910 &surface->group_stream.bbox);
1912 *group = surface->group_stream.resource;
1914 status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
1915 if (status == CAIRO_INT_STATUS_SUCCESS)
1918 surface->group_stream.mem_stream = NULL;
1919 surface->group_stream.stream = NULL;
1924 static cairo_int_status_t
1925 _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
1926 const cairo_box_double_t *bbox,
1927 cairo_pdf_resource_t *resource,
1928 cairo_bool_t is_form,
1929 cairo_bool_t is_group)
1931 cairo_int_status_t status;
1933 assert (surface->pdf_stream.active == FALSE);
1934 assert (surface->group_stream.active == FALSE);
1936 surface->content_resources = _cairo_pdf_surface_new_object (surface);
1937 if (surface->content_resources.id == 0)
1938 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1941 assert (bbox != NULL);
1945 _cairo_pdf_surface_open_stream (surface,
1947 surface->compress_content,
1950 " /BBox [ %f %f %f %f ]\n"
1953 " /S /Transparency\n"
1957 " /Resources %d 0 R\n",
1962 surface->content_resources.id);
1965 _cairo_pdf_surface_open_stream (surface,
1967 surface->compress_content,
1970 " /BBox [ %f %f %f %f ]\n"
1971 " /Resources %d 0 R\n",
1976 surface->content_resources.id);
1980 _cairo_pdf_surface_open_stream (surface,
1982 surface->compress_content,
1985 if (unlikely (status))
1988 surface->content = surface->pdf_stream.self;
1990 _cairo_output_stream_printf (surface->output, "q\n");
1992 return _cairo_output_stream_get_status (surface->output);
1995 static cairo_int_status_t
1996 _cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
1998 cairo_int_status_t status;
2000 assert (surface->pdf_stream.active == TRUE);
2001 assert (surface->group_stream.active == FALSE);
2003 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
2004 if (unlikely (status))
2007 _cairo_output_stream_printf (surface->output, "Q\n");
2008 status = _cairo_pdf_surface_close_stream (surface);
2009 if (unlikely (status))
2012 _cairo_pdf_surface_update_object (surface, surface->content_resources);
2013 _cairo_output_stream_printf (surface->output,
2015 surface->content_resources.id);
2016 _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
2017 _cairo_output_stream_printf (surface->output,
2020 return _cairo_output_stream_get_status (surface->output);
2024 _cairo_pdf_source_surface_entry_pluck (void *entry, void *closure)
2026 cairo_pdf_source_surface_entry_t *surface_entry = entry;
2027 cairo_hash_table_t *patterns = closure;
2029 _cairo_hash_table_remove (patterns, &surface_entry->base);
2030 free (surface_entry->unique_id);
2032 free (surface_entry);
2035 static cairo_status_t
2036 _cairo_pdf_surface_finish (void *abstract_surface)
2038 cairo_pdf_surface_t *surface = abstract_surface;
2040 cairo_pdf_resource_t info, catalog;
2041 cairo_status_t status, status2;
2043 cairo_pdf_jbig2_global_t *global;
2045 status = surface->base.status;
2046 if (status == CAIRO_STATUS_SUCCESS)
2047 status = _cairo_pdf_surface_emit_font_subsets (surface);
2049 _cairo_pdf_surface_write_pages (surface);
2051 info = _cairo_pdf_surface_write_info (surface);
2052 if (info.id == 0 && status == CAIRO_STATUS_SUCCESS)
2053 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2055 catalog = _cairo_pdf_surface_write_catalog (surface);
2056 if (catalog.id == 0 && status == CAIRO_STATUS_SUCCESS)
2057 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2059 offset = _cairo_pdf_surface_write_xref (surface);
2061 status = _cairo_error (CAIRO_STATUS_INVALID_INDEX);
2063 _cairo_output_stream_printf (surface->output,
2069 surface->next_available_resource.id,
2073 _cairo_output_stream_printf (surface->output,
2079 /* pdf_operators has already been flushed when the last stream was
2080 * closed so we should never be writing anything here - however,
2081 * the stream may itself be in an error state. */
2082 status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
2083 if (status == CAIRO_STATUS_SUCCESS)
2086 /* close any active streams still open due to fatal errors */
2087 status2 = _cairo_pdf_surface_close_stream (surface);
2088 if (status == CAIRO_STATUS_SUCCESS)
2091 if (surface->group_stream.stream != NULL) {
2092 status2 = _cairo_output_stream_destroy (surface->group_stream.stream);
2093 if (status == CAIRO_STATUS_SUCCESS)
2096 if (surface->group_stream.mem_stream != NULL) {
2097 status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
2098 if (status == CAIRO_STATUS_SUCCESS)
2101 if (surface->pdf_stream.active)
2102 surface->output = surface->pdf_stream.old_output;
2103 if (surface->group_stream.active)
2104 surface->output = surface->group_stream.old_output;
2106 /* and finish the pdf surface */
2107 status2 = _cairo_output_stream_destroy (surface->output);
2108 if (status == CAIRO_STATUS_SUCCESS)
2111 _cairo_pdf_surface_clear (surface);
2112 _cairo_pdf_group_resources_fini (&surface->resources);
2114 _cairo_array_fini (&surface->objects);
2115 _cairo_array_fini (&surface->pages);
2116 _cairo_array_fini (&surface->rgb_linear_functions);
2117 _cairo_array_fini (&surface->alpha_linear_functions);
2118 _cairo_array_fini (&surface->page_patterns);
2119 _cairo_array_fini (&surface->page_surfaces);
2120 _cairo_hash_table_foreach (surface->all_surfaces,
2121 _cairo_pdf_source_surface_entry_pluck,
2122 surface->all_surfaces);
2123 _cairo_hash_table_destroy (surface->all_surfaces);
2124 _cairo_array_fini (&surface->smask_groups);
2125 _cairo_array_fini (&surface->fonts);
2126 _cairo_array_fini (&surface->knockout_group);
2128 if (surface->font_subsets) {
2129 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
2130 surface->font_subsets = NULL;
2133 size = _cairo_array_num_elements (&surface->jbig2_global);
2134 for (i = 0; i < size; i++) {
2135 global = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, i);
2137 if (!global->emitted)
2138 return _cairo_error (CAIRO_STATUS_JBIG2_GLOBAL_MISSING);
2140 _cairo_array_fini (&surface->jbig2_global);
2142 _cairo_array_truncate (&surface->page_surfaces, 0);
2144 _cairo_surface_clipper_reset (&surface->clipper);
2149 static cairo_int_status_t
2150 _cairo_pdf_surface_start_page (void *abstract_surface)
2152 cairo_pdf_surface_t *surface = abstract_surface;
2154 /* Document header */
2155 if (! surface->header_emitted) {
2156 const char *version;
2158 switch (surface->pdf_version) {
2159 case CAIRO_PDF_VERSION_1_4:
2163 case CAIRO_PDF_VERSION_1_5:
2168 _cairo_output_stream_printf (surface->output,
2169 "%%PDF-%s\n", version);
2170 _cairo_output_stream_printf (surface->output,
2171 "%%%c%c%c%c\n", 181, 237, 174, 251);
2172 surface->header_emitted = TRUE;
2175 _cairo_pdf_group_resources_clear (&surface->resources);
2177 return CAIRO_STATUS_SUCCESS;
2180 static cairo_int_status_t
2181 _cairo_pdf_surface_has_fallback_images (void *abstract_surface,
2182 cairo_bool_t has_fallbacks)
2184 cairo_int_status_t status;
2185 cairo_pdf_surface_t *surface = abstract_surface;
2186 cairo_box_double_t bbox;
2188 surface->has_fallback_images = has_fallbacks;
2191 bbox.p2.x = surface->width;
2192 bbox.p2.y = surface->height;
2193 status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, has_fallbacks, has_fallbacks);
2194 if (unlikely (status))
2197 return CAIRO_STATUS_SUCCESS;
2201 _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
2206 static cairo_int_status_t
2207 _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surface,
2208 const cairo_pattern_t *source,
2209 const cairo_rectangle_int_t *extents,
2210 cairo_pdf_resource_t *surface_res,
2216 cairo_image_surface_t *image;
2217 cairo_surface_t *pad_image;
2219 cairo_int_status_t status;
2221 cairo_rectangle_int_t extents2;
2223 cairo_rectangle_int_t rect;
2224 cairo_surface_pattern_t pad_pattern;
2226 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source,
2227 &image, &image_extra);
2228 if (unlikely (status))
2231 pad_image = &image->base;
2233 /* get the operation extents in pattern space */
2234 _cairo_box_from_rectangle (&box, extents);
2235 _cairo_matrix_transform_bounding_box_fixed (&source->matrix, &box, NULL);
2236 _cairo_box_round_to_rectangle (&box, &rect);
2238 /* Check if image needs padding to fill extents */
2241 if (_cairo_fixed_integer_ceil(box.p1.x) < 0 ||
2242 _cairo_fixed_integer_ceil(box.p1.y) < 0 ||
2243 _cairo_fixed_integer_floor(box.p2.x) > w ||
2244 _cairo_fixed_integer_floor(box.p2.y) > h)
2246 pad_image = _cairo_image_surface_create_with_content (image->base.content,
2249 if (pad_image->status) {
2250 status = pad_image->status;
2254 _cairo_pattern_init_for_surface (&pad_pattern, &image->base);
2255 cairo_matrix_init_translate (&pad_pattern.base.matrix, rect.x, rect.y);
2256 pad_pattern.base.extend = CAIRO_EXTEND_PAD;
2257 status = _cairo_surface_paint (pad_image,
2258 CAIRO_OPERATOR_SOURCE, &pad_pattern.base,
2260 _cairo_pattern_fini (&pad_pattern.base);
2261 if (unlikely (status))
2265 status = _cairo_pdf_surface_add_source_surface (surface,
2280 if (unlikely (status))
2283 if (pad_image != &image->base) {
2284 /* If using a padded image, replace _add_source_surface
2285 * x/y_offset with padded image offset. Note:
2286 * _add_source_surface only sets a non zero x/y_offset for
2287 * RASTER_SOURCE patterns. _add_source_surface will always set
2288 * x/y_offset to 0 for surfaces so we can ignore the returned
2289 * offset and replace it with the offset required for the
2296 if (pad_image != &image->base)
2297 cairo_surface_destroy (pad_image);
2299 _cairo_pdf_surface_release_source_image_from_pattern (surface, source, image, image_extra);
2304 /* Emit alpha channel from the image into stream_res.
2306 static cairo_int_status_t
2307 _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
2308 cairo_image_surface_t *image,
2309 cairo_bool_t stencil_mask,
2310 cairo_bool_t interpolate,
2311 cairo_pdf_resource_t *stream_res)
2313 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
2315 unsigned long alpha_size;
2318 int i, x, y, bit, a;
2319 cairo_image_transparency_t transparency;
2321 /* This is the only image format we support, which simplifies things. */
2322 assert (image->format == CAIRO_FORMAT_ARGB32 ||
2323 image->format == CAIRO_FORMAT_RGB24 ||
2324 image->format == CAIRO_FORMAT_A8 ||
2325 image->format == CAIRO_FORMAT_A1 );
2327 transparency = _cairo_image_analyze_transparency (image);
2329 assert (transparency == CAIRO_IMAGE_IS_OPAQUE ||
2330 transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA);
2332 assert (transparency != CAIRO_IMAGE_IS_OPAQUE);
2335 if (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA || transparency == CAIRO_IMAGE_IS_OPAQUE) {
2336 alpha_size = (image->width + 7) / 8 * image->height;
2337 alpha = _cairo_malloc_ab ((image->width+7) / 8, image->height);
2339 alpha_size = image->height * image->width;
2340 alpha = _cairo_malloc_ab (image->height, image->width);
2343 if (unlikely (alpha == NULL)) {
2344 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2349 for (y = 0; y < image->height; y++) {
2350 if (transparency == CAIRO_IMAGE_IS_OPAQUE) {
2351 for (x = 0; x < (image->width + 7) / 8; x++)
2353 } else if (image->format == CAIRO_FORMAT_A1) {
2354 pixel8 = (uint8_t *) (image->data + y * image->stride);
2356 for (x = 0; x < (image->width + 7) / 8; x++, pixel8++) {
2358 a = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a);
2362 pixel8 = (uint8_t *) (image->data + y * image->stride);
2363 pixel32 = (uint32_t *) (image->data + y * image->stride);
2365 for (x = 0; x < image->width; x++) {
2366 if (image->format == CAIRO_FORMAT_ARGB32) {
2367 a = (*pixel32 & 0xff000000) >> 24;
2374 if (transparency == CAIRO_IMAGE_HAS_ALPHA) {
2376 } else { /* transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA or CAIRO_IMAGE_IS_OPAQUE */
2380 alpha[i] |= (1 << bit);
2394 status = _cairo_pdf_surface_open_stream (surface,
2398 " /Subtype /Image\n"
2399 " /ImageMask true\n"
2402 " /Interpolate %s\n"
2403 " /BitsPerComponent 1\n"
2405 image->width, image->height,
2406 interpolate ? "true" : "false");
2408 status = _cairo_pdf_surface_open_stream (surface,
2412 " /Subtype /Image\n"
2415 " /ColorSpace /DeviceGray\n"
2416 " /Interpolate %s\n"
2417 " /BitsPerComponent %d\n",
2418 image->width, image->height,
2419 interpolate ? "true" : "false",
2420 transparency == CAIRO_IMAGE_HAS_ALPHA ? 8 : 1);
2422 if (unlikely (status))
2425 _cairo_output_stream_write (surface->output, alpha, alpha_size);
2426 status = _cairo_pdf_surface_close_stream (surface);
2435 * _cairo_pdf_surface_emit_image:
2436 * @surface: the pdf surface
2437 * @image_surf: The image to write
2438 * @surface_entry: Contains image resource, smask resource, interpolate and stencil mask parameters.
2440 * Emit an image stream using the @image_res resource and write out
2441 * the image data from @image_surf. If @smask_res is not null, @smask_res will
2442 * be specified as the smask for the image. Otherwise emit the an smask if
2443 * the image is requires one.
2445 static cairo_int_status_t
2446 _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
2447 cairo_image_surface_t *image_surf,
2448 cairo_pdf_source_surface_entry_t *surface_entry)
2450 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
2452 unsigned long data_size;
2455 cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
2456 cairo_bool_t need_smask;
2457 cairo_image_color_t color;
2458 cairo_image_surface_t *image;
2459 cairo_image_transparency_t transparency;
2463 if (image->format != CAIRO_FORMAT_RGB24 &&
2464 image->format != CAIRO_FORMAT_ARGB32 &&
2465 image->format != CAIRO_FORMAT_A8 &&
2466 image->format != CAIRO_FORMAT_A1)
2468 cairo_surface_t *surf;
2469 cairo_surface_pattern_t pattern;
2471 surf = _cairo_image_surface_create_with_content (image_surf->base.content,
2473 image_surf->height);
2474 image = (cairo_image_surface_t *) surf;
2476 status = surf->status;
2480 _cairo_pattern_init_for_surface (&pattern, &image_surf->base);
2481 status = _cairo_surface_paint (surf,
2482 CAIRO_OPERATOR_SOURCE, &pattern.base,
2484 _cairo_pattern_fini (&pattern.base);
2485 if (unlikely (status))
2489 if (surface_entry->smask || surface_entry->stencil_mask) {
2490 return _cairo_pdf_surface_emit_smask (surface, image,
2491 surface_entry->stencil_mask,
2492 surface_entry->interpolate,
2493 &surface_entry->surface_res);
2496 color = _cairo_image_analyze_color (image);
2499 case CAIRO_IMAGE_UNKNOWN_COLOR:
2501 case CAIRO_IMAGE_IS_COLOR:
2502 data_size = image->height * image->width * 3;
2503 data = _cairo_malloc_abc (image->width, image->height, 3);
2506 case CAIRO_IMAGE_IS_GRAYSCALE:
2507 data_size = image->height * image->width;
2508 data = _cairo_malloc_ab (image->width, image->height);
2510 case CAIRO_IMAGE_IS_MONOCHROME:
2511 data_size = (image->width + 7) / 8 * image->height;
2512 data = _cairo_malloc_ab ((image->width+7) / 8, image->height);
2515 if (unlikely (data == NULL)) {
2516 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2521 for (y = 0; y < image->height; y++) {
2522 pixel = (uint32_t *) (image->data + y * image->stride);
2525 for (x = 0; x < image->width; x++, pixel++) {
2528 /* XXX: We're un-premultiplying alpha here. My reading of the PDF
2529 * specification suggests that we should be able to avoid having
2530 * to do this by filling in the SMask's Matte dictionary
2531 * appropriately, but my attempts to do that so far have
2533 if (image->format == CAIRO_FORMAT_ARGB32) {
2535 a = (*pixel & 0xff000000) >> 24;
2539 r = (((*pixel & 0xff0000) >> 16) * 255 + a / 2) / a;
2540 g = (((*pixel & 0x00ff00) >> 8) * 255 + a / 2) / a;
2541 b = (((*pixel & 0x0000ff) >> 0) * 255 + a / 2) / a;
2543 } else if (image->format == CAIRO_FORMAT_RGB24) {
2544 r = (*pixel & 0x00ff0000) >> 16;
2545 g = (*pixel & 0x0000ff00) >> 8;
2546 b = (*pixel & 0x000000ff) >> 0;
2552 case CAIRO_IMAGE_IS_COLOR:
2553 case CAIRO_IMAGE_UNKNOWN_COLOR:
2559 case CAIRO_IMAGE_IS_GRAYSCALE:
2563 case CAIRO_IMAGE_IS_MONOCHROME:
2567 data[i] |= (1 << bit);
2580 if (surface_entry->smask_res.id != 0) {
2582 smask = surface_entry->smask_res;
2585 if (image->format == CAIRO_FORMAT_ARGB32 ||
2586 image->format == CAIRO_FORMAT_A8 ||
2587 image->format == CAIRO_FORMAT_A1)
2589 transparency = _cairo_image_analyze_transparency (image);
2590 if (transparency != CAIRO_IMAGE_IS_OPAQUE) {
2592 smask = _cairo_pdf_surface_new_object (surface);
2593 if (smask.id == 0) {
2594 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2598 status = _cairo_pdf_surface_emit_smask (surface, image, FALSE, surface_entry->interpolate, &smask);
2599 if (unlikely (status))
2606 snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", smask.id);
2610 status = _cairo_pdf_surface_open_stream (surface,
2611 &surface_entry->surface_res,
2614 " /Subtype /Image\n"
2618 " /Interpolate %s\n"
2619 " /BitsPerComponent %d\n"
2623 color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray",
2624 surface_entry->interpolate ? "true" : "false",
2625 color == CAIRO_IMAGE_IS_MONOCHROME? 1 : 8,
2627 if (unlikely (status))
2630 #undef IMAGE_DICTIONARY
2632 _cairo_output_stream_write (surface->output, data, data_size);
2633 status = _cairo_pdf_surface_close_stream (surface);
2638 if (image != image_surf)
2639 cairo_surface_destroy (&image->base);
2644 static cairo_int_status_t
2645 _cairo_pdf_surface_lookup_jbig2_global (cairo_pdf_surface_t *surface,
2646 const unsigned char *global_id,
2647 unsigned long global_id_length,
2648 cairo_pdf_jbig2_global_t **entry)
2650 cairo_pdf_jbig2_global_t global;
2652 cairo_int_status_t status;
2654 size = _cairo_array_num_elements (&surface->jbig2_global);
2655 for (i = 0; i < size; i++) {
2656 *entry = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, i);
2657 if ((*entry)->id && global_id && (*entry)->id_length == global_id_length
2658 && memcmp((*entry)->id, global_id, global_id_length) == 0) {
2659 return CAIRO_STATUS_SUCCESS;
2663 global.id = malloc(global_id_length);
2664 if (unlikely (global.id == NULL)) {
2665 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2668 memcpy (global.id, global_id, global_id_length);
2669 global.id_length = global_id_length;
2670 global.res = _cairo_pdf_surface_new_object (surface);
2671 if (global.res.id == 0) {
2673 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2676 global.emitted = FALSE;
2677 status = _cairo_array_append (&surface->jbig2_global, &global);
2678 if (unlikely(status))
2681 size = _cairo_array_num_elements (&surface->jbig2_global);
2682 *entry = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, size - 1);
2683 return CAIRO_STATUS_SUCCESS;
2686 static cairo_int_status_t
2687 _cairo_pdf_surface_emit_jbig2_image (cairo_pdf_surface_t *surface,
2688 cairo_surface_t *source,
2689 cairo_pdf_source_surface_entry_t *surface_entry)
2691 cairo_int_status_t status;
2692 const unsigned char *mime_data;
2693 unsigned long mime_data_length;
2694 cairo_image_info_t info;
2695 const unsigned char *global_id;
2696 unsigned long global_id_length;
2697 const unsigned char *global_data;
2698 unsigned long global_data_length;
2699 cairo_pdf_jbig2_global_t *global_entry = NULL; /* hide compiler warning */
2701 char decode_parms_buf[100];
2703 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2,
2704 &mime_data, &mime_data_length);
2705 if (mime_data == NULL)
2706 return CAIRO_INT_STATUS_UNSUPPORTED;
2708 status = _cairo_image_info_get_jbig2_info (&info, mime_data, mime_data_length);
2712 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
2713 &global_id, &global_id_length);
2714 if (global_id && global_id_length > 0) {
2715 status = _cairo_pdf_surface_lookup_jbig2_global (surface, global_id, global_id_length, &global_entry);
2716 if (unlikely(status))
2719 if (!global_entry->emitted) {
2720 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL,
2721 &global_data, &global_data_length);
2723 status = _cairo_pdf_surface_open_stream (surface, &global_entry->res, FALSE, NULL);
2724 if (unlikely(status))
2727 _cairo_output_stream_write (surface->output, global_data, global_data_length);
2728 status = _cairo_pdf_surface_close_stream (surface);
2729 if (unlikely(status))
2732 global_entry->emitted = TRUE;
2736 snprintf(decode_parms_buf, sizeof(decode_parms_buf),
2737 " /DecodeParms << /JBIG2Globals %d 0 R >>\n", global_entry->res.id);
2739 decode_parms_buf[0] = 0;
2742 if (surface_entry->smask_res.id)
2743 snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", surface_entry->smask_res.id);
2747 if (surface_entry->stencil_mask) {
2748 status = _cairo_pdf_surface_open_stream (surface,
2749 &surface_entry->surface_res,
2752 " /Subtype /Image\n"
2753 " /ImageMask true\n"
2756 " /Interpolate %s\n"
2757 " /BitsPerComponent 1\n"
2759 " /Filter /JPXDecode\n"
2763 surface_entry->interpolate ? "true" : "false",
2766 status = _cairo_pdf_surface_open_stream (surface,
2767 &surface_entry->surface_res,
2770 " /Subtype /Image\n"
2773 " /ColorSpace /DeviceGray\n"
2774 " /BitsPerComponent 1\n"
2775 " /Interpolate %s\n"
2777 " /Filter /JBIG2Decode\n"
2781 surface_entry->interpolate ? "true" : "false",
2785 if (unlikely(status))
2788 _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
2789 status = _cairo_pdf_surface_close_stream (surface);
2794 static cairo_int_status_t
2795 _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface,
2796 cairo_surface_t *source,
2797 cairo_pdf_source_surface_entry_t *surface_entry)
2799 cairo_int_status_t status;
2800 const unsigned char *mime_data;
2801 unsigned long mime_data_length;
2802 cairo_image_info_t info;
2805 if (surface->pdf_version < CAIRO_PDF_VERSION_1_5)
2806 return CAIRO_INT_STATUS_UNSUPPORTED;
2808 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
2809 &mime_data, &mime_data_length);
2810 if (mime_data == NULL)
2811 return CAIRO_INT_STATUS_UNSUPPORTED;
2813 status = _cairo_image_info_get_jpx_info (&info, mime_data, mime_data_length);
2817 if ((surface_entry->smask || surface_entry->stencil_mask) && info.num_components != 1)
2818 return CAIRO_INT_STATUS_UNSUPPORTED;
2820 if ((surface_entry->stencil_mask) && info.bits_per_component != 1)
2821 return CAIRO_INT_STATUS_UNSUPPORTED;
2823 if (surface_entry->smask_res.id)
2824 snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", surface_entry->smask_res.id);
2828 if (surface_entry->stencil_mask) {
2829 status = _cairo_pdf_surface_open_stream (surface,
2830 &surface_entry->surface_res,
2833 " /Subtype /Image\n"
2834 " /ImageMask true\n"
2837 " /Interpolate %s\n"
2838 " /BitsPerComponent 1\n"
2840 " /Filter /JPXDecode\n",
2843 surface_entry->interpolate ? "true" : "false");
2845 status = _cairo_pdf_surface_open_stream (surface,
2846 &surface_entry->surface_res,
2849 " /Subtype /Image\n"
2852 " /Interpolate %s\n"
2854 " /Filter /JPXDecode\n",
2857 surface_entry->interpolate ? "true" : "false",
2863 _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
2864 status = _cairo_pdf_surface_close_stream (surface);
2869 static cairo_int_status_t
2870 _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
2871 cairo_surface_t *source,
2872 cairo_pdf_source_surface_entry_t *surface_entry)
2874 cairo_int_status_t status;
2875 const unsigned char *mime_data;
2876 unsigned long mime_data_length;
2877 cairo_image_info_t info;
2878 const char *colorspace;
2881 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
2882 &mime_data, &mime_data_length);
2883 if (unlikely (source->status))
2884 return source->status;
2885 if (mime_data == NULL)
2886 return CAIRO_INT_STATUS_UNSUPPORTED;
2888 status = _cairo_image_info_get_jpeg_info (&info, mime_data, mime_data_length);
2889 if (unlikely (status))
2892 if ((surface_entry->smask || surface_entry->stencil_mask) && info.num_components != 1)
2893 return CAIRO_INT_STATUS_UNSUPPORTED;
2895 if ((surface_entry->stencil_mask) && info.bits_per_component != 1)
2896 return CAIRO_INT_STATUS_UNSUPPORTED;
2898 switch (info.num_components) {
2900 colorspace = "/DeviceGray";
2903 colorspace = "/DeviceRGB";
2906 colorspace = "/DeviceCMYK";
2909 return CAIRO_INT_STATUS_UNSUPPORTED;
2912 if (surface_entry->smask_res.id)
2913 snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", surface_entry->smask_res.id);
2917 if (surface_entry->stencil_mask) {
2918 status = _cairo_pdf_surface_open_stream (surface,
2919 &surface_entry->surface_res,
2922 " /Subtype /Image\n"
2923 " /ImageMask true\n"
2926 " /Interpolate %s\n"
2927 " /BitsPerComponent 1\n"
2929 " /Filter /DCTDecode\n",
2932 surface_entry->interpolate ? "true" : "false");
2934 status = _cairo_pdf_surface_open_stream (surface,
2935 &surface_entry->surface_res,
2938 " /Subtype /Image\n"
2942 " /Interpolate %s\n"
2943 " /BitsPerComponent %d\n"
2945 " /Filter /DCTDecode\n",
2949 surface_entry->interpolate ? "true" : "false",
2950 info.bits_per_component,
2953 if (unlikely (status))
2956 _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
2957 status = _cairo_pdf_surface_close_stream (surface);
2962 static cairo_int_status_t
2963 _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
2964 cairo_pdf_source_surface_t *source)
2966 cairo_image_surface_t *image;
2968 cairo_int_status_t status;
2970 if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
2971 status = _cairo_pdf_surface_emit_jbig2_image (surface, source->surface, source->hash_entry);
2972 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2975 status = _cairo_pdf_surface_emit_jpx_image (surface, source->surface, source->hash_entry);
2976 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2979 status = _cairo_pdf_surface_emit_jpeg_image (surface, source->surface, source->hash_entry);
2980 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2984 if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
2985 status = _cairo_surface_acquire_source_image (source->surface, &image, &image_extra);
2987 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source->raster_pattern,
2988 &image, &image_extra);
2990 if (unlikely (status))
2993 status = _cairo_pdf_surface_emit_image (surface,
2995 source->hash_entry);
2997 if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
2998 _cairo_surface_release_source_image (source->surface, image, image_extra);
3000 _cairo_pdf_surface_release_source_image_from_pattern (surface, source->raster_pattern,
3001 image, image_extra);
3006 static cairo_int_status_t
3007 _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
3008 cairo_pdf_source_surface_t *pdf_source)
3010 double old_width, old_height;
3011 cairo_paginated_mode_t old_paginated_mode;
3012 cairo_surface_clipper_t old_clipper;
3013 cairo_box_double_t bbox;
3014 cairo_int_status_t status;
3016 cairo_surface_t *free_me = NULL;
3017 cairo_surface_t *source;
3018 const cairo_rectangle_int_t *extents;
3021 cairo_bool_t is_subsurface;
3022 cairo_bool_t transparency_group;
3023 cairo_recording_surface_t *recording;
3025 assert (pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE);
3026 extents = &pdf_source->hash_entry->extents;
3027 width = pdf_source->hash_entry->width;
3028 height = pdf_source->hash_entry->height;
3029 is_subsurface = FALSE;
3030 source = pdf_source->surface;
3031 if (_cairo_surface_is_snapshot (source)) {
3032 free_me = source = _cairo_surface_snapshot_get_target (source);
3033 } else if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
3034 cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
3036 source = sub->target;
3037 extents = &sub->extents;
3038 width = extents->width;
3039 height = extents->height;
3040 is_subsurface = TRUE;
3043 assert (source->type == CAIRO_SURFACE_TYPE_RECORDING);
3044 recording = (cairo_recording_surface_t *) source;
3046 old_width = surface->width;
3047 old_height = surface->height;
3048 old_paginated_mode = surface->paginated_mode;
3049 old_clipper = surface->clipper;
3050 _cairo_surface_clipper_init (&surface->clipper,
3051 _cairo_pdf_surface_clipper_intersect_clip_path);
3053 _cairo_pdf_surface_set_size_internal (surface, width, height);
3055 /* Patterns are emitted after fallback images. The paginated mode
3056 * needs to be set to _RENDER while the recording surface is replayed
3057 * back to this surface.
3059 surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
3060 _cairo_pdf_group_resources_clear (&surface->resources);
3061 _get_bbox_from_extents (height, extents, &bbox);
3063 /* We can optimize away the transparency group allowing the viewer
3064 * to replay the group in place when all operators are OVER and the
3065 * recording contains only opaque and/or clear alpha.
3067 transparency_group = !(pdf_source->hash_entry->operator == CAIRO_OPERATOR_OVER &&
3068 _cairo_recording_surface_has_only_bilevel_alpha (recording) &&
3069 _cairo_recording_surface_has_only_op_over (recording));
3070 status = _cairo_pdf_surface_open_content_stream (surface, &bbox, &pdf_source->hash_entry->surface_res,
3071 TRUE, transparency_group);
3072 if (unlikely (status))
3075 if (source->content == CAIRO_CONTENT_COLOR) {
3076 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
3077 if (unlikely (status))
3080 _cairo_output_stream_printf (surface->output,
3081 "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
3087 status = _cairo_recording_surface_replay_region (source,
3088 is_subsurface ? extents : NULL,
3090 CAIRO_RECORDING_REGION_NATIVE);
3091 assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
3092 if (unlikely (status))
3095 status = _cairo_pdf_surface_close_content_stream (surface);
3097 _cairo_surface_clipper_reset (&surface->clipper);
3098 surface->clipper = old_clipper;
3099 _cairo_pdf_surface_set_size_internal (surface,
3102 surface->paginated_mode = old_paginated_mode;
3105 cairo_surface_destroy (free_me);
3109 static cairo_int_status_t
3110 _cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface,
3111 cairo_pdf_source_surface_t *src_surface)
3113 if (src_surface->type == CAIRO_PATTERN_TYPE_SURFACE &&
3114 src_surface->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
3115 return _cairo_pdf_surface_emit_recording_surface (surface, src_surface);
3117 return _cairo_pdf_surface_emit_image_surface (surface, src_surface);
3120 static cairo_int_status_t
3121 _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
3122 cairo_pdf_pattern_t *pdf_pattern)
3124 cairo_pattern_t *pattern = pdf_pattern->pattern;
3125 cairo_int_status_t status;
3126 cairo_pdf_resource_t pattern_resource = {0};
3127 cairo_matrix_t cairo_p2d, pdf_p2d;
3128 cairo_extend_t extend = cairo_pattern_get_extend (pattern);
3129 double xstep, ystep;
3130 cairo_rectangle_int_t pattern_extents;
3131 int pattern_width = 0; /* squelch bogus compiler warning */
3132 int pattern_height = 0; /* squelch bogus compiler warning */
3135 char draw_surface[200];
3136 cairo_box_double_t bbox;
3138 if (pattern->extend == CAIRO_EXTEND_PAD) {
3139 status = _cairo_pdf_surface_add_padded_image_surface (surface,
3141 &pdf_pattern->extents,
3147 pattern_extents.x = 0;
3148 pattern_extents.y = 0;
3149 pattern_extents.width = pattern_width;
3150 pattern_extents.height = pattern_height;
3152 status = _cairo_pdf_surface_add_source_surface (surface,
3155 pdf_pattern->operator,
3159 &pdf_pattern->extents,
3168 if (unlikely (status))
3172 case CAIRO_EXTEND_PAD:
3173 case CAIRO_EXTEND_NONE:
3175 /* In PS/PDF, (as far as I can tell), all patterns are
3176 * repeating. So we support cairo's EXTEND_NONE semantics
3177 * by setting the repeat step size to a size large enough
3178 * to guarantee that no more than a single occurrence will
3181 * First, map the surface extents into pattern space (since
3182 * xstep and ystep are in pattern space). Then use an upper
3183 * bound on the length of the diagonal of the pattern image
3184 * and the surface as repeat size. This guarantees to never
3187 double x1 = 0.0, y1 = 0.0;
3188 double x2 = surface->width, y2 = surface->height;
3189 _cairo_matrix_transform_bounding_box (&pattern->matrix,
3193 /* Rather than computing precise bounds of the union, just
3194 * add the surface extents unconditionally. We only
3195 * required an answer that's large enough, we don't really
3196 * care if it's not as tight as possible.*/
3197 xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
3198 pattern_width + pattern_height);
3201 case CAIRO_EXTEND_REPEAT:
3202 xstep = pattern_width;
3203 ystep = pattern_height;
3205 case CAIRO_EXTEND_REFLECT:
3206 pattern_extents.x = 0;
3207 pattern_extents.y = 0;
3208 pattern_extents.width = pattern_width*2;
3209 pattern_extents.height = pattern_height*2;
3210 xstep = pattern_width*2;
3211 ystep = pattern_height*2;
3213 /* All the rest (if any) should have been analyzed away, so this
3214 * case should be unreachable. */
3221 /* At this point, (that is, within the surface backend interface),
3222 * the pattern's matrix maps from cairo's device space to cairo's
3223 * pattern space, (both with their origin at the upper-left, and
3224 * cairo's pattern space of size width,height).
3226 * Then, we must emit a PDF pattern object that maps from its own
3227 * pattern space, (which has a size that we establish in the BBox
3228 * dictionary entry), to the PDF page's *initial* space, (which
3229 * does not benefit from the Y-axis flipping matrix that we emit
3230 * on each page). So the PDF patterns matrix maps from a
3231 * (width,height) pattern space to a device space with the origin
3232 * in the lower-left corner.
3234 * So to handle all of that, we start with an identity matrix for
3235 * the PDF pattern to device matrix. We translate it up by the
3236 * image height then flip it in the Y direction, (moving us from
3237 * the PDF origin to cairo's origin). We then multiply in the
3238 * inverse of the cairo pattern matrix, (since it maps from device
3239 * to pattern, while we're setting up pattern to device). Finally,
3240 * we translate back down by the image height and flip again to
3241 * end up at the lower-left origin that PDF expects.
3243 * Additionally, within the stream that paints the pattern itself,
3244 * we are using a PDF image object that has a size of (1,1) so we
3245 * have to scale it up by the image width and height to fill our
3248 cairo_p2d = pattern->matrix;
3249 status = cairo_matrix_invert (&cairo_p2d);
3250 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3251 assert (status == CAIRO_INT_STATUS_SUCCESS);
3253 cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &surface->cairo_to_pdf);
3254 cairo_matrix_translate (&pdf_p2d, -x_offset, -y_offset);
3255 cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
3256 cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
3258 _get_bbox_from_extents (pattern_height, &pattern_extents, &bbox);
3259 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
3260 status = _cairo_pdf_surface_open_stream (surface,
3261 &pdf_pattern->pattern_res,
3264 " /BBox [ %f %f %f %f ]\n"
3269 " /Matrix [ %f %f %f %f %f %f ]\n"
3270 " /Resources << /XObject << /x%d %d 0 R >> >>\n",
3271 bbox.p1.x, bbox.p1.y, bbox.p2.x, bbox.p2.y,
3273 pdf_p2d.xx, pdf_p2d.yx,
3274 pdf_p2d.xy, pdf_p2d.yy,
3275 pdf_p2d.x0, pdf_p2d.y0,
3276 pattern_resource.id,
3277 pattern_resource.id);
3278 if (unlikely (status))
3281 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
3282 ((cairo_surface_pattern_t *) pattern)->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
3283 snprintf(draw_surface,
3284 sizeof (draw_surface),
3286 pattern_resource.id);
3288 snprintf(draw_surface,
3289 sizeof (draw_surface),
3290 "q %d 0 0 %d 0 0 cm /x%d Do Q",
3293 pattern_resource.id);
3296 if (extend == CAIRO_EXTEND_REFLECT) {
3297 _cairo_output_stream_printf (surface->output,
3298 "q 0 0 %d %d re W n %s Q\n"
3299 "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n %s Q\n"
3300 "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n %s Q\n"
3301 "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n %s Q\n",
3302 pattern_width, pattern_height,
3304 pattern_width*2, pattern_width, pattern_height,
3306 pattern_height*2, pattern_width, pattern_height,
3308 pattern_width*2, pattern_height*2, pattern_width, pattern_height,
3311 _cairo_output_stream_printf (surface->output,
3316 status = _cairo_pdf_surface_close_stream (surface);
3317 if (unlikely (status))
3320 return _cairo_output_stream_get_status (surface->output);
3323 typedef struct _cairo_pdf_color_stop {
3326 cairo_pdf_resource_t resource;
3327 } cairo_pdf_color_stop_t;
3329 static cairo_int_status_t
3330 cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t *surface,
3331 cairo_pdf_color_stop_t *stop1,
3332 cairo_pdf_color_stop_t *stop2,
3333 cairo_pdf_resource_t *function)
3336 cairo_pdf_rgb_linear_function_t elem;
3337 cairo_pdf_resource_t res;
3338 cairo_int_status_t status;
3340 num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions);
3341 for (i = 0; i < num_elems; i++) {
3342 _cairo_array_copy_element (&surface->rgb_linear_functions, i, &elem);
3343 if (memcmp (&elem.color1[0], &stop1->color[0], sizeof (double)*3) != 0)
3345 if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0)
3347 *function = elem.resource;
3348 return CAIRO_STATUS_SUCCESS;
3351 res = _cairo_pdf_surface_new_object (surface);
3353 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3355 _cairo_output_stream_printf (surface->output,
3357 "<< /FunctionType 2\n"
3358 " /Domain [ 0 1 ]\n"
3359 " /C0 [ %f %f %f ]\n"
3360 " /C1 [ %f %f %f ]\n"
3372 elem.resource = res;
3373 memcpy (&elem.color1[0], &stop1->color[0], sizeof (double)*3);
3374 memcpy (&elem.color2[0], &stop2->color[0], sizeof (double)*3);
3376 status = _cairo_array_append (&surface->rgb_linear_functions, &elem);
3382 static cairo_int_status_t
3383 cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t *surface,
3384 cairo_pdf_color_stop_t *stop1,
3385 cairo_pdf_color_stop_t *stop2,
3386 cairo_pdf_resource_t *function)
3389 cairo_pdf_alpha_linear_function_t elem;
3390 cairo_pdf_resource_t res;
3391 cairo_int_status_t status;
3393 num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions);
3394 for (i = 0; i < num_elems; i++) {
3395 _cairo_array_copy_element (&surface->alpha_linear_functions, i, &elem);
3396 if (elem.alpha1 != stop1->color[3])
3398 if (elem.alpha2 != stop2->color[3])
3400 *function = elem.resource;
3401 return CAIRO_STATUS_SUCCESS;
3404 res = _cairo_pdf_surface_new_object (surface);
3406 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3408 _cairo_output_stream_printf (surface->output,
3410 "<< /FunctionType 2\n"
3411 " /Domain [ 0 1 ]\n"
3421 elem.resource = res;
3422 elem.alpha1 = stop1->color[3];
3423 elem.alpha2 = stop2->color[3];
3425 status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
3431 static cairo_int_status_t
3432 _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
3433 unsigned int n_stops,
3434 cairo_pdf_color_stop_t *stops,
3435 cairo_bool_t is_alpha,
3436 cairo_pdf_resource_t *function)
3438 cairo_pdf_resource_t res;
3440 cairo_int_status_t status;
3442 /* emit linear gradients between pairs of subsequent stops... */
3443 for (i = 0; i < n_stops-1; i++) {
3445 status = cairo_pdf_surface_emit_alpha_linear_function (surface,
3448 &stops[i].resource);
3449 if (unlikely (status))
3452 status = cairo_pdf_surface_emit_rgb_linear_function (surface,
3455 &stops[i].resource);
3456 if (unlikely (status))
3461 /* ... and stitch them together */
3462 res = _cairo_pdf_surface_new_object (surface);
3464 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3466 _cairo_output_stream_printf (surface->output,
3468 "<< /FunctionType 3\n"
3469 " /Domain [ %f %f ]\n",
3472 stops[n_stops - 1].offset);
3474 _cairo_output_stream_printf (surface->output,
3476 for (i = 0; i < n_stops-1; i++)
3477 _cairo_output_stream_printf (surface->output,
3478 "%d 0 R ", stops[i].resource.id);
3479 _cairo_output_stream_printf (surface->output,
3482 _cairo_output_stream_printf (surface->output,
3484 for (i = 1; i < n_stops-1; i++)
3485 _cairo_output_stream_printf (surface->output,
3486 "%f ", stops[i].offset);
3487 _cairo_output_stream_printf (surface->output,
3490 _cairo_output_stream_printf (surface->output,
3492 for (i = 1; i < n_stops; i++)
3493 _cairo_output_stream_printf (surface->output,
3495 _cairo_output_stream_printf (surface->output,
3498 _cairo_output_stream_printf (surface->output,
3504 return _cairo_output_stream_get_status (surface->output);
3509 calc_gradient_color (cairo_pdf_color_stop_t *new_stop,
3510 cairo_pdf_color_stop_t *stop1,
3511 cairo_pdf_color_stop_t *stop2)
3514 double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
3516 for (i = 0; i < 4; i++)
3517 new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
3520 #define COLOR_STOP_EPSILON 1e-6
3522 static cairo_int_status_t
3523 _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
3524 cairo_gradient_pattern_t *pattern,
3525 cairo_pdf_resource_t *color_function,
3526 cairo_pdf_resource_t *alpha_function)
3528 cairo_pdf_color_stop_t *allstops, *stops;
3529 unsigned int n_stops;
3531 cairo_bool_t emit_alpha = FALSE;
3532 cairo_int_status_t status;
3534 color_function->id = 0;
3535 alpha_function->id = 0;
3537 allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t));
3538 if (unlikely (allstops == NULL))
3539 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3541 stops = &allstops[1];
3542 n_stops = pattern->n_stops;
3544 for (i = 0; i < n_stops; i++) {
3545 stops[i].color[0] = pattern->stops[i].color.red;
3546 stops[i].color[1] = pattern->stops[i].color.green;
3547 stops[i].color[2] = pattern->stops[i].color.blue;
3548 stops[i].color[3] = pattern->stops[i].color.alpha;
3549 if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
3551 stops[i].offset = pattern->stops[i].offset;
3554 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
3555 pattern->base.extend == CAIRO_EXTEND_REFLECT) {
3556 if (stops[0].offset > COLOR_STOP_EPSILON) {
3557 if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
3558 memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
3560 calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
3564 stops[0].offset = 0.0;
3566 if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
3567 if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
3568 memcpy (&stops[n_stops],
3569 &stops[n_stops - 1],
3570 sizeof (cairo_pdf_color_stop_t));
3572 calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
3576 stops[n_stops-1].offset = 1.0;
3579 if (stops[0].offset == stops[n_stops - 1].offset) {
3581 * The first and the last stops have the same offset, but we
3582 * don't want a function with an empty domain, because that
3583 * would provoke underdefined behaviour from rasterisers.
3584 * This can only happen with EXTEND_PAD, because EXTEND_NONE
3585 * is optimised into a clear pattern in cairo-gstate, and
3586 * REFLECT/REPEAT are always transformed to have the first
3587 * stop at t=0 and the last stop at t=1. Thus we want a step
3588 * function going from the first color to the last one.
3590 * This can be accomplished by stitching three functions:
3591 * - a constant first color function,
3592 * - a step from the first color to the last color (with empty domain)
3593 * - a constant last color function
3595 cairo_pdf_color_stop_t pad_stops[4];
3597 assert (pattern->base.extend == CAIRO_EXTEND_PAD);
3599 pad_stops[0] = pad_stops[1] = stops[0];
3600 pad_stops[2] = pad_stops[3] = stops[n_stops - 1];
3602 pad_stops[0].offset = 0;
3603 pad_stops[3].offset = 1;
3605 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3610 if (unlikely (status))
3614 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3619 if (unlikely (status))
3622 } else if (n_stops == 2) {
3623 /* no need for stitched function */
3624 status = cairo_pdf_surface_emit_rgb_linear_function (surface,
3626 &stops[n_stops - 1],
3628 if (unlikely (status))
3632 status = cairo_pdf_surface_emit_alpha_linear_function (surface,
3634 &stops[n_stops - 1],
3636 if (unlikely (status))
3640 /* multiple stops: stitch. XXX possible optimization: regularly spaced
3641 * stops do not require stitching. XXX */
3642 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3647 if (unlikely (status))
3651 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3656 if (unlikely (status))
3666 static cairo_int_status_t
3667 _cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface,
3668 cairo_gradient_pattern_t *pattern,
3669 cairo_pdf_resource_t *function,
3673 cairo_pdf_resource_t res;
3676 res = _cairo_pdf_surface_new_object (surface);
3678 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3680 _cairo_output_stream_printf (surface->output,
3682 "<< /FunctionType 3\n"
3683 " /Domain [ %d %d ]\n",
3688 _cairo_output_stream_printf (surface->output,
3690 for (i = begin; i < end; i++)
3691 _cairo_output_stream_printf (surface->output,
3692 "%d 0 R ", function->id);
3693 _cairo_output_stream_printf (surface->output,
3696 _cairo_output_stream_printf (surface->output,
3698 for (i = begin + 1; i < end; i++)
3699 _cairo_output_stream_printf (surface->output,
3701 _cairo_output_stream_printf (surface->output,
3704 _cairo_output_stream_printf (surface->output,
3706 for (i = begin; i < end; i++) {
3707 if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) {
3708 _cairo_output_stream_printf (surface->output,
3711 _cairo_output_stream_printf (surface->output,
3715 _cairo_output_stream_printf (surface->output,
3718 _cairo_output_stream_printf (surface->output,
3724 return _cairo_output_stream_get_status (surface->output);
3727 static cairo_int_status_t
3728 cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
3729 cairo_pdf_pattern_t *pdf_pattern,
3730 cairo_pdf_resource_t gstate_resource,
3731 cairo_pdf_resource_t gradient_mask)
3733 cairo_pdf_resource_t smask_resource;
3734 cairo_int_status_t status;
3736 double x1, y1, x2, y2;
3738 if (pdf_pattern->is_shading) {
3739 snprintf(buf, sizeof(buf),
3741 " << /sh%d %d 0 R >>\n",
3745 snprintf(buf, sizeof(buf),
3747 " << /p%d %d 0 R >>\n",
3752 if (pdf_pattern->is_shading) {
3755 /* When emitting a shading operator we are in cairo pattern
3756 * coordinates. _cairo_pdf_surface_paint_gradient has set the
3757 * ctm to the pattern matrix (including the convertion from
3758 * pdf to cairo coordinates) */
3759 _cairo_box_from_rectangle (&box, &pdf_pattern->extents);
3760 _cairo_box_to_doubles (&box, &x1, &y1, &x2, &y2);
3761 _cairo_matrix_transform_bounding_box (&pdf_pattern->pattern->matrix, &x1, &y1, &x2, &y2, NULL);
3763 cairo_box_double_t box;
3765 /* When emitting a shading pattern we are in pdf page
3766 * coordinates. The color and alpha shading patterns painted
3767 * in the XObject below contain the cairo pattern to pdf page
3768 * matrix in the /Matrix entry of the pattern. */
3769 _get_bbox_from_extents (pdf_pattern->height, &pdf_pattern->extents, &box);
3775 status = _cairo_pdf_surface_open_stream (surface,
3777 surface->compress_content,
3781 " /BBox [ %f %f %f %f ]\n"
3784 " << /a0 << /ca 1 /CA 1 >>"
3789 " << /Type /Group\n"
3790 " /S /Transparency\n"
3792 " /CS /DeviceGray\n"
3796 if (unlikely (status))
3799 if (pdf_pattern->is_shading) {
3800 _cairo_output_stream_printf (surface->output,
3801 "/a0 gs /sh%d sh\n",
3804 _cairo_output_stream_printf (surface->output,
3807 "/Pattern cs /p%d scn\n"
3816 status = _cairo_pdf_surface_close_stream (surface);
3817 if (unlikely (status))
3820 smask_resource = _cairo_pdf_surface_new_object (surface);
3821 if (smask_resource.id == 0)
3822 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3824 _cairo_output_stream_printf (surface->output,
3832 surface->pdf_stream.self.id);
3834 /* Create GState which uses the transparency group as an SMask. */
3835 _cairo_pdf_surface_update_object (surface, gstate_resource);
3837 _cairo_output_stream_printf (surface->output,
3839 "<< /Type /ExtGState\n"
3849 return _cairo_output_stream_get_status (surface->output);
3853 _cairo_pdf_surface_output_gradient (cairo_pdf_surface_t *surface,
3854 const cairo_pdf_pattern_t *pdf_pattern,
3855 cairo_pdf_resource_t pattern_resource,
3856 const cairo_matrix_t *pat_to_pdf,
3857 const cairo_circle_double_t*start,
3858 const cairo_circle_double_t*end,
3859 const double *domain,
3860 const char *colorspace,
3861 cairo_pdf_resource_t color_function)
3863 _cairo_output_stream_printf (surface->output,
3865 pattern_resource.id);
3867 if (!pdf_pattern->is_shading) {
3868 _cairo_output_stream_printf (surface->output,
3869 "<< /Type /Pattern\n"
3872 _cairo_output_stream_print_matrix (surface->output, pat_to_pdf);
3873 _cairo_output_stream_printf (surface->output,
3878 if (pdf_pattern->pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
3879 _cairo_output_stream_printf (surface->output,
3880 " << /ShadingType 2\n"
3882 " /Coords [ %f %f %f %f ]\n",
3884 start->center.x, start->center.y,
3885 end->center.x, end->center.y);
3887 _cairo_output_stream_printf (surface->output,
3888 " << /ShadingType 3\n"
3890 " /Coords [ %f %f %f %f %f %f ]\n",
3892 start->center.x, start->center.y,
3893 MAX (start->radius, 0),
3894 end->center.x, end->center.y,
3895 MAX (end->radius, 0));
3898 _cairo_output_stream_printf (surface->output,
3899 " /Domain [ %f %f ]\n",
3900 domain[0], domain[1]);
3902 if (pdf_pattern->pattern->extend != CAIRO_EXTEND_NONE) {
3903 _cairo_output_stream_printf (surface->output,
3904 " /Extend [ true true ]\n");
3906 _cairo_output_stream_printf (surface->output,
3907 " /Extend [ false false ]\n");
3910 _cairo_output_stream_printf (surface->output,
3911 " /Function %d 0 R\n"
3915 if (!pdf_pattern->is_shading) {
3916 _cairo_output_stream_printf (surface->output,
3920 _cairo_output_stream_printf (surface->output,
3924 static cairo_int_status_t
3925 _cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t *surface,
3926 cairo_pdf_pattern_t *pdf_pattern)
3928 cairo_gradient_pattern_t *pattern = (cairo_gradient_pattern_t *) pdf_pattern->pattern;
3929 cairo_pdf_resource_t color_function, alpha_function;
3930 cairo_matrix_t pat_to_pdf;
3931 cairo_circle_double_t start, end;
3933 cairo_int_status_t status;
3935 assert (pattern->n_stops != 0);
3937 status = _cairo_pdf_surface_emit_pattern_stops (surface,
3941 if (unlikely (status))
3944 pat_to_pdf = pattern->base.matrix;
3945 status = cairo_matrix_invert (&pat_to_pdf);
3946 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3947 assert (status == CAIRO_INT_STATUS_SUCCESS);
3948 cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
3950 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
3951 pattern->base.extend == CAIRO_EXTEND_REFLECT)
3953 double bounds_x1, bounds_x2, bounds_y1, bounds_y2;
3954 double x_scale, y_scale, tolerance;
3956 /* TODO: use tighter extents */
3959 bounds_x2 = surface->width;
3960 bounds_y2 = surface->height;
3961 _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
3962 &bounds_x1, &bounds_y1,
3963 &bounds_x2, &bounds_y2,
3966 x_scale = surface->base.x_resolution / surface->base.x_fallback_resolution;
3967 y_scale = surface->base.y_resolution / surface->base.y_fallback_resolution;
3969 tolerance = fabs (_cairo_matrix_compute_determinant (&pattern->base.matrix));
3970 tolerance /= _cairo_matrix_transformed_circle_major_axis (&pattern->base.matrix, 1);
3971 tolerance *= MIN (x_scale, y_scale);
3973 _cairo_gradient_pattern_box_to_parameter (pattern,
3974 bounds_x1, bounds_y1,
3975 bounds_x2, bounds_y2,
3977 } else if (pattern->stops[0].offset == pattern->stops[pattern->n_stops - 1].offset) {
3979 * If the first and the last stop offset are the same, then
3980 * the color function is a step function.
3981 * _cairo_ps_surface_emit_pattern_stops emits it as a stitched
3982 * function no matter how many stops the pattern has. The
3983 * domain of the stitched function will be [0 1] in this case.
3985 * This is done to avoid emitting degenerate gradients for
3986 * EXTEND_PAD patterns having a step color function.
3991 assert (pattern->base.extend == CAIRO_EXTEND_PAD);
3993 domain[0] = pattern->stops[0].offset;
3994 domain[1] = pattern->stops[pattern->n_stops - 1].offset;
3997 /* PDF requires the first and last stop to be the same as the
3998 * extreme coordinates. For repeating patterns this moves the
3999 * extreme coordinates out to the begin/end of the repeating
4000 * function. For non repeating patterns this may move the extreme
4001 * coordinates in if there are not stops at offset 0 and 1. */
4002 _cairo_gradient_pattern_interpolate (pattern, domain[0], &start);
4003 _cairo_gradient_pattern_interpolate (pattern, domain[1], &end);
4005 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
4006 pattern->base.extend == CAIRO_EXTEND_REFLECT)
4008 int repeat_begin, repeat_end;
4010 repeat_begin = floor (domain[0]);
4011 repeat_end = ceil (domain[1]);
4013 status = _cairo_pdf_surface_emit_repeating_function (surface,
4018 if (unlikely (status))
4021 if (alpha_function.id != 0) {
4022 status = _cairo_pdf_surface_emit_repeating_function (surface,
4027 if (unlikely (status))
4030 } else if (pattern->n_stops <= 2) {
4031 /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
4032 * Type 2 function is used by itself without a stitching
4033 * function. Type 2 functions always have the domain [0 1] */
4038 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
4039 _cairo_pdf_surface_output_gradient (surface, pdf_pattern,
4040 pdf_pattern->pattern_res,
4041 &pat_to_pdf, &start, &end, domain,
4042 "/DeviceRGB", color_function);
4044 if (alpha_function.id != 0) {
4045 cairo_pdf_resource_t mask_resource;
4047 assert (pdf_pattern->gstate_res.id != 0);
4049 /* Create pattern for SMask. */
4050 mask_resource = _cairo_pdf_surface_new_object (surface);
4051 if (mask_resource.id == 0)
4052 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4054 _cairo_pdf_surface_output_gradient (surface, pdf_pattern,
4056 &pat_to_pdf, &start, &end, domain,
4057 "/DeviceGray", alpha_function);
4059 status = cairo_pdf_surface_emit_transparency_group (surface,
4061 pdf_pattern->gstate_res,
4063 if (unlikely (status))
4067 return _cairo_output_stream_get_status (surface->output);
4070 static cairo_int_status_t
4071 _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
4072 cairo_pdf_pattern_t *pdf_pattern)
4074 cairo_matrix_t pat_to_pdf;
4075 cairo_int_status_t status;
4076 cairo_pattern_t *pattern = pdf_pattern->pattern;
4077 cairo_pdf_shading_t shading;
4079 cairo_pdf_resource_t res;
4081 pat_to_pdf = pattern->matrix;
4082 status = cairo_matrix_invert (&pat_to_pdf);
4083 /* cairo_pattern_set_matrix ensures the matrix is invertible */
4084 assert (status == CAIRO_INT_STATUS_SUCCESS);
4086 cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
4088 status = _cairo_pdf_shading_init_color (&shading, (cairo_mesh_pattern_t *) pattern);
4089 if (unlikely (status))
4092 res = _cairo_pdf_surface_new_object (surface);
4093 if (unlikely (res.id == 0))
4094 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4096 _cairo_output_stream_printf (surface->output,
4098 "<< /ShadingType %d\n"
4099 " /ColorSpace /DeviceRGB\n"
4100 " /BitsPerCoordinate %d\n"
4101 " /BitsPerComponent %d\n"
4102 " /BitsPerFlag %d\n"
4105 shading.shading_type,
4106 shading.bits_per_coordinate,
4107 shading.bits_per_component,
4108 shading.bits_per_flag);
4110 for (i = 0; i < shading.decode_array_length; i++)
4111 _cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
4113 _cairo_output_stream_printf (surface->output,
4118 shading.data_length);
4120 _cairo_output_stream_write (surface->output, shading.data, shading.data_length);
4122 _cairo_output_stream_printf (surface->output,
4126 _cairo_pdf_shading_fini (&shading);
4128 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
4129 _cairo_output_stream_printf (surface->output,
4131 "<< /Type /Pattern\n"
4134 pdf_pattern->pattern_res.id);
4135 _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
4136 _cairo_output_stream_printf (surface->output,
4138 " /Shading %d 0 R\n"
4143 if (pdf_pattern->gstate_res.id != 0) {
4144 cairo_pdf_resource_t mask_resource;
4146 /* Create pattern for SMask. */
4147 res = _cairo_pdf_surface_new_object (surface);
4148 if (unlikely (res.id == 0))
4149 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4151 status = _cairo_pdf_shading_init_alpha (&shading, (cairo_mesh_pattern_t *) pattern);
4152 if (unlikely (status))
4155 _cairo_output_stream_printf (surface->output,
4157 "<< /ShadingType %d\n"
4158 " /ColorSpace /DeviceGray\n"
4159 " /BitsPerCoordinate %d\n"
4160 " /BitsPerComponent %d\n"
4161 " /BitsPerFlag %d\n"
4164 shading.shading_type,
4165 shading.bits_per_coordinate,
4166 shading.bits_per_component,
4167 shading.bits_per_flag);
4169 for (i = 0; i < shading.decode_array_length; i++)
4170 _cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
4172 _cairo_output_stream_printf (surface->output,
4177 shading.data_length);
4179 _cairo_output_stream_write (surface->output, shading.data, shading.data_length);
4181 _cairo_output_stream_printf (surface->output,
4184 _cairo_pdf_shading_fini (&shading);
4186 mask_resource = _cairo_pdf_surface_new_object (surface);
4187 if (unlikely (mask_resource.id == 0))
4188 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4190 _cairo_output_stream_printf (surface->output,
4192 "<< /Type /Pattern\n"
4196 _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
4197 _cairo_output_stream_printf (surface->output,
4199 " /Shading %d 0 R\n"
4204 status = cairo_pdf_surface_emit_transparency_group (surface,
4206 pdf_pattern->gstate_res,
4208 if (unlikely (status))
4212 return _cairo_output_stream_get_status (surface->output);
4215 static cairo_int_status_t
4216 _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
4218 double old_width, old_height;
4219 cairo_int_status_t status;
4221 old_width = surface->width;
4222 old_height = surface->height;
4223 _cairo_pdf_surface_set_size_internal (surface,
4225 pdf_pattern->height);
4227 switch (pdf_pattern->pattern->type) {
4228 case CAIRO_PATTERN_TYPE_SOLID:
4230 status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4233 case CAIRO_PATTERN_TYPE_SURFACE:
4234 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4235 status = _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
4238 case CAIRO_PATTERN_TYPE_LINEAR:
4239 case CAIRO_PATTERN_TYPE_RADIAL:
4240 status = _cairo_pdf_surface_emit_gradient (surface, pdf_pattern);
4243 case CAIRO_PATTERN_TYPE_MESH:
4244 status = _cairo_pdf_surface_emit_mesh_pattern (surface, pdf_pattern);
4249 status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4253 _cairo_pdf_surface_set_size_internal (surface,
4260 static cairo_int_status_t
4261 _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
4262 cairo_operator_t op,
4263 const cairo_pattern_t *source,
4264 const cairo_rectangle_int_t *extents,
4265 cairo_pdf_resource_t *smask_res,
4266 cairo_bool_t stencil_mask)
4268 cairo_pdf_resource_t surface_res;
4270 cairo_matrix_t cairo_p2d, pdf_p2d;
4271 cairo_int_status_t status;
4273 cairo_rectangle_int_t extents2;
4277 if (source->extend == CAIRO_EXTEND_PAD &&
4278 !(source->type == CAIRO_PATTERN_TYPE_SURFACE &&
4279 ((cairo_surface_pattern_t *)source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING))
4281 status = _cairo_pdf_surface_add_padded_image_surface (surface,
4290 status = _cairo_pdf_surface_add_source_surface (surface,
4306 if (unlikely (status))
4309 cairo_p2d = source->matrix;
4310 status = cairo_matrix_invert (&cairo_p2d);
4311 /* cairo_pattern_set_matrix ensures the matrix is invertible */
4312 assert (status == CAIRO_INT_STATUS_SUCCESS);
4314 pdf_p2d = surface->cairo_to_pdf;
4315 cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
4316 cairo_matrix_translate (&pdf_p2d, x_offset, y_offset);
4317 cairo_matrix_translate (&pdf_p2d, 0.0, height);
4318 cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
4319 if (!(source->type == CAIRO_PATTERN_TYPE_SURFACE &&
4320 ((cairo_surface_pattern_t *)source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING))
4322 cairo_matrix_scale (&pdf_p2d, width, height);
4325 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4326 if (unlikely (status))
4329 if (! _cairo_matrix_is_identity (&pdf_p2d)) {
4330 _cairo_output_stream_print_matrix (surface->output, &pdf_p2d);
4331 _cairo_output_stream_printf (surface->output, " cm\n");
4334 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
4335 if (unlikely (status))
4339 _cairo_output_stream_printf (surface->output,
4343 _cairo_output_stream_printf (surface->output,
4344 "/a%d gs /x%d Do\n",
4349 return _cairo_pdf_surface_add_xobject (surface, surface_res);
4352 static cairo_int_status_t
4353 _cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t *surface,
4354 cairo_operator_t op,
4355 const cairo_pattern_t *source,
4356 const cairo_rectangle_int_t *extents)
4358 cairo_pdf_resource_t shading_res, gstate_res;
4359 cairo_matrix_t pat_to_pdf;
4360 cairo_int_status_t status;
4363 status = _cairo_pdf_surface_add_pdf_shading (surface, source,
4365 &shading_res, &gstate_res);
4366 if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
4367 return CAIRO_INT_STATUS_SUCCESS;
4368 if (unlikely (status))
4371 pat_to_pdf = source->matrix;
4372 status = cairo_matrix_invert (&pat_to_pdf);
4373 /* cairo_pattern_set_matrix ensures the matrix is invertible */
4374 assert (status == CAIRO_INT_STATUS_SUCCESS);
4375 cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
4377 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4378 if (unlikely (status))
4381 if (! _cairo_matrix_is_identity (&pat_to_pdf)) {
4382 _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
4383 _cairo_output_stream_printf (surface->output, " cm\n");
4386 status = _cairo_pdf_surface_add_shading (surface, shading_res);
4387 if (unlikely (status))
4390 if (gstate_res.id != 0) {
4391 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
4392 if (unlikely (status))
4395 _cairo_output_stream_printf (surface->output,
4396 "/s%d gs /sh%d sh\n",
4400 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
4401 if (unlikely (status))
4404 _cairo_output_stream_printf (surface->output,
4405 "/a%d gs /sh%d sh\n",
4413 static cairo_int_status_t
4414 _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface,
4415 cairo_operator_t op,
4416 const cairo_pattern_t *source,
4417 const cairo_rectangle_int_t *extents,
4420 switch (source->type) {
4421 case CAIRO_PATTERN_TYPE_SURFACE:
4422 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4423 return _cairo_pdf_surface_paint_surface_pattern (surface,
4429 case CAIRO_PATTERN_TYPE_LINEAR:
4430 case CAIRO_PATTERN_TYPE_RADIAL:
4431 case CAIRO_PATTERN_TYPE_MESH:
4432 return _cairo_pdf_surface_paint_gradient (surface,
4437 case CAIRO_PATTERN_TYPE_SOLID:
4440 return CAIRO_STATUS_SUCCESS;
4445 _can_paint_pattern (const cairo_pattern_t *pattern)
4447 switch (pattern->type) {
4448 case CAIRO_PATTERN_TYPE_SOLID:
4451 case CAIRO_PATTERN_TYPE_SURFACE:
4452 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4453 return (pattern->extend == CAIRO_EXTEND_NONE ||
4454 pattern->extend == CAIRO_EXTEND_PAD);
4456 case CAIRO_PATTERN_TYPE_LINEAR:
4457 case CAIRO_PATTERN_TYPE_RADIAL:
4460 case CAIRO_PATTERN_TYPE_MESH:
4469 static cairo_int_status_t
4470 _cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface,
4471 cairo_operator_t op)
4473 cairo_int_status_t status;
4475 if (op == surface->current_operator)
4476 return CAIRO_STATUS_SUCCESS;
4478 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4479 if (unlikely (status))
4482 _cairo_output_stream_printf (surface->output,
4484 surface->current_operator = op;
4485 _cairo_pdf_surface_add_operator (surface, op);
4487 return CAIRO_STATUS_SUCCESS;
4490 static cairo_int_status_t
4491 _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
4492 const cairo_pattern_t *pattern,
4493 cairo_pdf_resource_t pattern_res,
4494 cairo_bool_t is_stroke)
4496 cairo_int_status_t status;
4498 const cairo_color_t *solid_color = NULL;
4500 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
4501 const cairo_solid_pattern_t *solid = (const cairo_solid_pattern_t *) pattern;
4503 solid_color = &solid->color;
4506 if (solid_color != NULL) {
4507 if (surface->current_pattern_is_solid_color == FALSE ||
4508 surface->current_color_red != solid_color->red ||
4509 surface->current_color_green != solid_color->green ||
4510 surface->current_color_blue != solid_color->blue ||
4511 surface->current_color_is_stroke != is_stroke)
4513 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4514 if (unlikely (status))
4517 _cairo_output_stream_printf (surface->output,
4524 _cairo_output_stream_printf (surface->output, "RG ");
4526 _cairo_output_stream_printf (surface->output, "rg ");
4528 surface->current_color_red = solid_color->red;
4529 surface->current_color_green = solid_color->green;
4530 surface->current_color_blue = solid_color->blue;
4531 surface->current_color_is_stroke = is_stroke;
4534 if (surface->current_pattern_is_solid_color == FALSE ||
4535 surface->current_color_alpha != solid_color->alpha)
4537 status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha);
4538 if (unlikely (status))
4541 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4542 if (unlikely (status))
4545 _cairo_output_stream_printf (surface->output,
4548 surface->current_color_alpha = solid_color->alpha;
4551 surface->current_pattern_is_solid_color = TRUE;
4553 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
4554 if (unlikely (status))
4557 status = _cairo_pdf_surface_add_pattern (surface, pattern_res);
4558 if (unlikely (status))
4561 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4562 if (unlikely (status))
4565 /* fill-stroke calls select_pattern twice. Don't save if the
4566 * gstate is already saved. */
4567 if (!surface->select_pattern_gstate_saved)
4568 _cairo_output_stream_printf (surface->output, "q ");
4571 _cairo_output_stream_printf (surface->output,
4572 "/Pattern CS /p%d SCN ",
4575 _cairo_output_stream_printf (surface->output,
4576 "/Pattern cs /p%d scn ",
4579 _cairo_output_stream_printf (surface->output,
4582 surface->select_pattern_gstate_saved = TRUE;
4583 surface->current_pattern_is_solid_color = FALSE;
4586 return _cairo_output_stream_get_status (surface->output);
4589 static cairo_int_status_t
4590 _cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
4592 cairo_int_status_t status;
4594 if (surface->select_pattern_gstate_saved) {
4595 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4596 if (unlikely (status))
4599 _cairo_output_stream_printf (surface->output, "Q\n");
4600 _cairo_pdf_operators_reset (&surface->pdf_operators);
4601 surface->current_pattern_is_solid_color = FALSE;
4603 surface->select_pattern_gstate_saved = FALSE;
4605 return CAIRO_STATUS_SUCCESS;
4608 static cairo_int_status_t
4609 _cairo_pdf_surface_show_page (void *abstract_surface)
4611 cairo_pdf_surface_t *surface = abstract_surface;
4612 cairo_int_status_t status;
4614 status = _cairo_pdf_surface_close_content_stream (surface);
4615 if (unlikely (status))
4618 _cairo_surface_clipper_reset (&surface->clipper);
4620 status = _cairo_pdf_surface_write_page (surface);
4621 if (unlikely (status))
4624 _cairo_pdf_surface_clear (surface);
4626 return CAIRO_STATUS_SUCCESS;
4630 _cairo_pdf_surface_get_extents (void *abstract_surface,
4631 cairo_rectangle_int_t *rectangle)
4633 cairo_pdf_surface_t *surface = abstract_surface;
4638 /* XXX: The conversion to integers here is pretty bogus, (not to
4639 * mention the arbitrary limitation of width to a short(!). We
4640 * may need to come up with a better interface for get_size.
4642 rectangle->width = ceil (surface->width);
4643 rectangle->height = ceil (surface->height);
4649 _cairo_pdf_surface_get_font_options (void *abstract_surface,
4650 cairo_font_options_t *options)
4652 _cairo_font_options_init_default (options);
4654 cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
4655 cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
4656 cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
4657 _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_OFF);
4660 static cairo_pdf_resource_t
4661 _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface)
4663 cairo_pdf_resource_t info;
4665 info = _cairo_pdf_surface_new_object (surface);
4669 _cairo_output_stream_printf (surface->output,
4671 "<< /Creator (cairo %s (http://cairographics.org))\n"
4672 " /Producer (cairo %s (http://cairographics.org))\n"
4676 cairo_version_string (),
4677 cairo_version_string ());
4683 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
4685 cairo_pdf_resource_t page;
4688 _cairo_pdf_surface_update_object (surface, surface->pages_resource);
4689 _cairo_output_stream_printf (surface->output,
4693 surface->pages_resource.id);
4695 num_pages = _cairo_array_num_elements (&surface->pages);
4696 for (i = 0; i < num_pages; i++) {
4697 _cairo_array_copy_element (&surface->pages, i, &page);
4698 _cairo_output_stream_printf (surface->output, "%d 0 R ", page.id);
4701 _cairo_output_stream_printf (surface->output, "]\n");
4702 _cairo_output_stream_printf (surface->output, " /Count %d\n", num_pages);
4705 /* TODO: Figure out which other defaults to be inherited by /Page
4707 _cairo_output_stream_printf (surface->output,
4712 static cairo_int_status_t
4713 _utf8_to_pdf_string (const char *utf8, char **str_out)
4719 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
4722 len = strlen (utf8);
4723 for (i = 0; i < len; i++) {
4724 unsigned c = utf8[i];
4725 if (c < 32 || c > 126 || c == '(' || c == ')' || c == '\\') {
4732 str = malloc (len + 3);
4734 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4737 for (i = 0; i < len; i++)
4742 uint16_t *utf16 = NULL;
4745 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
4746 if (unlikely (status))
4749 str = malloc (utf16_len*4 + 7);
4752 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4755 strcpy (str, "<FEFF");
4756 for (i = 0; i < utf16_len; i++)
4757 snprintf (str + 4*i + 5, 5, "%04X", utf16[i]);
4767 static cairo_int_status_t
4768 _cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t *surface,
4771 uint16_t *utf16 = NULL;
4773 cairo_int_status_t status;
4776 if (utf8 && *utf8) {
4777 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
4778 if (unlikely (status))
4782 _cairo_output_stream_printf (surface->output, "<");
4783 if (utf16 == NULL || utf16_len == 0) {
4784 /* According to the "ToUnicode Mapping File Tutorial"
4785 * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
4787 * Glyphs that do not map to a Unicode code point must be
4788 * mapped to 0xfffd "REPLACEMENT CHARACTER".
4790 _cairo_output_stream_printf (surface->output,
4793 for (i = 0; i < utf16_len; i++)
4794 _cairo_output_stream_printf (surface->output,
4795 "%04x", (int) (utf16[i]));
4797 _cairo_output_stream_printf (surface->output, ">");
4801 return CAIRO_STATUS_SUCCESS;
4806 * Public domain code from:
4807 * http://burtleburtle.net/bob/hash/doobs.html
4810 #define HASH_MIX(a,b,c) \
4812 a -= b; a -= c; a ^= (c>>13); \
4813 b -= c; b -= a; b ^= (a<<8); \
4814 c -= a; c -= b; c ^= (b>>13); \
4815 a -= b; a -= c; a ^= (c>>12); \
4816 b -= c; b -= a; b ^= (a<<16); \
4817 c -= a; c -= b; c ^= (b>>5); \
4818 a -= b; a -= c; a ^= (c>>3); \
4819 b -= c; b -= a; b ^= (a<<10); \
4820 c -= a; c -= b; c ^= (b>>15); \
4824 _hash_data (const unsigned char *data, int length, uint32_t initval)
4826 uint32_t a, b, c, len;
4829 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
4830 c = initval; /* the previous hash value */
4833 a += (data[0] + ((uint32_t)data[1]<<8) + ((uint32_t)data[2]<<16) + ((uint32_t)data[3]<<24));
4834 b += (data[4] + ((uint32_t)data[5]<<8) + ((uint32_t)data[6]<<16) + ((uint32_t)data[7]<<24));
4835 c += (data[8] + ((uint32_t)data[9]<<8) + ((uint32_t)data[10]<<16)+ ((uint32_t)data[11]<<24));
4843 case 11: c+= ((uint32_t) data[10] << 24);
4844 case 10: c+= ((uint32_t) data[9] << 16);
4845 case 9 : c+= ((uint32_t) data[8] << 8);
4846 case 8 : b+= ((uint32_t) data[7] << 24);
4847 case 7 : b+= ((uint32_t) data[6] << 16);
4848 case 6 : b+= ((uint32_t) data[5] << 8);
4849 case 5 : b+= data[4];
4850 case 4 : a+= ((uint32_t) data[3] << 24);
4851 case 3 : a+= ((uint32_t) data[2] << 16);
4852 case 2 : a+= ((uint32_t) data[1] << 8);
4853 case 1 : a+= data[0];
4861 _create_font_subset_tag (cairo_scaled_font_subset_t *font_subset,
4862 const char *font_name,
4870 hash = _hash_data ((unsigned char *) font_name, strlen(font_name), 0);
4871 hash = _hash_data ((unsigned char *) (font_subset->glyphs),
4872 font_subset->num_glyphs * sizeof(unsigned long), hash);
4874 numerator = abs (hash);
4875 for (i = 0; i < 6; i++) {
4876 d = ldiv (numerator, 26);
4878 tag[i] = 'A' + d.rem;
4883 static cairo_int_status_t
4884 _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
4885 cairo_scaled_font_subset_t *font_subset,
4886 cairo_pdf_resource_t *stream)
4888 unsigned int i, num_bfchar;
4889 cairo_int_status_t status;
4893 status = _cairo_pdf_surface_open_stream (surface,
4895 surface->compress_content,
4897 if (unlikely (status))
4900 _cairo_output_stream_printf (surface->output,
4901 "/CIDInit /ProcSet findresource begin\n"
4905 "<< /Registry (Adobe)\n"
4906 " /Ordering (UCS)\n"
4909 "/CMapName /Adobe-Identity-UCS def\n"
4911 "1 begincodespacerange\n");
4913 if (font_subset->is_composite && !font_subset->is_latin) {
4914 _cairo_output_stream_printf (surface->output,
4917 _cairo_output_stream_printf (surface->output,
4921 _cairo_output_stream_printf (surface->output,
4922 "endcodespacerange\n");
4924 if (font_subset->is_scaled) {
4925 /* Type 3 fonts include glyph 0 in the subset */
4926 num_bfchar = font_subset->num_glyphs;
4928 /* The CMap specification has a limit of 100 characters per beginbfchar operator */
4929 _cairo_output_stream_printf (surface->output,
4931 num_bfchar > 100 ? 100 : num_bfchar);
4933 for (i = 0; i < num_bfchar; i++) {
4934 if (i != 0 && i % 100 == 0) {
4935 _cairo_output_stream_printf (surface->output,
4938 num_bfchar - i > 100 ? 100 : num_bfchar - i);
4940 _cairo_output_stream_printf (surface->output, "<%02x> ", i);
4941 status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
4942 font_subset->utf8[i]);
4943 if (unlikely (status))
4946 _cairo_output_stream_printf (surface->output,
4950 /* Other fonts reserve glyph 0 for .notdef. Omit glyph 0 from the /ToUnicode map */
4951 num_bfchar = font_subset->num_glyphs - 1;
4953 /* The CMap specification has a limit of 100 characters per beginbfchar operator */
4954 _cairo_output_stream_printf (surface->output,
4956 num_bfchar > 100 ? 100 : num_bfchar);
4958 for (i = 0; i < num_bfchar; i++) {
4959 if (i != 0 && i % 100 == 0) {
4960 _cairo_output_stream_printf (surface->output,
4963 num_bfchar - i > 100 ? 100 : num_bfchar - i);
4965 if (font_subset->is_latin)
4966 _cairo_output_stream_printf (surface->output, "<%02x> ", font_subset->to_latin_char[i + 1]);
4967 else if (font_subset->is_composite)
4968 _cairo_output_stream_printf (surface->output, "<%04x> ", i + 1);
4970 _cairo_output_stream_printf (surface->output, "<%02x> ", i + 1);
4972 status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
4973 font_subset->utf8[i + 1]);
4974 if (unlikely (status))
4977 _cairo_output_stream_printf (surface->output,
4982 _cairo_output_stream_printf (surface->output,
4985 _cairo_output_stream_printf (surface->output,
4987 "CMapName currentdict /CMap defineresource pop\n"
4991 *stream = surface->pdf_stream.self;
4992 return _cairo_pdf_surface_close_stream (surface);
4995 #define PDF_UNITS_PER_EM 1000
4997 static cairo_int_status_t
4998 _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
4999 cairo_scaled_font_subset_t *font_subset,
5000 cairo_cff_subset_t *subset)
5002 cairo_pdf_resource_t stream, descriptor, cidfont_dict;
5003 cairo_pdf_resource_t subset_resource, to_unicode_stream;
5004 cairo_pdf_font_t font;
5005 unsigned int i, last_glyph;
5006 cairo_int_status_t status;
5009 _create_font_subset_tag (font_subset, subset->ps_name, tag);
5011 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
5012 font_subset->font_id,
5013 font_subset->subset_id);
5014 if (subset_resource.id == 0)
5015 return CAIRO_STATUS_SUCCESS;
5017 status = _cairo_pdf_surface_open_stream (surface,
5020 font_subset->is_latin ?
5021 " /Subtype /Type1C\n" :
5022 " /Subtype /CIDFontType0C\n");
5023 if (unlikely (status))
5026 stream = surface->pdf_stream.self;
5027 _cairo_output_stream_write (surface->output,
5028 subset->data, subset->data_length);
5029 status = _cairo_pdf_surface_close_stream (surface);
5030 if (unlikely (status))
5033 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
5035 &to_unicode_stream);
5036 if (_cairo_int_status_is_error (status))
5039 descriptor = _cairo_pdf_surface_new_object (surface);
5040 if (descriptor.id == 0)
5041 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5043 _cairo_output_stream_printf (surface->output,
5045 "<< /Type /FontDescriptor\n"
5046 " /FontName /%s+%s\n",
5051 if (subset->family_name_utf8) {
5054 status = _utf8_to_pdf_string (subset->family_name_utf8, &pdf_str);
5055 if (unlikely (status))
5058 _cairo_output_stream_printf (surface->output,
5059 " /FontFamily %s\n",
5064 _cairo_output_stream_printf (surface->output,
5066 " /FontBBox [ %ld %ld %ld %ld ]\n"
5073 " /FontFile3 %u 0 R\n"
5076 (long)(subset->x_min*PDF_UNITS_PER_EM),
5077 (long)(subset->y_min*PDF_UNITS_PER_EM),
5078 (long)(subset->x_max*PDF_UNITS_PER_EM),
5079 (long)(subset->y_max*PDF_UNITS_PER_EM),
5080 (long)(subset->ascent*PDF_UNITS_PER_EM),
5081 (long)(subset->descent*PDF_UNITS_PER_EM),
5082 (long)(subset->y_max*PDF_UNITS_PER_EM),
5085 if (font_subset->is_latin) {
5086 /* find last glyph used */
5087 for (i = 255; i >= 32; i--)
5088 if (font_subset->latin_to_subset_glyph_index[i] > 0)
5092 _cairo_pdf_surface_update_object (surface, subset_resource);
5093 _cairo_output_stream_printf (surface->output,
5096 " /Subtype /Type1\n"
5097 " /BaseFont /%s+%s\n"
5100 " /FontDescriptor %d 0 R\n"
5101 " /Encoding /WinAnsiEncoding\n"
5109 for (i = 32; i < last_glyph + 1; i++) {
5110 int glyph = font_subset->latin_to_subset_glyph_index[i];
5112 _cairo_output_stream_printf (surface->output,
5114 (long)(subset->widths[glyph]*PDF_UNITS_PER_EM));
5116 _cairo_output_stream_printf (surface->output, " 0");
5120 _cairo_output_stream_printf (surface->output,
5123 if (to_unicode_stream.id != 0)
5124 _cairo_output_stream_printf (surface->output,
5125 " /ToUnicode %d 0 R\n",
5126 to_unicode_stream.id);
5128 _cairo_output_stream_printf (surface->output,
5132 cidfont_dict = _cairo_pdf_surface_new_object (surface);
5133 if (cidfont_dict.id == 0)
5134 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5136 _cairo_output_stream_printf (surface->output,
5139 " /Subtype /CIDFontType0\n"
5140 " /BaseFont /%s+%s\n"
5142 " << /Registry (Adobe)\n"
5143 " /Ordering (Identity)\n"
5146 " /FontDescriptor %d 0 R\n"
5153 for (i = 0; i < font_subset->num_glyphs; i++)
5154 _cairo_output_stream_printf (surface->output,
5156 (long)(subset->widths[i]*PDF_UNITS_PER_EM));
5158 _cairo_output_stream_printf (surface->output,
5163 _cairo_pdf_surface_update_object (surface, subset_resource);
5164 _cairo_output_stream_printf (surface->output,
5167 " /Subtype /Type0\n"
5168 " /BaseFont /%s+%s\n"
5169 " /Encoding /Identity-H\n"
5170 " /DescendantFonts [ %d 0 R]\n",
5176 if (to_unicode_stream.id != 0)
5177 _cairo_output_stream_printf (surface->output,
5178 " /ToUnicode %d 0 R\n",
5179 to_unicode_stream.id);
5181 _cairo_output_stream_printf (surface->output,
5186 font.font_id = font_subset->font_id;
5187 font.subset_id = font_subset->subset_id;
5188 font.subset_resource = subset_resource;
5189 status = _cairo_array_append (&surface->fonts, &font);
5194 static cairo_int_status_t
5195 _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
5196 cairo_scaled_font_subset_t *font_subset)
5198 cairo_int_status_t status;
5199 cairo_cff_subset_t subset;
5202 snprintf (name, sizeof name, "CairoFont-%d-%d",
5203 font_subset->font_id, font_subset->subset_id);
5204 status = _cairo_cff_subset_init (&subset, name, font_subset);
5205 if (unlikely (status))
5208 status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
5210 _cairo_cff_subset_fini (&subset);
5215 static cairo_int_status_t
5216 _cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t *surface,
5217 cairo_scaled_font_subset_t *font_subset)
5219 cairo_int_status_t status;
5220 cairo_cff_subset_t subset;
5223 /* CFF fallback subsetting does not work with 8-bit glyphs unless
5224 * they are a latin subset */
5225 if (!font_subset->is_composite && !font_subset->is_latin)
5226 return CAIRO_INT_STATUS_UNSUPPORTED;
5228 snprintf (name, sizeof name, "CairoFont-%d-%d",
5229 font_subset->font_id, font_subset->subset_id);
5230 status = _cairo_cff_fallback_init (&subset, name, font_subset);
5231 if (unlikely (status))
5234 status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
5236 _cairo_cff_fallback_fini (&subset);
5241 static cairo_int_status_t
5242 _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
5243 cairo_scaled_font_subset_t *font_subset,
5244 cairo_type1_subset_t *subset)
5246 cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
5247 cairo_pdf_font_t font;
5248 cairo_int_status_t status;
5249 unsigned long length;
5250 unsigned int i, last_glyph;
5253 _create_font_subset_tag (font_subset, subset->base_font, tag);
5255 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
5256 font_subset->font_id,
5257 font_subset->subset_id);
5258 if (subset_resource.id == 0)
5259 return CAIRO_STATUS_SUCCESS;
5261 length = subset->header_length + subset->data_length + subset->trailer_length;
5262 status = _cairo_pdf_surface_open_stream (surface,
5268 subset->header_length,
5269 subset->data_length,
5270 subset->trailer_length);
5271 if (unlikely (status))
5274 stream = surface->pdf_stream.self;
5275 _cairo_output_stream_write (surface->output, subset->data, length);
5276 status = _cairo_pdf_surface_close_stream (surface);
5277 if (unlikely (status))
5280 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
5282 &to_unicode_stream);
5283 if (_cairo_int_status_is_error (status))
5286 last_glyph = font_subset->num_glyphs - 1;
5287 if (font_subset->is_latin) {
5288 /* find last glyph used */
5289 for (i = 255; i >= 32; i--)
5290 if (font_subset->latin_to_subset_glyph_index[i] > 0)
5296 descriptor = _cairo_pdf_surface_new_object (surface);
5297 if (descriptor.id == 0)
5298 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5300 _cairo_output_stream_printf (surface->output,
5302 "<< /Type /FontDescriptor\n"
5303 " /FontName /%s+%s\n"
5305 " /FontBBox [ %ld %ld %ld %ld ]\n"
5312 " /FontFile %u 0 R\n"
5318 (long)(subset->x_min*PDF_UNITS_PER_EM),
5319 (long)(subset->y_min*PDF_UNITS_PER_EM),
5320 (long)(subset->x_max*PDF_UNITS_PER_EM),
5321 (long)(subset->y_max*PDF_UNITS_PER_EM),
5322 (long)(subset->ascent*PDF_UNITS_PER_EM),
5323 (long)(subset->descent*PDF_UNITS_PER_EM),
5324 (long)(subset->y_max*PDF_UNITS_PER_EM),
5327 _cairo_pdf_surface_update_object (surface, subset_resource);
5328 _cairo_output_stream_printf (surface->output,
5331 " /Subtype /Type1\n"
5332 " /BaseFont /%s+%s\n"
5335 " /FontDescriptor %d 0 R\n",
5339 font_subset->is_latin ? 32 : 0,
5343 if (font_subset->is_latin)
5344 _cairo_output_stream_printf (surface->output, " /Encoding /WinAnsiEncoding\n");
5346 _cairo_output_stream_printf (surface->output, " /Widths [");
5347 if (font_subset->is_latin) {
5348 for (i = 32; i < last_glyph + 1; i++) {
5349 int glyph = font_subset->latin_to_subset_glyph_index[i];
5351 _cairo_output_stream_printf (surface->output,
5353 (long)(subset->widths[glyph]*PDF_UNITS_PER_EM));
5355 _cairo_output_stream_printf (surface->output, " 0");
5359 for (i = 0; i < font_subset->num_glyphs; i++)
5360 _cairo_output_stream_printf (surface->output,
5362 (long)(subset->widths[i]*PDF_UNITS_PER_EM));
5365 _cairo_output_stream_printf (surface->output,
5368 if (to_unicode_stream.id != 0)
5369 _cairo_output_stream_printf (surface->output,
5370 " /ToUnicode %d 0 R\n",
5371 to_unicode_stream.id);
5373 _cairo_output_stream_printf (surface->output,
5377 font.font_id = font_subset->font_id;
5378 font.subset_id = font_subset->subset_id;
5379 font.subset_resource = subset_resource;
5380 return _cairo_array_append (&surface->fonts, &font);
5383 static cairo_int_status_t
5384 _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
5385 cairo_scaled_font_subset_t *font_subset)
5387 cairo_int_status_t status;
5388 cairo_type1_subset_t subset;
5391 /* 16-bit glyphs not compatible with Type 1 fonts */
5392 if (font_subset->is_composite && !font_subset->is_latin)
5393 return CAIRO_INT_STATUS_UNSUPPORTED;
5395 snprintf (name, sizeof name, "CairoFont-%d-%d",
5396 font_subset->font_id, font_subset->subset_id);
5397 status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE);
5398 if (unlikely (status))
5401 status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
5403 _cairo_type1_subset_fini (&subset);
5407 static cairo_int_status_t
5408 _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
5409 cairo_scaled_font_subset_t *font_subset)
5411 cairo_int_status_t status;
5412 cairo_type1_subset_t subset;
5415 /* 16-bit glyphs not compatible with Type 1 fonts */
5416 if (font_subset->is_composite && !font_subset->is_latin)
5417 return CAIRO_INT_STATUS_UNSUPPORTED;
5419 snprintf (name, sizeof name, "CairoFont-%d-%d",
5420 font_subset->font_id, font_subset->subset_id);
5421 status = _cairo_type1_fallback_init_binary (&subset, name, font_subset);
5422 if (unlikely (status))
5425 status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
5427 _cairo_type1_fallback_fini (&subset);
5431 static cairo_int_status_t
5432 _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
5433 cairo_scaled_font_subset_t *font_subset)
5435 cairo_pdf_resource_t stream, descriptor, cidfont_dict;
5436 cairo_pdf_resource_t subset_resource, to_unicode_stream;
5437 cairo_int_status_t status;
5438 cairo_pdf_font_t font;
5439 cairo_truetype_subset_t subset;
5440 unsigned int i, last_glyph;
5443 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
5444 font_subset->font_id,
5445 font_subset->subset_id);
5446 if (subset_resource.id == 0)
5447 return CAIRO_STATUS_SUCCESS;
5449 status = _cairo_truetype_subset_init_pdf (&subset, font_subset);
5450 if (unlikely (status))
5453 _create_font_subset_tag (font_subset, subset.ps_name, tag);
5455 status = _cairo_pdf_surface_open_stream (surface,
5459 subset.data_length);
5460 if (unlikely (status)) {
5461 _cairo_truetype_subset_fini (&subset);
5465 stream = surface->pdf_stream.self;
5466 _cairo_output_stream_write (surface->output,
5467 subset.data, subset.data_length);
5468 status = _cairo_pdf_surface_close_stream (surface);
5469 if (unlikely (status)) {
5470 _cairo_truetype_subset_fini (&subset);
5474 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
5476 &to_unicode_stream);
5477 if (_cairo_int_status_is_error (status)) {
5478 _cairo_truetype_subset_fini (&subset);
5482 descriptor = _cairo_pdf_surface_new_object (surface);
5483 if (descriptor.id == 0) {
5484 _cairo_truetype_subset_fini (&subset);
5485 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5488 _cairo_output_stream_printf (surface->output,
5490 "<< /Type /FontDescriptor\n"
5491 " /FontName /%s+%s\n",
5496 if (subset.family_name_utf8) {
5499 status = _utf8_to_pdf_string (subset.family_name_utf8, &pdf_str);
5500 if (unlikely (status)) {
5501 _cairo_truetype_subset_fini (&subset);
5505 _cairo_output_stream_printf (surface->output,
5506 " /FontFamily %s\n",
5511 _cairo_output_stream_printf (surface->output,
5513 " /FontBBox [ %ld %ld %ld %ld ]\n"
5520 " /FontFile2 %u 0 R\n"
5523 font_subset->is_latin ? 32 : 4,
5524 (long)(subset.x_min*PDF_UNITS_PER_EM),
5525 (long)(subset.y_min*PDF_UNITS_PER_EM),
5526 (long)(subset.x_max*PDF_UNITS_PER_EM),
5527 (long)(subset.y_max*PDF_UNITS_PER_EM),
5528 (long)(subset.ascent*PDF_UNITS_PER_EM),
5529 (long)(subset.descent*PDF_UNITS_PER_EM),
5530 (long)(subset.y_max*PDF_UNITS_PER_EM),
5533 if (font_subset->is_latin) {
5534 /* find last glyph used */
5535 for (i = 255; i >= 32; i--)
5536 if (font_subset->latin_to_subset_glyph_index[i] > 0)
5540 _cairo_pdf_surface_update_object (surface, subset_resource);
5541 _cairo_output_stream_printf (surface->output,
5544 " /Subtype /TrueType\n"
5545 " /BaseFont /%s+%s\n"
5548 " /FontDescriptor %d 0 R\n"
5549 " /Encoding /WinAnsiEncoding\n"
5557 for (i = 32; i < last_glyph + 1; i++) {
5558 int glyph = font_subset->latin_to_subset_glyph_index[i];
5560 _cairo_output_stream_printf (surface->output,
5562 (long)(subset.widths[glyph]*PDF_UNITS_PER_EM));
5564 _cairo_output_stream_printf (surface->output, " 0");
5568 _cairo_output_stream_printf (surface->output,
5571 if (to_unicode_stream.id != 0)
5572 _cairo_output_stream_printf (surface->output,
5573 " /ToUnicode %d 0 R\n",
5574 to_unicode_stream.id);
5576 _cairo_output_stream_printf (surface->output,
5580 cidfont_dict = _cairo_pdf_surface_new_object (surface);
5581 if (cidfont_dict.id == 0) {
5582 _cairo_truetype_subset_fini (&subset);
5583 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5586 _cairo_output_stream_printf (surface->output,
5589 " /Subtype /CIDFontType2\n"
5590 " /BaseFont /%s+%s\n"
5592 " << /Registry (Adobe)\n"
5593 " /Ordering (Identity)\n"
5596 " /FontDescriptor %d 0 R\n"
5603 for (i = 0; i < font_subset->num_glyphs; i++)
5604 _cairo_output_stream_printf (surface->output,
5606 (long)(subset.widths[i]*PDF_UNITS_PER_EM));
5608 _cairo_output_stream_printf (surface->output,
5613 _cairo_pdf_surface_update_object (surface, subset_resource);
5614 _cairo_output_stream_printf (surface->output,
5617 " /Subtype /Type0\n"
5618 " /BaseFont /%s+%s\n"
5619 " /Encoding /Identity-H\n"
5620 " /DescendantFonts [ %d 0 R]\n",
5626 if (to_unicode_stream.id != 0)
5627 _cairo_output_stream_printf (surface->output,
5628 " /ToUnicode %d 0 R\n",
5629 to_unicode_stream.id);
5631 _cairo_output_stream_printf (surface->output,
5636 font.font_id = font_subset->font_id;
5637 font.subset_id = font_subset->subset_id;
5638 font.subset_resource = subset_resource;
5639 status = _cairo_array_append (&surface->fonts, &font);
5641 _cairo_truetype_subset_fini (&subset);
5646 static cairo_int_status_t
5647 _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
5648 cairo_output_stream_t *stream)
5650 uint8_t *byte, output_byte;
5651 int row, col, num_cols;
5653 /* The only image type supported by Type 3 fonts are 1-bit image
5655 assert (image->format == CAIRO_FORMAT_A1);
5657 _cairo_output_stream_printf (stream,
5667 _cairo_output_stream_printf (stream,
5670 num_cols = (image->width + 7) / 8;
5671 for (row = 0; row < image->height; row++) {
5672 byte = image->data + row * image->stride;
5673 for (col = 0; col < num_cols; col++) {
5674 output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
5675 _cairo_output_stream_write (stream, &output_byte, 1);
5680 _cairo_output_stream_printf (stream,
5683 return _cairo_output_stream_get_status (stream);
5686 static cairo_int_status_t
5687 _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
5690 cairo_pdf_surface_t *surface = closure;
5691 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
5692 cairo_int_status_t status2;
5694 cairo_surface_t *type3_surface;
5695 cairo_output_stream_t *null_stream;
5697 null_stream = _cairo_null_stream_create ();
5698 type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
5700 _cairo_pdf_emit_imagemask,
5701 surface->font_subsets,
5703 if (unlikely (type3_surface->status)) {
5704 status2 = _cairo_output_stream_destroy (null_stream);
5705 status = type3_surface->status;
5706 cairo_surface_destroy (type3_surface);
5710 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
5711 _cairo_pdf_surface_add_font,
5714 for (i = 0; i < font_subset->num_glyphs; i++) {
5715 status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
5716 font_subset->glyphs[i]);
5717 if (unlikely (status))
5721 cairo_surface_destroy (type3_surface);
5722 status2 = _cairo_output_stream_destroy (null_stream);
5723 if (status == CAIRO_INT_STATUS_SUCCESS)
5729 static cairo_int_status_t
5730 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
5731 cairo_scaled_font_subset_t *font_subset)
5733 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
5734 cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
5735 cairo_pdf_font_t font;
5738 cairo_box_t font_bbox = {{0,0},{0,0}};
5739 cairo_box_t bbox = {{0,0},{0,0}};
5740 cairo_surface_t *type3_surface;
5742 if (font_subset->num_glyphs == 0)
5743 return CAIRO_STATUS_SUCCESS;
5745 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
5746 font_subset->font_id,
5747 font_subset->subset_id);
5748 if (subset_resource.id == 0)
5749 return CAIRO_STATUS_SUCCESS;
5751 glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
5752 if (unlikely (glyphs == NULL))
5753 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5755 widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
5756 if (unlikely (widths == NULL)) {
5758 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5761 _cairo_pdf_group_resources_clear (&surface->resources);
5762 type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
5764 _cairo_pdf_emit_imagemask,
5765 surface->font_subsets,
5767 if (unlikely (type3_surface->status)) {
5770 status = type3_surface->status;
5771 cairo_surface_destroy (type3_surface);
5775 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
5776 _cairo_pdf_surface_add_font,
5779 for (i = 0; i < font_subset->num_glyphs; i++) {
5780 status = _cairo_pdf_surface_open_stream (surface,
5782 surface->compress_content,
5784 if (unlikely (status))
5787 glyphs[i] = surface->pdf_stream.self;
5788 status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
5790 font_subset->glyphs[i],
5793 if (unlikely (status))
5796 status = _cairo_pdf_surface_close_stream (surface);
5797 if (unlikely (status))
5801 font_bbox.p1.x = bbox.p1.x;
5802 font_bbox.p1.y = bbox.p1.y;
5803 font_bbox.p2.x = bbox.p2.x;
5804 font_bbox.p2.y = bbox.p2.y;
5806 if (bbox.p1.x < font_bbox.p1.x)
5807 font_bbox.p1.x = bbox.p1.x;
5808 if (bbox.p1.y < font_bbox.p1.y)
5809 font_bbox.p1.y = bbox.p1.y;
5810 if (bbox.p2.x > font_bbox.p2.x)
5811 font_bbox.p2.x = bbox.p2.x;
5812 if (bbox.p2.y > font_bbox.p2.y)
5813 font_bbox.p2.y = bbox.p2.y;
5816 cairo_surface_destroy (type3_surface);
5817 if (unlikely (status)) {
5823 encoding = _cairo_pdf_surface_new_object (surface);
5824 if (encoding.id == 0) {
5827 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5830 _cairo_output_stream_printf (surface->output,
5832 "<< /Type /Encoding\n"
5833 " /Differences [0", encoding.id);
5834 for (i = 0; i < font_subset->num_glyphs; i++)
5835 _cairo_output_stream_printf (surface->output,
5837 _cairo_output_stream_printf (surface->output,
5842 char_procs = _cairo_pdf_surface_new_object (surface);
5843 if (char_procs.id == 0) {
5846 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5849 _cairo_output_stream_printf (surface->output,
5851 "<<\n", char_procs.id);
5852 for (i = 0; i < font_subset->num_glyphs; i++)
5853 _cairo_output_stream_printf (surface->output,
5856 _cairo_output_stream_printf (surface->output,
5862 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
5864 &to_unicode_stream);
5865 if (_cairo_int_status_is_error (status)) {
5870 _cairo_pdf_surface_update_object (surface, subset_resource);
5871 _cairo_output_stream_printf (surface->output,
5874 " /Subtype /Type3\n"
5875 " /FontBBox [%f %f %f %f]\n"
5876 " /FontMatrix [ 1 0 0 1 0 0 ]\n"
5877 " /Encoding %d 0 R\n"
5878 " /CharProcs %d 0 R\n"
5882 _cairo_fixed_to_double (font_bbox.p1.x),
5883 - _cairo_fixed_to_double (font_bbox.p2.y),
5884 _cairo_fixed_to_double (font_bbox.p2.x),
5885 - _cairo_fixed_to_double (font_bbox.p1.y),
5888 font_subset->num_glyphs - 1);
5890 _cairo_output_stream_printf (surface->output,
5892 for (i = 0; i < font_subset->num_glyphs; i++)
5893 _cairo_output_stream_printf (surface->output, " %f", widths[i]);
5894 _cairo_output_stream_printf (surface->output,
5898 _cairo_output_stream_printf (surface->output,
5900 _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
5902 if (to_unicode_stream.id != 0)
5903 _cairo_output_stream_printf (surface->output,
5904 " /ToUnicode %d 0 R\n",
5905 to_unicode_stream.id);
5907 _cairo_output_stream_printf (surface->output,
5911 font.font_id = font_subset->font_id;
5912 font.subset_id = font_subset->subset_id;
5913 font.subset_resource = subset_resource;
5914 return _cairo_array_append (&surface->fonts, &font);
5917 static cairo_int_status_t
5918 _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
5921 cairo_pdf_surface_t *surface = closure;
5922 cairo_int_status_t status;
5924 status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
5925 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5928 status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
5929 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5932 status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
5933 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5936 status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
5937 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5940 status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
5941 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5945 return CAIRO_INT_STATUS_SUCCESS;
5948 static cairo_int_status_t
5949 _cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
5952 cairo_pdf_surface_t *surface = closure;
5953 cairo_int_status_t status;
5955 status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
5956 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5960 return CAIRO_INT_STATUS_SUCCESS;
5963 static cairo_int_status_t
5964 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
5966 cairo_int_status_t status;
5968 status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
5969 _cairo_pdf_surface_analyze_user_font_subset,
5971 if (unlikely (status))
5974 status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
5975 _cairo_pdf_surface_emit_unscaled_font_subset,
5977 if (unlikely (status))
5980 status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
5981 _cairo_pdf_surface_emit_scaled_font_subset,
5983 if (unlikely (status))
5986 status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
5987 _cairo_pdf_surface_emit_scaled_font_subset,
5991 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
5992 surface->font_subsets = NULL;
5997 static cairo_pdf_resource_t
5998 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface)
6000 cairo_pdf_resource_t catalog;
6002 catalog = _cairo_pdf_surface_new_object (surface);
6003 if (catalog.id == 0)
6006 _cairo_output_stream_printf (surface->output,
6008 "<< /Type /Catalog\n"
6013 surface->pages_resource.id);
6019 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
6021 cairo_pdf_object_t *object;
6026 num_objects = _cairo_array_num_elements (&surface->objects);
6028 offset = _cairo_output_stream_get_position (surface->output);
6029 _cairo_output_stream_printf (surface->output,
6032 0, num_objects + 1);
6034 _cairo_output_stream_printf (surface->output,
6035 "0000000000 65535 f \n");
6036 for (i = 0; i < num_objects; i++) {
6037 object = _cairo_array_index (&surface->objects, i);
6040 snprintf (buffer, sizeof buffer, "%010ld", object->offset);
6041 _cairo_output_stream_printf (surface->output,
6042 "%s 00000 n \n", buffer);
6048 static cairo_int_status_t
6049 _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
6050 cairo_pdf_smask_group_t *group)
6052 cairo_pdf_resource_t mask_group;
6053 cairo_pdf_resource_t smask;
6054 cairo_pdf_smask_group_t *smask_group;
6055 cairo_pdf_resource_t pattern_res, gstate_res;
6056 cairo_int_status_t status;
6057 cairo_box_double_t bbox;
6059 /* Create mask group */
6060 _get_bbox_from_extents (group->height, &group->extents, &bbox);
6061 status = _cairo_pdf_surface_open_group (surface, &bbox, NULL);
6062 if (unlikely (status))
6065 if (_can_paint_pattern (group->mask)) {
6066 _cairo_output_stream_printf (surface->output, "q\n");
6067 status = _cairo_pdf_surface_paint_pattern (surface,
6068 CAIRO_OPERATOR_OVER,
6072 if (unlikely (status))
6075 _cairo_output_stream_printf (surface->output, "Q\n");
6079 status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask,
6080 CAIRO_OPERATOR_OVER,
6082 &pattern_res, &gstate_res);
6083 if (unlikely (status))
6086 if (gstate_res.id != 0) {
6087 smask_group = _cairo_pdf_surface_create_smask_group (surface, &group->extents);
6088 if (unlikely (smask_group == NULL))
6089 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6091 smask_group->width = group->width;
6092 smask_group->height = group->height;
6093 smask_group->operation = PDF_PAINT;
6094 smask_group->source = cairo_pattern_reference (group->mask);
6095 smask_group->source_res = pattern_res;
6096 status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
6097 if (unlikely (status)) {
6098 _cairo_pdf_smask_group_destroy (smask_group);
6102 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
6103 if (unlikely (status))
6106 status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
6107 if (unlikely (status))
6110 _cairo_output_stream_printf (surface->output,
6111 "q /s%d gs /x%d Do Q\n",
6113 smask_group->group_res.id);
6115 status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE);
6116 if (unlikely (status))
6119 _cairo_output_stream_printf (surface->output,
6120 "%f %f %f %f re f\n",
6123 bbox.p2.x - bbox.p1.x,
6124 bbox.p2.y - bbox.p1.y);
6126 status = _cairo_pdf_surface_unselect_pattern (surface);
6127 if (unlikely (status))
6132 status = _cairo_pdf_surface_close_group (surface, &mask_group);
6133 if (unlikely (status))
6136 /* Create source group */
6137 status = _cairo_pdf_surface_open_group (surface, &bbox, &group->source_res);
6138 if (unlikely (status))
6141 if (_can_paint_pattern (group->source)) {
6142 _cairo_output_stream_printf (surface->output, "q\n");
6143 status = _cairo_pdf_surface_paint_pattern (surface,
6144 CAIRO_OPERATOR_OVER,
6148 if (unlikely (status))
6151 _cairo_output_stream_printf (surface->output, "Q\n");
6155 status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source,
6156 CAIRO_OPERATOR_OVER,
6158 &pattern_res, &gstate_res);
6159 if (unlikely (status))
6162 if (gstate_res.id != 0) {
6163 smask_group = _cairo_pdf_surface_create_smask_group (surface, &group->extents);
6164 if (unlikely (smask_group == NULL))
6165 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6167 smask_group->operation = PDF_PAINT;
6168 smask_group->source = cairo_pattern_reference (group->source);
6169 smask_group->source_res = pattern_res;
6170 status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
6171 if (unlikely (status)) {
6172 _cairo_pdf_smask_group_destroy (smask_group);
6176 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
6177 if (unlikely (status))
6180 status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
6181 if (unlikely (status))
6184 _cairo_output_stream_printf (surface->output,
6185 "q /s%d gs /x%d Do Q\n",
6187 smask_group->group_res.id);
6189 status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE);
6190 if (unlikely (status))
6193 _cairo_output_stream_printf (surface->output,
6194 "%f %f %f %f re f\n",
6197 bbox.p2.x - bbox.p1.x,
6198 bbox.p2.y - bbox.p1.y);
6200 status = _cairo_pdf_surface_unselect_pattern (surface);
6201 if (unlikely (status))
6206 status = _cairo_pdf_surface_close_group (surface, NULL);
6207 if (unlikely (status))
6210 /* Create an smask based on the alpha component of mask_group */
6211 smask = _cairo_pdf_surface_new_object (surface);
6213 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6215 _cairo_output_stream_printf (surface->output,
6225 /* Create a GState that uses the smask */
6226 _cairo_pdf_surface_update_object (surface, group->group_res);
6227 _cairo_output_stream_printf (surface->output,
6229 "<< /Type /ExtGState\n"
6236 group->group_res.id,
6239 return _cairo_output_stream_get_status (surface->output);
6242 static cairo_int_status_t
6243 _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
6244 cairo_pdf_smask_group_t *group)
6246 double old_width, old_height;
6247 cairo_int_status_t status;
6248 cairo_box_double_t bbox;
6250 old_width = surface->width;
6251 old_height = surface->height;
6252 _cairo_pdf_surface_set_size_internal (surface,
6255 /* _mask is a special case that requires two groups - source
6256 * and mask as well as a smask and gstate dictionary */
6257 if (group->operation == PDF_MASK) {
6258 status = _cairo_pdf_surface_write_mask_group (surface, group);
6262 _get_bbox_from_extents (group->height, &group->extents, &bbox);
6263 status = _cairo_pdf_surface_open_group (surface, &bbox, &group->group_res);
6264 if (unlikely (status))
6267 status = _cairo_pdf_surface_select_pattern (surface,
6270 group->operation == PDF_STROKE);
6271 if (unlikely (status))
6274 switch (group->operation) {
6276 _cairo_output_stream_printf (surface->output,
6278 surface->width, surface->height);
6284 status = _cairo_pdf_operators_fill (&surface->pdf_operators,
6289 status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
6293 &group->ctm_inverse);
6295 case PDF_SHOW_GLYPHS:
6296 status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
6297 group->utf8, group->utf8_len,
6298 group->glyphs, group->num_glyphs,
6299 group->clusters, group->num_clusters,
6300 group->cluster_flags,
6301 group->scaled_font);
6304 if (unlikely (status))
6307 status = _cairo_pdf_surface_unselect_pattern (surface);
6308 if (unlikely (status))
6311 status = _cairo_pdf_surface_close_group (surface, NULL);
6314 _cairo_pdf_surface_set_size_internal (surface,
6321 static cairo_int_status_t
6322 _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface)
6324 cairo_pdf_pattern_t pattern;
6325 cairo_pdf_smask_group_t *group;
6326 cairo_pdf_source_surface_t src_surface;
6327 unsigned int pattern_index, group_index, surface_index;
6328 cairo_int_status_t status;
6330 /* Writing out PDF_MASK groups will cause additional smask groups
6331 * to be appended to surface->smask_groups. Additional patterns
6332 * may also be appended to surface->patterns.
6334 * Writing recording surface patterns will cause additional patterns
6335 * and groups to be appended.
6340 while ((pattern_index < _cairo_array_num_elements (&surface->page_patterns)) ||
6341 (group_index < _cairo_array_num_elements (&surface->smask_groups)) ||
6342 (surface_index < _cairo_array_num_elements (&surface->page_surfaces)))
6344 for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) {
6345 _cairo_array_copy_element (&surface->smask_groups, group_index, &group);
6346 status = _cairo_pdf_surface_write_smask_group (surface, group);
6347 if (unlikely (status))
6351 for (; pattern_index < _cairo_array_num_elements (&surface->page_patterns); pattern_index++) {
6352 _cairo_array_copy_element (&surface->page_patterns, pattern_index, &pattern);
6353 status = _cairo_pdf_surface_emit_pattern (surface, &pattern);
6354 if (unlikely (status))
6358 for (; surface_index < _cairo_array_num_elements (&surface->page_surfaces); surface_index++) {
6359 _cairo_array_copy_element (&surface->page_surfaces, surface_index, &src_surface);
6360 status = _cairo_pdf_surface_emit_surface (surface, &src_surface);
6361 if (unlikely (status))
6366 return CAIRO_STATUS_SUCCESS;
6369 static cairo_int_status_t
6370 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
6372 cairo_pdf_resource_t page, knockout, res;
6373 cairo_int_status_t status;
6374 unsigned int i, len;
6376 _cairo_pdf_group_resources_clear (&surface->resources);
6377 if (surface->has_fallback_images) {
6378 cairo_rectangle_int_t extents;
6379 cairo_box_double_t bbox;
6383 extents.width = ceil (surface->width);
6384 extents.height = ceil (surface->height);
6385 _get_bbox_from_extents (surface->height, &extents, &bbox);
6386 status = _cairo_pdf_surface_open_knockout_group (surface, &bbox);
6387 if (unlikely (status))
6390 len = _cairo_array_num_elements (&surface->knockout_group);
6391 for (i = 0; i < len; i++) {
6392 _cairo_array_copy_element (&surface->knockout_group, i, &res);
6393 _cairo_output_stream_printf (surface->output,
6396 status = _cairo_pdf_surface_add_xobject (surface, res);
6397 if (unlikely (status))
6400 _cairo_output_stream_printf (surface->output,
6402 surface->content.id);
6403 status = _cairo_pdf_surface_add_xobject (surface, surface->content);
6404 if (unlikely (status))
6407 status = _cairo_pdf_surface_close_group (surface, &knockout);
6408 if (unlikely (status))
6411 _cairo_pdf_group_resources_clear (&surface->resources);
6412 status = _cairo_pdf_surface_open_content_stream (surface, NULL, NULL, FALSE, FALSE);
6413 if (unlikely (status))
6416 _cairo_output_stream_printf (surface->output,
6419 status = _cairo_pdf_surface_add_xobject (surface, knockout);
6420 if (unlikely (status))
6423 status = _cairo_pdf_surface_close_content_stream (surface);
6424 if (unlikely (status))
6428 page = _cairo_pdf_surface_new_object (surface);
6430 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6432 _cairo_output_stream_printf (surface->output,
6436 " /MediaBox [ 0 0 %f %f ]\n"
6437 " /Contents %d 0 R\n"
6440 " /S /Transparency\n"
6444 " /Resources %d 0 R\n"
6448 surface->pages_resource.id,
6451 surface->content.id,
6452 surface->content_resources.id);
6454 status = _cairo_array_append (&surface->pages, &page);
6455 if (unlikely (status))
6458 status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface);
6459 if (unlikely (status))
6462 return CAIRO_STATUS_SUCCESS;
6465 static cairo_int_status_t
6466 _cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t *surface,
6467 cairo_surface_pattern_t *pattern)
6469 cairo_image_surface_t *image;
6471 cairo_int_status_t status;
6472 cairo_image_transparency_t transparency;
6474 status = _cairo_surface_acquire_source_image (pattern->surface,
6477 if (unlikely (status))
6480 if (image->base.status)
6481 return image->base.status;
6483 transparency = _cairo_image_analyze_transparency (image);
6484 if (transparency == CAIRO_IMAGE_IS_OPAQUE)
6485 status = CAIRO_STATUS_SUCCESS;
6487 status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
6489 _cairo_surface_release_source_image (pattern->surface, image, image_extra);
6495 _surface_pattern_supported (cairo_surface_pattern_t *pattern)
6497 cairo_extend_t extend;
6499 if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
6502 if (pattern->surface->backend->acquire_source_image == NULL)
6505 /* Does an ALPHA-only source surface even make sense? Maybe, but I
6506 * don't think it's worth the extra code to support it. */
6508 /* XXX: Need to write this function here...
6509 if (pattern->surface->content == CAIRO_CONTENT_ALPHA)
6513 extend = cairo_pattern_get_extend (&pattern->base);
6515 case CAIRO_EXTEND_NONE:
6516 case CAIRO_EXTEND_REPEAT:
6517 case CAIRO_EXTEND_REFLECT:
6518 /* There's no point returning FALSE for EXTEND_PAD, as the image
6519 * surface does not currently implement it either */
6520 case CAIRO_EXTEND_PAD:
6529 _pattern_supported (const cairo_pattern_t *pattern)
6531 switch (pattern->type) {
6532 case CAIRO_PATTERN_TYPE_SOLID:
6533 case CAIRO_PATTERN_TYPE_LINEAR:
6534 case CAIRO_PATTERN_TYPE_RADIAL:
6535 case CAIRO_PATTERN_TYPE_MESH:
6536 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
6539 case CAIRO_PATTERN_TYPE_SURFACE:
6540 return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
6549 _pdf_operator_supported (cairo_operator_t op)
6552 case CAIRO_OPERATOR_OVER:
6553 case CAIRO_OPERATOR_MULTIPLY:
6554 case CAIRO_OPERATOR_SCREEN:
6555 case CAIRO_OPERATOR_OVERLAY:
6556 case CAIRO_OPERATOR_DARKEN:
6557 case CAIRO_OPERATOR_LIGHTEN:
6558 case CAIRO_OPERATOR_COLOR_DODGE:
6559 case CAIRO_OPERATOR_COLOR_BURN:
6560 case CAIRO_OPERATOR_HARD_LIGHT:
6561 case CAIRO_OPERATOR_SOFT_LIGHT:
6562 case CAIRO_OPERATOR_DIFFERENCE:
6563 case CAIRO_OPERATOR_EXCLUSION:
6564 case CAIRO_OPERATOR_HSL_HUE:
6565 case CAIRO_OPERATOR_HSL_SATURATION:
6566 case CAIRO_OPERATOR_HSL_COLOR:
6567 case CAIRO_OPERATOR_HSL_LUMINOSITY:
6571 case CAIRO_OPERATOR_CLEAR:
6572 case CAIRO_OPERATOR_SOURCE:
6573 case CAIRO_OPERATOR_IN:
6574 case CAIRO_OPERATOR_OUT:
6575 case CAIRO_OPERATOR_ATOP:
6576 case CAIRO_OPERATOR_DEST:
6577 case CAIRO_OPERATOR_DEST_OVER:
6578 case CAIRO_OPERATOR_DEST_IN:
6579 case CAIRO_OPERATOR_DEST_OUT:
6580 case CAIRO_OPERATOR_DEST_ATOP:
6581 case CAIRO_OPERATOR_XOR:
6582 case CAIRO_OPERATOR_ADD:
6583 case CAIRO_OPERATOR_SATURATE:
6588 static cairo_int_status_t
6589 _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
6590 cairo_operator_t op,
6591 const cairo_pattern_t *pattern,
6592 const cairo_rectangle_int_t *extents)
6594 if (surface->force_fallbacks &&
6595 surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
6597 return CAIRO_INT_STATUS_UNSUPPORTED;
6600 if (! _pattern_supported (pattern))
6601 return CAIRO_INT_STATUS_UNSUPPORTED;
6603 if (_pdf_operator_supported (op)) {
6604 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
6605 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
6607 if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
6608 if (pattern->extend == CAIRO_EXTEND_PAD) {
6610 cairo_rectangle_int_t rect;
6611 cairo_rectangle_int_t rec_extents;
6613 /* get the operation extents in pattern space */
6614 _cairo_box_from_rectangle (&box, extents);
6615 _cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &box, NULL);
6616 _cairo_box_round_to_rectangle (&box, &rect);
6618 /* Check if surface needs padding to fill extents */
6619 if (_cairo_surface_get_extents (surface_pattern->surface, &rec_extents)) {
6620 if (_cairo_fixed_integer_ceil(box.p1.x) < rec_extents.x ||
6621 _cairo_fixed_integer_ceil(box.p1.y) < rec_extents.y ||
6622 _cairo_fixed_integer_floor(box.p2.y) > rec_extents.x + rec_extents.width ||
6623 _cairo_fixed_integer_floor(box.p2.y) > rec_extents.y + rec_extents.height)
6625 return CAIRO_INT_STATUS_UNSUPPORTED;
6629 return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
6633 return CAIRO_STATUS_SUCCESS;
6637 /* The SOURCE operator is supported if the pattern is opaque or if
6638 * there is nothing painted underneath. */
6639 if (op == CAIRO_OPERATOR_SOURCE) {
6640 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
6641 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
6643 if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
6644 if (_cairo_pattern_is_opaque (pattern, extents)) {
6645 return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
6647 /* FIXME: The analysis surface does not yet have
6648 * the capability to analyze a non opaque recording
6649 * surface and mark it supported if there is
6650 * nothing underneath. For now recording surfaces of
6651 * type CONTENT_COLOR_ALPHA painted with
6652 * OPERATOR_SOURCE will result in a fallback
6655 return CAIRO_INT_STATUS_UNSUPPORTED;
6658 return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
6663 if (_cairo_pattern_is_opaque (pattern, extents))
6664 return CAIRO_STATUS_SUCCESS;
6666 return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
6669 return CAIRO_INT_STATUS_UNSUPPORTED;
6673 _cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
6674 cairo_operator_t op,
6675 const cairo_pattern_t *pattern,
6676 const cairo_rectangle_int_t *extents)
6678 return _cairo_pdf_surface_analyze_operation (surface, op, pattern, extents) != CAIRO_INT_STATUS_UNSUPPORTED;
6681 static cairo_int_status_t
6682 _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
6684 cairo_box_double_t bbox;
6685 cairo_int_status_t status;
6687 status = _cairo_pdf_surface_close_content_stream (surface);
6688 if (unlikely (status))
6691 status = _cairo_array_append (&surface->knockout_group, &surface->content);
6692 if (unlikely (status))
6695 _cairo_pdf_group_resources_clear (&surface->resources);
6698 bbox.p2.x = surface->width;
6699 bbox.p2.y = surface->height;
6700 return _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, TRUE, TRUE);
6703 /* If source is an opaque image and mask is an image and both images
6704 * have the same bounding box we can emit them as a image/smask pair.
6706 static cairo_int_status_t
6707 _cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface,
6708 cairo_operator_t op,
6709 const cairo_pattern_t *source,
6710 const cairo_pattern_t *mask,
6711 const cairo_rectangle_int_t *extents)
6713 cairo_int_status_t status;
6714 cairo_image_surface_t *image;
6716 cairo_image_transparency_t transparency;
6717 cairo_pdf_resource_t smask_res;
6718 int src_width, src_height;
6719 int mask_width, mask_height;
6720 double src_x_offset, src_y_offset;
6721 double mask_x_offset, mask_y_offset;
6722 double src_x1, src_y1, src_x2, src_y2;
6723 double mask_x1, mask_y1, mask_x2, mask_y2;
6725 double src_radius, mask_radius, e;
6726 cairo_rectangle_int_t extents2;
6727 cairo_bool_t need_smask;
6729 /* Check that source and mask are images */
6731 if (!((source->type == CAIRO_PATTERN_TYPE_SURFACE || source->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) &&
6732 (mask->type == CAIRO_PATTERN_TYPE_SURFACE || mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)))
6733 return CAIRO_INT_STATUS_UNSUPPORTED;
6735 if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
6736 ((cairo_surface_pattern_t *) source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
6738 return CAIRO_INT_STATUS_UNSUPPORTED;
6741 if (mask->type == CAIRO_PATTERN_TYPE_SURFACE &&
6742 ((cairo_surface_pattern_t *) mask)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
6744 return CAIRO_INT_STATUS_UNSUPPORTED;
6747 if (source->extend != CAIRO_EXTEND_NONE || mask->extend != CAIRO_EXTEND_NONE)
6748 return CAIRO_INT_STATUS_UNSUPPORTED;
6750 /* Check that source is opaque and get image sizes */
6752 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source,
6753 &image, &image_extra);
6754 if (unlikely (status))
6757 if (image->base.status)
6758 return image->base.status;
6760 src_width = image->width;
6761 src_height = image->height;
6762 if (source->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
6763 cairo_surface_get_device_offset (&image->base, &src_x_offset, &src_y_offset);
6769 transparency = _cairo_image_analyze_transparency (image);
6770 _cairo_pdf_surface_release_source_image_from_pattern (surface, source, image, image_extra);
6772 if (transparency != CAIRO_IMAGE_IS_OPAQUE)
6773 return CAIRO_INT_STATUS_UNSUPPORTED;
6775 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, mask,
6776 &image, &image_extra);
6777 if (unlikely (status))
6780 if (image->base.status)
6781 return image->base.status;
6783 mask_width = image->width;
6784 mask_height = image->height;
6785 if (mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
6786 cairo_surface_get_device_offset (&image->base, &mask_x_offset, &mask_y_offset);
6792 transparency = _cairo_image_analyze_transparency (image);
6793 need_smask = transparency != CAIRO_IMAGE_IS_OPAQUE;
6795 _cairo_pdf_surface_release_source_image_from_pattern (surface, mask, image, image_extra);
6797 /* Check that both images have the same extents with a tolerance
6798 * of half the smallest source pixel. */
6800 p2u = source->matrix;
6801 status = cairo_matrix_invert (&p2u);
6802 /* cairo_pattern_set_matrix ensures the matrix is invertible */
6803 assert (status == CAIRO_INT_STATUS_SUCCESS);
6807 src_y2 = src_height;
6808 cairo_matrix_transform_point (&p2u, &src_x1, &src_y1);
6809 cairo_matrix_transform_point (&p2u, &src_x2, &src_y2);
6810 src_radius = _cairo_matrix_transformed_circle_major_axis (&p2u, 0.5);
6813 status = cairo_matrix_invert (&p2u);
6814 /* cairo_pattern_set_matrix ensures the matrix is invertible */
6815 assert (status == CAIRO_INT_STATUS_SUCCESS);
6818 mask_x2 = mask_width;
6819 mask_y2 = mask_height;
6820 cairo_matrix_transform_point (&p2u, &mask_x1, &mask_y1);
6821 cairo_matrix_transform_point (&p2u, &mask_x2, &mask_y2);
6822 mask_radius = _cairo_matrix_transformed_circle_major_axis (&p2u, 0.5);
6824 if (src_radius < mask_radius)
6829 if (fabs(src_x1 - mask_x1) > e ||
6830 fabs(src_x2 - mask_x2) > e ||
6831 fabs(src_y1 - mask_y1) > e ||
6832 fabs(src_y2 - mask_y2) > e)
6833 return CAIRO_INT_STATUS_UNSUPPORTED;
6835 /* Check both images have same device offset */
6836 if (fabs(src_x_offset - mask_x_offset) > e ||
6837 fabs(src_y_offset - mask_y_offset) > e)
6838 return CAIRO_INT_STATUS_UNSUPPORTED;
6841 status = _cairo_pdf_surface_add_source_surface (surface,
6856 if (unlikely (status))
6860 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6861 if (unlikely (status))
6864 _cairo_output_stream_printf (surface->output, "q\n");
6865 status = _cairo_pdf_surface_paint_surface_pattern (surface, op, source, extents,
6866 need_smask ? &smask_res : NULL,
6868 if (unlikely (status))
6871 _cairo_output_stream_printf (surface->output, "Q\n");
6873 status = _cairo_output_stream_get_status (surface->output);
6879 /* A PDF stencil mask is an A1 mask used with the current color */
6880 static cairo_int_status_t
6881 _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface,
6882 cairo_operator_t op,
6883 const cairo_pattern_t *source,
6884 const cairo_pattern_t *mask,
6885 const cairo_rectangle_int_t *extents)
6887 cairo_int_status_t status;
6888 cairo_image_surface_t *image;
6890 cairo_image_transparency_t transparency;
6891 cairo_pdf_resource_t pattern_res = {0};
6893 if (! (source->type == CAIRO_PATTERN_TYPE_SOLID &&
6894 (mask->type == CAIRO_PATTERN_TYPE_SURFACE || mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)))
6895 return CAIRO_INT_STATUS_UNSUPPORTED;
6897 if (mask->type == CAIRO_PATTERN_TYPE_SURFACE &&
6898 ((cairo_surface_pattern_t *) mask)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
6900 return CAIRO_INT_STATUS_UNSUPPORTED;
6903 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, mask,
6904 &image, &image_extra);
6905 if (unlikely (status))
6908 if (image->base.status)
6909 return image->base.status;
6911 transparency = _cairo_image_analyze_transparency (image);
6912 if (transparency != CAIRO_IMAGE_IS_OPAQUE &&
6913 transparency != CAIRO_IMAGE_HAS_BILEVEL_ALPHA)
6915 status = CAIRO_INT_STATUS_UNSUPPORTED;
6919 status = _cairo_pdf_surface_select_pattern (surface, source,
6920 pattern_res, FALSE);
6921 if (unlikely (status))
6924 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6925 if (unlikely (status))
6928 _cairo_output_stream_printf (surface->output, "q\n");
6929 status = _cairo_pdf_surface_paint_surface_pattern (surface, op, mask, extents, NULL, TRUE);
6930 if (unlikely (status))
6933 _cairo_output_stream_printf (surface->output, "Q\n");
6935 status = _cairo_output_stream_get_status (surface->output);
6938 _cairo_pdf_surface_release_source_image_from_pattern (surface, mask, image, image_extra);
6943 static cairo_int_status_t
6944 _cairo_pdf_surface_set_clip (cairo_pdf_surface_t *surface,
6945 cairo_composite_rectangles_t *composite)
6947 cairo_clip_t *clip = composite->clip;
6949 if (_cairo_composite_rectangles_can_reduce_clip (composite, clip))
6953 if (_cairo_composite_rectangles_can_reduce_clip (composite,
6954 surface->clipper.clip))
6955 return CAIRO_STATUS_SUCCESS;
6958 return _cairo_surface_clipper_set_clip (&surface->clipper, clip);
6961 static cairo_int_status_t
6962 _cairo_pdf_surface_paint (void *abstract_surface,
6963 cairo_operator_t op,
6964 const cairo_pattern_t *source,
6965 const cairo_clip_t *clip)
6967 cairo_pdf_surface_t *surface = abstract_surface;
6968 cairo_pdf_smask_group_t *group;
6969 cairo_pdf_resource_t pattern_res, gstate_res;
6970 cairo_composite_rectangles_t extents;
6971 cairo_int_status_t status;
6973 status = _cairo_composite_rectangles_init_for_paint (&extents,
6976 if (unlikely (status))
6979 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
6980 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
6982 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
6983 status = _cairo_pdf_surface_start_fallback (surface);
6984 if (unlikely (status))
6988 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
6990 status = _cairo_pdf_surface_set_clip (surface, &extents);
6991 if (unlikely (status))
6994 status = _cairo_pdf_surface_select_operator (surface, op);
6995 if (unlikely (status))
6998 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6999 if (unlikely (status))
7002 if (_can_paint_pattern (source)) {
7003 _cairo_output_stream_printf (surface->output, "q\n");
7004 status = _cairo_pdf_surface_paint_pattern (surface,
7009 if (unlikely (status))
7012 _cairo_output_stream_printf (surface->output, "Q\n");
7013 _cairo_composite_rectangles_fini (&extents);
7014 return _cairo_output_stream_get_status (surface->output);
7019 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
7021 &pattern_res, &gstate_res);
7022 if (unlikely (status))
7025 if (gstate_res.id != 0) {
7026 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
7027 if (unlikely (group == NULL)) {
7028 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7032 group->operation = PDF_PAINT;
7033 status = _cairo_pattern_create_copy (&group->source, source);
7034 if (unlikely (status)) {
7035 _cairo_pdf_smask_group_destroy (group);
7038 group->source_res = pattern_res;
7039 status = _cairo_pdf_surface_add_smask_group (surface, group);
7040 if (unlikely (status)) {
7041 _cairo_pdf_smask_group_destroy (group);
7045 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
7046 if (unlikely (status))
7049 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
7050 if (unlikely (status))
7053 _cairo_output_stream_printf (surface->output,
7054 "q /s%d gs /x%d Do Q\n",
7056 group->group_res.id);
7058 status = _cairo_pdf_surface_select_pattern (surface, source,
7059 pattern_res, FALSE);
7060 if (unlikely (status))
7063 _cairo_output_stream_printf (surface->output,
7065 surface->width, surface->height);
7067 status = _cairo_pdf_surface_unselect_pattern (surface);
7068 if (unlikely (status))
7072 _cairo_composite_rectangles_fini (&extents);
7073 return _cairo_output_stream_get_status (surface->output);
7076 _cairo_composite_rectangles_fini (&extents);
7080 static cairo_int_status_t
7081 _cairo_pdf_surface_mask (void *abstract_surface,
7082 cairo_operator_t op,
7083 const cairo_pattern_t *source,
7084 const cairo_pattern_t *mask,
7085 const cairo_clip_t *clip)
7087 cairo_pdf_surface_t *surface = abstract_surface;
7088 cairo_pdf_smask_group_t *group;
7089 cairo_composite_rectangles_t extents;
7090 cairo_int_status_t status;
7091 cairo_rectangle_int_t r;
7094 status = _cairo_composite_rectangles_init_for_mask (&extents,
7096 op, source, mask, clip);
7097 if (unlikely (status))
7100 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
7101 cairo_int_status_t source_status, mask_status;
7103 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
7104 if (_cairo_int_status_is_error (status))
7106 source_status = status;
7108 if (mask->has_component_alpha) {
7109 status = CAIRO_INT_STATUS_UNSUPPORTED;
7111 status = _cairo_pdf_surface_analyze_operation (surface, op, mask, &extents.bounded);
7112 if (_cairo_int_status_is_error (status))
7115 mask_status = status;
7117 _cairo_composite_rectangles_fini (&extents);
7118 return _cairo_analysis_surface_merge_status (source_status,
7120 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
7121 status = _cairo_pdf_surface_start_fallback (surface);
7122 if (unlikely (status))
7126 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
7127 assert (_cairo_pdf_surface_operation_supported (surface, op, mask, &extents.bounded));
7129 /* get the accurate extents */
7130 status = _cairo_pattern_get_ink_extents (source, &r);
7131 if (unlikely (status))
7134 /* XXX slight impedance mismatch */
7135 _cairo_box_from_rectangle (&box, &r);
7136 status = _cairo_composite_rectangles_intersect_source_extents (&extents,
7138 if (unlikely (status))
7141 status = _cairo_pattern_get_ink_extents (mask, &r);
7142 if (unlikely (status))
7145 _cairo_box_from_rectangle (&box, &r);
7146 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
7148 if (unlikely (status))
7151 status = _cairo_pdf_surface_set_clip (surface, &extents);
7152 if (unlikely (status))
7155 status = _cairo_pdf_surface_select_operator (surface, op);
7156 if (unlikely (status))
7159 /* Check if we can combine source and mask into a smask image */
7160 status = _cairo_pdf_surface_emit_combined_smask (surface, op, source, mask, &extents.bounded);
7161 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
7164 /* Check if we can use a stencil mask */
7165 status = _cairo_pdf_surface_emit_stencil_mask (surface, op, source, mask, &extents.bounded);
7166 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
7169 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
7170 if (unlikely (group == NULL)) {
7171 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7175 group->operation = PDF_MASK;
7176 status = _cairo_pattern_create_copy (&group->source, source);
7177 if (unlikely (status)) {
7178 _cairo_pdf_smask_group_destroy (group);
7181 status = _cairo_pattern_create_copy (&group->mask, mask);
7182 if (unlikely (status)) {
7183 _cairo_pdf_smask_group_destroy (group);
7186 group->source_res = _cairo_pdf_surface_new_object (surface);
7187 if (group->source_res.id == 0) {
7188 _cairo_pdf_smask_group_destroy (group);
7189 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7193 status = _cairo_pdf_surface_add_smask_group (surface, group);
7194 if (unlikely (status)) {
7195 _cairo_pdf_smask_group_destroy (group);
7199 status = _cairo_pdf_surface_add_smask (surface, group->group_res);
7200 if (unlikely (status))
7203 status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
7204 if (unlikely (status))
7207 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7208 if (unlikely (status))
7211 _cairo_output_stream_printf (surface->output,
7212 "q /s%d gs /x%d Do Q\n",
7213 group->group_res.id,
7214 group->source_res.id);
7216 _cairo_composite_rectangles_fini (&extents);
7217 return _cairo_output_stream_get_status (surface->output);
7220 _cairo_composite_rectangles_fini (&extents);
7224 static cairo_int_status_t
7225 _cairo_pdf_surface_stroke (void *abstract_surface,
7226 cairo_operator_t op,
7227 const cairo_pattern_t *source,
7228 const cairo_path_fixed_t *path,
7229 const cairo_stroke_style_t *style,
7230 const cairo_matrix_t *ctm,
7231 const cairo_matrix_t *ctm_inverse,
7233 cairo_antialias_t antialias,
7234 const cairo_clip_t *clip)
7236 cairo_pdf_surface_t *surface = abstract_surface;
7237 cairo_pdf_smask_group_t *group;
7238 cairo_pdf_resource_t pattern_res, gstate_res;
7239 cairo_composite_rectangles_t extents;
7240 cairo_int_status_t status;
7242 status = _cairo_composite_rectangles_init_for_stroke (&extents,
7247 if (unlikely (status))
7250 /* use the more accurate extents */
7251 if (extents.is_bounded) {
7252 cairo_rectangle_int_t mask;
7255 status = _cairo_path_fixed_stroke_extents (path, style,
7259 if (unlikely (status))
7262 _cairo_box_from_rectangle (&box, &mask);
7263 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
7265 if (unlikely (status))
7269 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
7270 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
7274 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
7276 status = _cairo_pdf_surface_set_clip (surface, &extents);
7277 if (unlikely (status))
7282 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
7284 &pattern_res, &gstate_res);
7285 if (unlikely (status))
7288 status = _cairo_pdf_surface_select_operator (surface, op);
7289 if (unlikely (status))
7292 if (gstate_res.id != 0) {
7293 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
7294 if (unlikely (group == NULL)) {
7295 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7299 group->operation = PDF_STROKE;
7300 status = _cairo_pattern_create_copy (&group->source, source);
7301 if (unlikely (status)) {
7302 _cairo_pdf_smask_group_destroy (group);
7305 group->source_res = pattern_res;
7306 status = _cairo_path_fixed_init_copy (&group->path, path);
7307 if (unlikely (status)) {
7308 _cairo_pdf_smask_group_destroy (group);
7312 group->style = *style;
7314 group->ctm_inverse = *ctm_inverse;
7315 status = _cairo_pdf_surface_add_smask_group (surface, group);
7316 if (unlikely (status)) {
7317 _cairo_pdf_smask_group_destroy (group);
7321 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
7322 if (unlikely (status))
7325 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
7326 if (unlikely (status))
7329 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7330 if (unlikely (status))
7333 _cairo_output_stream_printf (surface->output,
7334 "q /s%d gs /x%d Do Q\n",
7336 group->group_res.id);
7338 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
7339 if (unlikely (status))
7342 status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
7347 if (unlikely (status))
7350 status = _cairo_pdf_surface_unselect_pattern (surface);
7351 if (unlikely (status))
7355 _cairo_composite_rectangles_fini (&extents);
7356 return _cairo_output_stream_get_status (surface->output);
7359 _cairo_composite_rectangles_fini (&extents);
7363 static cairo_int_status_t
7364 _cairo_pdf_surface_fill (void *abstract_surface,
7365 cairo_operator_t op,
7366 const cairo_pattern_t *source,
7367 const cairo_path_fixed_t*path,
7368 cairo_fill_rule_t fill_rule,
7370 cairo_antialias_t antialias,
7371 const cairo_clip_t *clip)
7373 cairo_pdf_surface_t *surface = abstract_surface;
7374 cairo_int_status_t status;
7375 cairo_pdf_smask_group_t *group;
7376 cairo_pdf_resource_t pattern_res, gstate_res;
7377 cairo_composite_rectangles_t extents;
7379 status = _cairo_composite_rectangles_init_for_fill (&extents,
7383 if (unlikely (status))
7386 /* use the more accurate extents */
7387 if (extents.is_bounded) {
7388 cairo_rectangle_int_t mask;
7391 _cairo_path_fixed_fill_extents (path,
7396 _cairo_box_from_rectangle (&box, &mask);
7397 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
7399 if (unlikely (status))
7403 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
7404 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
7406 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
7407 status = _cairo_pdf_surface_start_fallback (surface);
7408 if (unlikely (status))
7412 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
7414 status = _cairo_pdf_surface_set_clip (surface, &extents);
7415 if (unlikely (status))
7418 status = _cairo_pdf_surface_select_operator (surface, op);
7419 if (unlikely (status))
7422 if (_can_paint_pattern (source)) {
7423 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7424 if (unlikely (status))
7427 _cairo_output_stream_printf (surface->output, "q\n");
7428 status = _cairo_pdf_operators_clip (&surface->pdf_operators,
7431 if (unlikely (status))
7434 status = _cairo_pdf_surface_paint_pattern (surface,
7439 if (unlikely (status))
7442 _cairo_output_stream_printf (surface->output, "Q\n");
7443 status = _cairo_output_stream_get_status (surface->output);
7449 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
7451 &pattern_res, &gstate_res);
7452 if (unlikely (status))
7455 if (gstate_res.id != 0) {
7456 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
7457 if (unlikely (group == NULL)) {
7458 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7462 group->operation = PDF_FILL;
7463 status = _cairo_pattern_create_copy (&group->source, source);
7464 if (unlikely (status)) {
7465 _cairo_pdf_smask_group_destroy (group);
7468 group->source_res = pattern_res;
7469 status = _cairo_path_fixed_init_copy (&group->path, path);
7470 if (unlikely (status)) {
7471 _cairo_pdf_smask_group_destroy (group);
7475 group->fill_rule = fill_rule;
7476 status = _cairo_pdf_surface_add_smask_group (surface, group);
7477 if (unlikely (status)) {
7478 _cairo_pdf_smask_group_destroy (group);
7482 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
7483 if (unlikely (status))
7486 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
7487 if (unlikely (status))
7490 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7491 if (unlikely (status))
7494 _cairo_output_stream_printf (surface->output,
7495 "q /s%d gs /x%d Do Q\n",
7497 group->group_res.id);
7499 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
7500 if (unlikely (status))
7503 status = _cairo_pdf_operators_fill (&surface->pdf_operators,
7506 if (unlikely (status))
7509 status = _cairo_pdf_surface_unselect_pattern (surface);
7510 if (unlikely (status))
7514 _cairo_composite_rectangles_fini (&extents);
7515 return _cairo_output_stream_get_status (surface->output);
7518 _cairo_composite_rectangles_fini (&extents);
7522 static cairo_int_status_t
7523 _cairo_pdf_surface_fill_stroke (void *abstract_surface,
7524 cairo_operator_t fill_op,
7525 const cairo_pattern_t *fill_source,
7526 cairo_fill_rule_t fill_rule,
7527 double fill_tolerance,
7528 cairo_antialias_t fill_antialias,
7529 const cairo_path_fixed_t*path,
7530 cairo_operator_t stroke_op,
7531 const cairo_pattern_t *stroke_source,
7532 const cairo_stroke_style_t *stroke_style,
7533 const cairo_matrix_t *stroke_ctm,
7534 const cairo_matrix_t *stroke_ctm_inverse,
7535 double stroke_tolerance,
7536 cairo_antialias_t stroke_antialias,
7537 const cairo_clip_t *clip)
7539 cairo_pdf_surface_t *surface = abstract_surface;
7540 cairo_int_status_t status;
7541 cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res;
7542 cairo_composite_rectangles_t extents;
7544 /* During analysis we return unsupported and let the _fill and
7545 * _stroke functions that are on the fallback path do the analysis
7546 * for us. During render we may still encounter unsupported
7547 * combinations of fill/stroke patterns. However we can return
7548 * unsupported anytime to let the _fill and _stroke functions take
7551 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
7552 return CAIRO_INT_STATUS_UNSUPPORTED;
7554 /* PDF rendering of fill-stroke is not the same as cairo when
7555 * either the fill or stroke is not opaque.
7557 if ( !_cairo_pattern_is_opaque (fill_source, NULL) ||
7558 !_cairo_pattern_is_opaque (stroke_source, NULL))
7560 return CAIRO_INT_STATUS_UNSUPPORTED;
7563 if (fill_op != stroke_op)
7564 return CAIRO_INT_STATUS_UNSUPPORTED;
7566 /* Compute the operation extents using the stroke which will naturally
7567 * be larger than the fill extents.
7569 status = _cairo_composite_rectangles_init_for_stroke (&extents,
7571 stroke_op, stroke_source,
7572 path, stroke_style, stroke_ctm,
7574 if (unlikely (status))
7577 /* use the more accurate extents */
7578 if (extents.is_bounded) {
7579 cairo_rectangle_int_t mask;
7582 status = _cairo_path_fixed_stroke_extents (path, stroke_style,
7583 stroke_ctm, stroke_ctm_inverse,
7586 if (unlikely (status))
7589 _cairo_box_from_rectangle (&box, &mask);
7590 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
7592 if (unlikely (status))
7596 status = _cairo_pdf_surface_set_clip (surface, &extents);
7597 if (unlikely (status))
7600 status = _cairo_pdf_surface_select_operator (surface, fill_op);
7601 if (unlikely (status))
7604 /* use the more accurate extents */
7605 if (extents.is_bounded) {
7606 cairo_rectangle_int_t mask;
7609 _cairo_path_fixed_fill_extents (path,
7614 _cairo_box_from_rectangle (&box, &mask);
7615 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
7617 if (unlikely (status))
7621 fill_pattern_res.id = 0;
7623 status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
7628 if (unlikely (status))
7631 assert (gstate_res.id == 0);
7633 stroke_pattern_res.id = 0;
7635 status = _cairo_pdf_surface_add_pdf_pattern (surface,
7639 &stroke_pattern_res,
7641 if (unlikely (status))
7644 assert (gstate_res.id == 0);
7646 /* As PDF has separate graphics state for fill and stroke we can
7647 * select both at the same time */
7648 status = _cairo_pdf_surface_select_pattern (surface, fill_source,
7649 fill_pattern_res, FALSE);
7650 if (unlikely (status))
7653 status = _cairo_pdf_surface_select_pattern (surface, stroke_source,
7654 stroke_pattern_res, TRUE);
7655 if (unlikely (status))
7658 status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators,
7663 stroke_ctm_inverse);
7664 if (unlikely (status))
7667 status = _cairo_pdf_surface_unselect_pattern (surface);
7668 if (unlikely (status))
7671 _cairo_composite_rectangles_fini (&extents);
7672 return _cairo_output_stream_get_status (surface->output);
7675 _cairo_composite_rectangles_fini (&extents);
7680 _cairo_pdf_surface_has_show_text_glyphs (void *abstract_surface)
7685 static cairo_int_status_t
7686 _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
7687 cairo_operator_t op,
7688 const cairo_pattern_t *source,
7691 cairo_glyph_t *glyphs,
7693 const cairo_text_cluster_t *clusters,
7695 cairo_text_cluster_flags_t cluster_flags,
7696 cairo_scaled_font_t *scaled_font,
7697 const cairo_clip_t *clip)
7699 cairo_pdf_surface_t *surface = abstract_surface;
7700 cairo_pdf_smask_group_t *group;
7701 cairo_pdf_resource_t pattern_res, gstate_res;
7702 cairo_composite_rectangles_t extents;
7703 cairo_bool_t overlap;
7704 cairo_int_status_t status;
7706 status = _cairo_composite_rectangles_init_for_glyphs (&extents,
7713 if (unlikely (status))
7716 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
7717 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
7721 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
7723 status = _cairo_pdf_surface_set_clip (surface, &extents);
7724 if (unlikely (status))
7729 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
7731 &pattern_res, &gstate_res);
7732 if (unlikely (status))
7735 status = _cairo_pdf_surface_select_operator (surface, op);
7736 if (unlikely (status))
7739 if (gstate_res.id != 0) {
7740 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
7741 if (unlikely (group == NULL)) {
7742 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7746 group->operation = PDF_SHOW_GLYPHS;
7747 status = _cairo_pattern_create_copy (&group->source, source);
7748 if (unlikely (status)) {
7749 _cairo_pdf_smask_group_destroy (group);
7752 group->source_res = pattern_res;
7755 group->utf8 = malloc (utf8_len);
7756 if (unlikely (group->utf8 == NULL)) {
7757 _cairo_pdf_smask_group_destroy (group);
7758 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7761 memcpy (group->utf8, utf8, utf8_len);
7763 group->utf8_len = utf8_len;
7766 group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
7767 if (unlikely (group->glyphs == NULL)) {
7768 _cairo_pdf_smask_group_destroy (group);
7769 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7772 memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
7774 group->num_glyphs = num_glyphs;
7777 group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
7778 if (unlikely (group->clusters == NULL)) {
7779 _cairo_pdf_smask_group_destroy (group);
7780 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7783 memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
7785 group->num_clusters = num_clusters;
7787 group->scaled_font = cairo_scaled_font_reference (scaled_font);
7788 status = _cairo_pdf_surface_add_smask_group (surface, group);
7789 if (unlikely (status)) {
7790 _cairo_pdf_smask_group_destroy (group);
7794 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
7795 if (unlikely (status))
7798 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
7799 if (unlikely (status))
7802 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7803 if (unlikely (status))
7806 _cairo_output_stream_printf (surface->output,
7807 "q /s%d gs /x%d Do Q\n",
7809 group->group_res.id);
7811 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
7812 if (unlikely (status))
7815 /* Each call to show_glyphs() with a transclucent pattern must
7816 * be in a separate text object otherwise overlapping text
7817 * from separate calls to show_glyphs will not composite with
7819 if (! _cairo_pattern_is_opaque (source, &extents.bounded)) {
7820 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7821 if (unlikely (status))
7825 status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
7828 clusters, num_clusters,
7831 if (unlikely (status))
7834 status = _cairo_pdf_surface_unselect_pattern (surface);
7835 if (unlikely (status))
7839 _cairo_composite_rectangles_fini (&extents);
7840 return _cairo_output_stream_get_status (surface->output);
7843 _cairo_composite_rectangles_fini (&extents);
7847 static const char **
7848 _cairo_pdf_surface_get_supported_mime_types (void *abstract_surface)
7850 return _cairo_pdf_supported_mime_types;
7854 _cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
7855 cairo_paginated_mode_t paginated_mode)
7857 cairo_pdf_surface_t *surface = abstract_surface;
7859 surface->paginated_mode = paginated_mode;
7862 static const cairo_surface_backend_t cairo_pdf_surface_backend = {
7863 CAIRO_SURFACE_TYPE_PDF,
7864 _cairo_pdf_surface_finish,
7866 _cairo_default_context_create,
7868 NULL, /* create similar: handled by wrapper */
7869 NULL, /* create similar image */
7870 NULL, /* map to image */
7871 NULL, /* unmap image */
7873 _cairo_surface_default_source,
7874 NULL, /* acquire_source_image */
7875 NULL, /* release_source_image */
7876 NULL, /* snapshot */
7878 NULL, /* _cairo_pdf_surface_copy_page */
7879 _cairo_pdf_surface_show_page,
7881 _cairo_pdf_surface_get_extents,
7882 _cairo_pdf_surface_get_font_options,
7885 NULL, /* mark_dirty_rectangle */
7887 /* Here are the drawing functions */
7888 _cairo_pdf_surface_paint,
7889 _cairo_pdf_surface_mask,
7890 _cairo_pdf_surface_stroke,
7891 _cairo_pdf_surface_fill,
7892 _cairo_pdf_surface_fill_stroke,
7893 NULL, /* show_glyphs */
7894 _cairo_pdf_surface_has_show_text_glyphs,
7895 _cairo_pdf_surface_show_text_glyphs,
7896 _cairo_pdf_surface_get_supported_mime_types,
7899 static const cairo_paginated_surface_backend_t
7900 cairo_pdf_surface_paginated_backend = {
7901 _cairo_pdf_surface_start_page,
7902 _cairo_pdf_surface_set_paginated_mode,
7903 NULL, /* set_bounding_box */
7904 _cairo_pdf_surface_has_fallback_images,
7905 _cairo_pdf_surface_supports_fine_grained_fallbacks,