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-private.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.
136 _cairo_pdf_surface_get_extents (void *abstract_surface,
137 cairo_rectangle_int_t *rectangle);
140 * CAIRO_HAS_PDF_SURFACE:
142 * Defined if the PDF surface backend is available.
143 * This macro can be used to conditionally compile backend-specific code.
148 static const cairo_pdf_version_t _cairo_pdf_versions[] =
150 CAIRO_PDF_VERSION_1_4,
151 CAIRO_PDF_VERSION_1_5
154 #define CAIRO_PDF_VERSION_LAST ARRAY_LENGTH (_cairo_pdf_versions)
156 static const char * _cairo_pdf_version_strings[CAIRO_PDF_VERSION_LAST] =
162 static const char *_cairo_pdf_supported_mime_types[] =
164 CAIRO_MIME_TYPE_JPEG,
166 CAIRO_MIME_TYPE_UNIQUE_ID,
170 typedef struct _cairo_pdf_object {
172 } cairo_pdf_object_t;
174 typedef struct _cairo_pdf_font {
175 unsigned int font_id;
176 unsigned int subset_id;
177 cairo_pdf_resource_t subset_resource;
180 typedef struct _cairo_pdf_rgb_linear_function {
181 cairo_pdf_resource_t resource;
184 } cairo_pdf_rgb_linear_function_t;
186 typedef struct _cairo_pdf_alpha_linear_function {
187 cairo_pdf_resource_t resource;
190 } cairo_pdf_alpha_linear_function_t;
192 static cairo_pdf_resource_t
193 _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
196 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
199 _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
201 static cairo_status_t
202 _cairo_pdf_surface_add_font (unsigned int font_id,
203 unsigned int subset_id,
207 _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
209 static cairo_status_t
210 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
211 cairo_pdf_resource_t *resource,
212 cairo_bool_t compressed,
214 ...) CAIRO_PRINTF_FORMAT(4, 5);
215 static cairo_status_t
216 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface);
218 static cairo_status_t
219 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
222 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
224 static cairo_pdf_resource_t
225 _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface);
227 static cairo_pdf_resource_t
228 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface);
231 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
233 static cairo_status_t
234 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
236 static cairo_status_t
237 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
240 _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b);
242 static const cairo_surface_backend_t cairo_pdf_surface_backend;
243 static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
245 static cairo_pdf_resource_t
246 _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
248 cairo_pdf_resource_t resource;
249 cairo_status_t status;
250 cairo_pdf_object_t object;
252 object.offset = _cairo_output_stream_get_position (surface->output);
254 status = _cairo_array_append (&surface->objects, &object);
255 if (unlikely (status)) {
260 resource = surface->next_available_resource;
261 surface->next_available_resource.id++;
267 _cairo_pdf_surface_update_object (cairo_pdf_surface_t *surface,
268 cairo_pdf_resource_t resource)
270 cairo_pdf_object_t *object;
272 object = _cairo_array_index (&surface->objects, resource.id - 1);
273 object->offset = _cairo_output_stream_get_position (surface->output);
277 _cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
281 surface->width = width;
282 surface->height = height;
283 cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
284 _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
285 &surface->cairo_to_pdf);
289 _path_covers_bbox (cairo_pdf_surface_t *surface,
290 cairo_path_fixed_t *path)
294 return _cairo_path_fixed_is_box (path, &box) &&
297 box.p2.x >= _cairo_fixed_from_double (surface->width) &&
298 box.p2.y >= _cairo_fixed_from_double (surface->height);
301 static cairo_status_t
302 _cairo_pdf_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
303 cairo_path_fixed_t *path,
304 cairo_fill_rule_t fill_rule,
306 cairo_antialias_t antialias)
308 cairo_pdf_surface_t *surface = cairo_container_of (clipper,
311 cairo_int_status_t status;
313 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
314 if (unlikely (status))
318 _cairo_output_stream_printf (surface->output, "Q q\n");
320 surface->current_pattern_is_solid_color = FALSE;
321 _cairo_pdf_operators_reset (&surface->pdf_operators);
323 return CAIRO_STATUS_SUCCESS;
326 if (_path_covers_bbox (surface, path))
327 return CAIRO_STATUS_SUCCESS;
329 return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
332 static cairo_surface_t *
333 _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
337 cairo_pdf_surface_t *surface;
338 cairo_status_t status, status_ignored;
340 surface = malloc (sizeof (cairo_pdf_surface_t));
341 if (unlikely (surface == NULL)) {
342 /* destroy stream on behalf of caller */
343 status = _cairo_output_stream_destroy (output);
344 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
347 _cairo_surface_init (&surface->base,
348 &cairo_pdf_surface_backend,
350 CAIRO_CONTENT_COLOR_ALPHA);
352 surface->output = output;
353 surface->width = width;
354 surface->height = height;
355 cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
357 _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
358 _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
359 _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
360 _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
361 _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
362 _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
363 _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t));
365 _cairo_array_init (&surface->page_patterns, sizeof (cairo_pdf_pattern_t));
366 _cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t));
367 surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal);
368 if (unlikely (surface->all_surfaces == NULL)) {
369 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
373 _cairo_pdf_group_resources_init (&surface->resources);
375 surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
376 if (! surface->font_subsets) {
377 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
381 _cairo_scaled_font_subsets_enable_latin_subset (surface->font_subsets, TRUE);
383 surface->next_available_resource.id = 1;
384 surface->pages_resource = _cairo_pdf_surface_new_object (surface);
385 if (surface->pages_resource.id == 0) {
386 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
390 surface->pdf_version = CAIRO_PDF_VERSION_1_5;
391 surface->compress_content = TRUE;
392 surface->pdf_stream.active = FALSE;
393 surface->pdf_stream.old_output = NULL;
394 surface->group_stream.active = FALSE;
395 surface->group_stream.stream = NULL;
396 surface->group_stream.mem_stream = NULL;
398 surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
400 surface->force_fallbacks = FALSE;
401 surface->select_pattern_gstate_saved = FALSE;
402 surface->current_pattern_is_solid_color = FALSE;
403 surface->current_operator = CAIRO_OPERATOR_OVER;
404 surface->header_emitted = FALSE;
406 _cairo_surface_clipper_init (&surface->clipper,
407 _cairo_pdf_surface_clipper_intersect_clip_path);
409 _cairo_pdf_operators_init (&surface->pdf_operators,
411 &surface->cairo_to_pdf,
412 surface->font_subsets);
413 _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
414 _cairo_pdf_surface_add_font,
416 _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators, TRUE);
418 surface->paginated_surface = _cairo_paginated_surface_create (
420 CAIRO_CONTENT_COLOR_ALPHA,
421 &cairo_pdf_surface_paginated_backend);
423 status = surface->paginated_surface->status;
424 if (status == CAIRO_STATUS_SUCCESS) {
425 /* paginated keeps the only reference to surface now, drop ours */
426 cairo_surface_destroy (&surface->base);
427 return surface->paginated_surface;
431 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
433 _cairo_hash_table_destroy (surface->all_surfaces);
435 _cairo_array_fini (&surface->objects);
438 /* destroy stream on behalf of caller */
439 status_ignored = _cairo_output_stream_destroy (output);
441 return _cairo_surface_create_in_error (status);
445 * cairo_pdf_surface_create_for_stream:
446 * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
447 * to indicate a no-op @write_func. With a no-op @write_func,
448 * the surface may be queried or used as a source without
449 * generating any temporary files.
450 * @closure: the closure argument for @write_func
451 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
452 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
454 * Creates a PDF surface of the specified size in points to be written
455 * incrementally to the stream represented by @write_func and @closure.
457 * Return value: a pointer to the newly created surface. The caller
458 * owns the surface and should call cairo_surface_destroy() when done
461 * This function always returns a valid pointer, but it will return a
462 * pointer to a "nil" surface if an error such as out of memory
463 * occurs. You can use cairo_surface_status() to check for this.
468 cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func,
470 double width_in_points,
471 double height_in_points)
473 cairo_output_stream_t *output;
475 output = _cairo_output_stream_create (write_func, NULL, closure);
476 if (_cairo_output_stream_get_status (output))
477 return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
479 return _cairo_pdf_surface_create_for_stream_internal (output,
485 * cairo_pdf_surface_create:
486 * @filename: a filename for the PDF output (must be writable), %NULL may be
487 * used to specify no output. This will generate a PDF surface that
488 * may be queried and used as a source, without generating a
490 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
491 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
493 * Creates a PDF surface of the specified size in points to be written
496 * Return value: a pointer to the newly created surface. The caller
497 * owns the surface and should call cairo_surface_destroy() when done
500 * This function always returns a valid pointer, but it will return a
501 * pointer to a "nil" surface if an error such as out of memory
502 * occurs. You can use cairo_surface_status() to check for this.
507 cairo_pdf_surface_create (const char *filename,
508 double width_in_points,
509 double height_in_points)
511 cairo_output_stream_t *output;
513 output = _cairo_output_stream_create_for_filename (filename);
514 if (_cairo_output_stream_get_status (output))
515 return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
517 return _cairo_pdf_surface_create_for_stream_internal (output,
523 _cairo_surface_is_pdf (cairo_surface_t *surface)
525 return surface->backend == &cairo_pdf_surface_backend;
528 /* If the abstract_surface is a paginated surface, and that paginated
529 * surface's target is a pdf_surface, then set pdf_surface to that
530 * target. Otherwise return FALSE.
533 _extract_pdf_surface (cairo_surface_t *surface,
534 cairo_pdf_surface_t **pdf_surface)
536 cairo_surface_t *target;
537 cairo_status_t status_ignored;
541 if (surface->finished) {
542 status_ignored = _cairo_surface_set_error (surface,
543 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
547 if (! _cairo_surface_is_paginated (surface)) {
548 status_ignored = _cairo_surface_set_error (surface,
549 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
553 target = _cairo_paginated_surface_get_target (surface);
554 if (target->status) {
555 status_ignored = _cairo_surface_set_error (surface,
559 if (target->finished) {
560 status_ignored = _cairo_surface_set_error (surface,
561 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
565 if (! _cairo_surface_is_pdf (target)) {
566 status_ignored = _cairo_surface_set_error (surface,
567 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
571 *pdf_surface = (cairo_pdf_surface_t *) target;
576 * cairo_pdf_surface_restrict_to_version:
577 * @surface: a PDF #cairo_surface_t
578 * @version: PDF version
580 * Restricts the generated PDF file to @version. See cairo_pdf_get_versions()
581 * for a list of available version values that can be used here.
583 * This function should only be called before any drawing operations
584 * have been performed on the given surface. The simplest way to do
585 * this is to call this function immediately after creating the
591 cairo_pdf_surface_restrict_to_version (cairo_surface_t *abstract_surface,
592 cairo_pdf_version_t version)
594 cairo_pdf_surface_t *surface = NULL; /* hide compiler warning */
596 if (! _extract_pdf_surface (abstract_surface, &surface))
599 if (version < CAIRO_PDF_VERSION_LAST)
600 surface->pdf_version = version;
602 _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators,
603 version >= CAIRO_PDF_VERSION_1_5);
607 * cairo_pdf_get_versions:
608 * @versions: supported version list
609 * @num_versions: list length
611 * Used to retrieve the list of supported versions. See
612 * cairo_pdf_surface_restrict_to_version().
617 cairo_pdf_get_versions (cairo_pdf_version_t const **versions,
620 if (versions != NULL)
621 *versions = _cairo_pdf_versions;
623 if (num_versions != NULL)
624 *num_versions = CAIRO_PDF_VERSION_LAST;
628 * cairo_pdf_version_to_string:
629 * @version: a version id
631 * Get the string representation of the given @version id. This function
632 * will return %NULL if @version isn't valid. See cairo_pdf_get_versions()
633 * for a way to get the list of valid version ids.
635 * Return value: the string associated to given version.
640 cairo_pdf_version_to_string (cairo_pdf_version_t version)
642 if (version >= CAIRO_PDF_VERSION_LAST)
645 return _cairo_pdf_version_strings[version];
649 * cairo_pdf_surface_set_size:
650 * @surface: a PDF #cairo_surface_t
651 * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
652 * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
654 * Changes the size of a PDF surface for the current (and
657 * This function should only be called before any drawing operations
658 * have been performed on the current page. The simplest way to do
659 * this is to call this function immediately after creating the
660 * surface or immediately after completing a page with either
661 * cairo_show_page() or cairo_copy_page().
666 cairo_pdf_surface_set_size (cairo_surface_t *surface,
667 double width_in_points,
668 double height_in_points)
670 cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
671 cairo_status_t status;
673 if (! _extract_pdf_surface (surface, &pdf_surface))
676 _cairo_pdf_surface_set_size_internal (pdf_surface,
679 status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
683 status = _cairo_surface_set_error (surface, status);
687 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
690 cairo_pdf_pattern_t *pattern;
691 cairo_pdf_source_surface_t *src_surface;
692 cairo_pdf_smask_group_t *group;
694 size = _cairo_array_num_elements (&surface->page_patterns);
695 for (i = 0; i < size; i++) {
696 pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->page_patterns, i);
697 cairo_pattern_destroy (pattern->pattern);
699 _cairo_array_truncate (&surface->page_patterns, 0);
701 size = _cairo_array_num_elements (&surface->page_surfaces);
702 for (i = 0; i < size; i++) {
703 src_surface = (cairo_pdf_source_surface_t *) _cairo_array_index (&surface->page_surfaces, i);
704 cairo_surface_destroy (src_surface->surface);
706 _cairo_array_truncate (&surface->page_surfaces, 0);
708 size = _cairo_array_num_elements (&surface->smask_groups);
709 for (i = 0; i < size; i++) {
710 _cairo_array_copy_element (&surface->smask_groups, i, &group);
711 _cairo_pdf_smask_group_destroy (group);
713 _cairo_array_truncate (&surface->smask_groups, 0);
714 _cairo_array_truncate (&surface->knockout_group, 0);
718 _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
722 for (i = 0; i < CAIRO_NUM_OPERATORS; i++)
723 res->operators[i] = FALSE;
725 _cairo_array_init (&res->alphas, sizeof (double));
726 _cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t));
727 _cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t));
728 _cairo_array_init (&res->shadings, sizeof (cairo_pdf_resource_t));
729 _cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t));
730 _cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t));
734 _cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
736 _cairo_array_fini (&res->alphas);
737 _cairo_array_fini (&res->smasks);
738 _cairo_array_fini (&res->patterns);
739 _cairo_array_fini (&res->shadings);
740 _cairo_array_fini (&res->xobjects);
741 _cairo_array_fini (&res->fonts);
745 _cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
749 for (i = 0; i < CAIRO_NUM_OPERATORS; i++)
750 res->operators[i] = FALSE;
752 _cairo_array_truncate (&res->alphas, 0);
753 _cairo_array_truncate (&res->smasks, 0);
754 _cairo_array_truncate (&res->patterns, 0);
755 _cairo_array_truncate (&res->shadings, 0);
756 _cairo_array_truncate (&res->xobjects, 0);
757 _cairo_array_truncate (&res->fonts, 0);
761 _cairo_pdf_surface_add_operator (cairo_pdf_surface_t *surface,
764 cairo_pdf_group_resources_t *res = &surface->resources;
766 res->operators[op] = TRUE;
769 static cairo_status_t
770 _cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
776 cairo_status_t status;
777 cairo_pdf_group_resources_t *res = &surface->resources;
779 num_alphas = _cairo_array_num_elements (&res->alphas);
780 for (i = 0; i < num_alphas; i++) {
781 _cairo_array_copy_element (&res->alphas, i, &other);
782 if (alpha == other) {
784 return CAIRO_STATUS_SUCCESS;
788 status = _cairo_array_append (&res->alphas, &alpha);
789 if (unlikely (status))
792 *index = _cairo_array_num_elements (&res->alphas) - 1;
794 return CAIRO_STATUS_SUCCESS;
797 static cairo_status_t
798 _cairo_pdf_surface_add_smask (cairo_pdf_surface_t *surface,
799 cairo_pdf_resource_t smask)
801 return _cairo_array_append (&(surface->resources.smasks), &smask);
804 static cairo_status_t
805 _cairo_pdf_surface_add_pattern (cairo_pdf_surface_t *surface,
806 cairo_pdf_resource_t pattern)
808 return _cairo_array_append (&(surface->resources.patterns), &pattern);
811 static cairo_status_t
812 _cairo_pdf_surface_add_shading (cairo_pdf_surface_t *surface,
813 cairo_pdf_resource_t shading)
815 return _cairo_array_append (&(surface->resources.shadings), &shading);
819 static cairo_status_t
820 _cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface,
821 cairo_pdf_resource_t xobject)
823 return _cairo_array_append (&(surface->resources.xobjects), &xobject);
826 static cairo_status_t
827 _cairo_pdf_surface_add_font (unsigned int font_id,
828 unsigned int subset_id,
831 cairo_pdf_surface_t *surface = closure;
832 cairo_pdf_font_t font;
834 cairo_status_t status;
835 cairo_pdf_group_resources_t *res = &surface->resources;
837 num_fonts = _cairo_array_num_elements (&res->fonts);
838 for (i = 0; i < num_fonts; i++) {
839 _cairo_array_copy_element (&res->fonts, i, &font);
840 if (font.font_id == font_id &&
841 font.subset_id == subset_id)
842 return CAIRO_STATUS_SUCCESS;
845 num_fonts = _cairo_array_num_elements (&surface->fonts);
846 for (i = 0; i < num_fonts; i++) {
847 _cairo_array_copy_element (&surface->fonts, i, &font);
848 if (font.font_id == font_id &&
849 font.subset_id == subset_id)
850 return _cairo_array_append (&res->fonts, &font);
853 font.font_id = font_id;
854 font.subset_id = subset_id;
855 font.subset_resource = _cairo_pdf_surface_new_object (surface);
856 if (font.subset_resource.id == 0)
857 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
859 status = _cairo_array_append (&surface->fonts, &font);
860 if (unlikely (status))
863 return _cairo_array_append (&res->fonts, &font);
866 static cairo_pdf_resource_t
867 _cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface,
868 unsigned int font_id,
869 unsigned int subset_id)
871 cairo_pdf_font_t font;
874 num_fonts = _cairo_array_num_elements (&surface->fonts);
875 for (i = 0; i < num_fonts; i++) {
876 _cairo_array_copy_element (&surface->fonts, i, &font);
877 if (font.font_id == font_id && font.subset_id == subset_id)
878 return font.subset_resource;
881 font.subset_resource.id = 0;
882 return font.subset_resource;
886 _cairo_operator_to_pdf_blend_mode (cairo_operator_t op)
889 /* The extend blend mode operators */
890 case CAIRO_OPERATOR_MULTIPLY: return "Multiply";
891 case CAIRO_OPERATOR_SCREEN: return "Screen";
892 case CAIRO_OPERATOR_OVERLAY: return "Overlay";
893 case CAIRO_OPERATOR_DARKEN: return "Darken";
894 case CAIRO_OPERATOR_LIGHTEN: return "Lighten";
895 case CAIRO_OPERATOR_COLOR_DODGE: return "ColorDodge";
896 case CAIRO_OPERATOR_COLOR_BURN: return "ColorBurn";
897 case CAIRO_OPERATOR_HARD_LIGHT: return "HardLight";
898 case CAIRO_OPERATOR_SOFT_LIGHT: return "SoftLight";
899 case CAIRO_OPERATOR_DIFFERENCE: return "Difference";
900 case CAIRO_OPERATOR_EXCLUSION: return "Exclusion";
901 case CAIRO_OPERATOR_HSL_HUE: return "Hue";
902 case CAIRO_OPERATOR_HSL_SATURATION: return "Saturation";
903 case CAIRO_OPERATOR_HSL_COLOR: return "Color";
904 case CAIRO_OPERATOR_HSL_LUMINOSITY: return "Luminosity";
907 /* The original Porter-Duff set */
908 case CAIRO_OPERATOR_CLEAR:
909 case CAIRO_OPERATOR_SOURCE:
910 case CAIRO_OPERATOR_OVER:
911 case CAIRO_OPERATOR_IN:
912 case CAIRO_OPERATOR_OUT:
913 case CAIRO_OPERATOR_ATOP:
914 case CAIRO_OPERATOR_DEST:
915 case CAIRO_OPERATOR_DEST_OVER:
916 case CAIRO_OPERATOR_DEST_IN:
917 case CAIRO_OPERATOR_DEST_OUT:
918 case CAIRO_OPERATOR_DEST_ATOP:
919 case CAIRO_OPERATOR_XOR:
920 case CAIRO_OPERATOR_ADD:
921 case CAIRO_OPERATOR_SATURATE:
927 _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface,
928 cairo_pdf_group_resources_t *res)
930 int num_alphas, num_smasks, num_resources, i;
932 cairo_pdf_resource_t *smask, *pattern, *shading, *xobject;
933 cairo_pdf_font_t *font;
935 _cairo_output_stream_printf (surface->output, "<<\n");
937 num_alphas = _cairo_array_num_elements (&res->alphas);
938 num_smasks = _cairo_array_num_elements (&res->smasks);
939 if (num_alphas > 0 || num_smasks > 0) {
940 _cairo_output_stream_printf (surface->output,
943 for (i = 0; i < CAIRO_NUM_OPERATORS; i++) {
944 if (res->operators[i]) {
945 _cairo_output_stream_printf (surface->output,
946 " /b%d << /BM /%s >>\n",
947 i, _cairo_operator_to_pdf_blend_mode(i));
951 for (i = 0; i < num_alphas; i++) {
952 _cairo_array_copy_element (&res->alphas, i, &alpha);
953 _cairo_output_stream_printf (surface->output,
954 " /a%d << /CA %f /ca %f >>\n",
958 for (i = 0; i < num_smasks; i++) {
959 smask = _cairo_array_index (&res->smasks, i);
960 _cairo_output_stream_printf (surface->output,
962 smask->id, smask->id);
965 _cairo_output_stream_printf (surface->output,
969 num_resources = _cairo_array_num_elements (&res->patterns);
970 if (num_resources > 0) {
971 _cairo_output_stream_printf (surface->output,
973 for (i = 0; i < num_resources; i++) {
974 pattern = _cairo_array_index (&res->patterns, i);
975 _cairo_output_stream_printf (surface->output,
977 pattern->id, pattern->id);
980 _cairo_output_stream_printf (surface->output,
984 num_resources = _cairo_array_num_elements (&res->shadings);
985 if (num_resources > 0) {
986 _cairo_output_stream_printf (surface->output,
988 for (i = 0; i < num_resources; i++) {
989 shading = _cairo_array_index (&res->shadings, i);
990 _cairo_output_stream_printf (surface->output,
992 shading->id, shading->id);
995 _cairo_output_stream_printf (surface->output,
999 num_resources = _cairo_array_num_elements (&res->xobjects);
1000 if (num_resources > 0) {
1001 _cairo_output_stream_printf (surface->output,
1004 for (i = 0; i < num_resources; i++) {
1005 xobject = _cairo_array_index (&res->xobjects, i);
1006 _cairo_output_stream_printf (surface->output,
1008 xobject->id, xobject->id);
1011 _cairo_output_stream_printf (surface->output,
1015 num_resources = _cairo_array_num_elements (&res->fonts);
1016 if (num_resources > 0) {
1017 _cairo_output_stream_printf (surface->output," /Font <<\n");
1018 for (i = 0; i < num_resources; i++) {
1019 font = _cairo_array_index (&res->fonts, i);
1020 _cairo_output_stream_printf (surface->output,
1021 " /f-%d-%d %d 0 R\n",
1024 font->subset_resource.id);
1026 _cairo_output_stream_printf (surface->output, " >>\n");
1029 _cairo_output_stream_printf (surface->output,
1033 static cairo_pdf_smask_group_t *
1034 _cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t *surface,
1035 const cairo_rectangle_int_t *extents)
1037 cairo_pdf_smask_group_t *group;
1039 group = calloc (1, sizeof (cairo_pdf_smask_group_t));
1040 if (unlikely (group == NULL)) {
1041 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1045 group->group_res = _cairo_pdf_surface_new_object (surface);
1046 if (group->group_res.id == 0) {
1047 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1051 group->width = surface->width;
1052 group->height = surface->height;
1053 if (extents != NULL) {
1054 group->extents = *extents;
1056 group->extents.x = 0;
1057 group->extents.y = 0;
1058 group->extents.width = surface->width;
1059 group->extents.height = surface->height;
1061 group->extents = *extents;
1067 _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
1069 if (group->operation == PDF_FILL || group->operation == PDF_STROKE)
1070 _cairo_path_fixed_fini (&group->path);
1072 cairo_pattern_destroy (group->source);
1074 cairo_pattern_destroy (group->mask);
1076 free (group->glyphs);
1077 free (group->clusters);
1078 if (group->scaled_font)
1079 cairo_scaled_font_destroy (group->scaled_font);
1083 static cairo_status_t
1084 _cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t *surface,
1085 cairo_pdf_smask_group_t *group)
1087 return _cairo_array_append (&surface->smask_groups, &group);
1091 _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b)
1093 const cairo_pdf_source_surface_entry_t *a = key_a;
1094 const cairo_pdf_source_surface_entry_t *b = key_b;
1096 if (a->interpolate != b->interpolate)
1099 if (a->unique_id && b->unique_id && a->unique_id_length == b->unique_id_length)
1100 return (memcmp (a->unique_id, b->unique_id, a->unique_id_length) == 0);
1102 return (a->id == b->id);
1106 _cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key)
1108 if (key->unique_id && key->unique_id_length > 0) {
1109 key->base.hash = _cairo_hash_bytes (_CAIRO_HASH_INIT_VALUE,
1110 key->unique_id, key->unique_id_length);
1112 key->base.hash = key->id;
1116 static cairo_int_status_t
1117 _cairo_pdf_surface_acquire_source_image_from_pattern (cairo_pdf_surface_t *surface,
1118 const cairo_pattern_t *pattern,
1119 const cairo_rectangle_int_t *extents,
1120 cairo_image_surface_t **image,
1123 switch (pattern->type) {
1124 case CAIRO_PATTERN_TYPE_SURFACE: {
1125 cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
1126 return _cairo_surface_acquire_source_image (surf_pat->surface, image, image_extra);
1129 case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
1130 cairo_surface_t *surf;
1131 surf = _cairo_raster_source_pattern_acquire (pattern, &surface->base, extents);
1133 return CAIRO_INT_STATUS_UNSUPPORTED;
1134 assert (cairo_surface_get_type (surf) == CAIRO_SURFACE_TYPE_IMAGE);
1135 *image = (cairo_image_surface_t *) surf;
1138 case CAIRO_PATTERN_TYPE_SOLID:
1139 case CAIRO_PATTERN_TYPE_LINEAR:
1140 case CAIRO_PATTERN_TYPE_RADIAL:
1141 case CAIRO_PATTERN_TYPE_MESH:
1147 return CAIRO_STATUS_SUCCESS;
1151 _cairo_pdf_surface_release_source_image_from_pattern (cairo_pdf_surface_t *surface,
1152 const cairo_pattern_t *pattern,
1153 cairo_image_surface_t *image,
1156 switch (pattern->type) {
1157 case CAIRO_PATTERN_TYPE_SURFACE: {
1158 cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
1159 _cairo_surface_release_source_image (surf_pat->surface, image, image_extra);
1162 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1163 _cairo_raster_source_pattern_release (pattern, &image->base);
1166 case CAIRO_PATTERN_TYPE_SOLID:
1167 case CAIRO_PATTERN_TYPE_LINEAR:
1168 case CAIRO_PATTERN_TYPE_RADIAL:
1169 case CAIRO_PATTERN_TYPE_MESH:
1177 static cairo_int_status_t
1178 _get_jpx_image_info (cairo_surface_t *source,
1179 cairo_image_info_t *info,
1180 const unsigned char **mime_data,
1181 unsigned long *mime_data_length)
1183 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
1184 mime_data, mime_data_length);
1185 if (*mime_data == NULL)
1186 return CAIRO_INT_STATUS_UNSUPPORTED;
1188 return _cairo_image_info_get_jpx_info (info, *mime_data, *mime_data_length);
1191 static cairo_int_status_t
1192 _get_jpeg_image_info (cairo_surface_t *source,
1193 cairo_image_info_t *info,
1194 const unsigned char **mime_data,
1195 unsigned long *mime_data_length)
1197 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
1198 mime_data, mime_data_length);
1199 if (*mime_data == NULL)
1200 return CAIRO_INT_STATUS_UNSUPPORTED;
1202 return _cairo_image_info_get_jpeg_info (info, *mime_data, *mime_data_length);
1205 static cairo_int_status_t
1206 _get_source_surface_size (cairo_surface_t *source,
1209 cairo_rectangle_int_t *extents)
1211 cairo_int_status_t status;
1212 cairo_image_info_t info;
1213 const unsigned char *mime_data;
1214 unsigned long mime_data_length;
1216 if (source->type == CAIRO_SURFACE_TYPE_RECORDING) {
1217 if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1218 cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
1220 *extents = sub->extents;
1221 *width = extents->width;
1222 *height = extents->height;
1224 cairo_surface_t *free_me = NULL;
1225 cairo_rectangle_int_t surf_extents;
1227 cairo_bool_t bounded;
1229 if (_cairo_surface_is_snapshot (source))
1230 free_me = source = _cairo_surface_snapshot_get_target (source);
1232 status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)source,
1234 if (unlikely (status)) {
1235 cairo_surface_destroy (free_me);
1239 bounded = _cairo_surface_get_extents (source, &surf_extents);
1240 cairo_surface_destroy (free_me);
1242 *width = surf_extents.width;
1243 *height = surf_extents.height;
1245 _cairo_box_round_to_rectangle (&box, extents);
1248 return CAIRO_STATUS_SUCCESS;
1254 status = _get_jpx_image_info (source, &info, &mime_data, &mime_data_length);
1255 if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
1256 *width = info.width;
1257 *height = info.height;
1258 extents->width = info.width;
1259 extents->height = info.height;
1263 status = _get_jpeg_image_info (source, &info, &mime_data, &mime_data_length);
1264 if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
1265 *width = info.width;
1266 *height = info.height;
1267 extents->width = info.width;
1268 extents->height = info.height;
1272 if (! _cairo_surface_get_extents (source, extents))
1273 return CAIRO_INT_STATUS_UNSUPPORTED;
1275 *width = extents->width;
1276 *height = extents->height;
1278 return CAIRO_STATUS_SUCCESS;
1282 * _cairo_pdf_surface_add_source_surface:
1283 * @surface: the pdf surface
1284 * @source_surface: A #cairo_surface_t to use as the source surface
1285 * @source_pattern: A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source
1286 * @filter: filter type of the source pattern
1287 * @stencil_mask: if true, the surface will be written to the PDF as an /ImageMask
1288 * @extents: extents of the operation that is using this source
1289 * @surface_res: return PDF resource number of the surface
1290 * @width: returns width of surface
1291 * @height: returns height of surface
1292 * @x_offset: x offset of surface
1293 * @t_offset: y offset of surface
1294 * @source_extents: returns extents of source (either ink extents or extents needed to cover @extents)
1296 * Add surface or raster_source pattern to list of surfaces to be
1297 * written to the PDF file when the current page is finished. Returns
1298 * a PDF resource to reference the image. A hash table of all images
1299 * in the PDF files (keyed by CAIRO_MIME_TYPE_UNIQUE_ID or surface
1300 * unique_id) to ensure surfaces with the same id are only written
1301 * once to the PDF file.
1303 * Only one of @source_pattern or @source_surface is to be
1304 * specified. Set the other to NULL.
1306 static cairo_status_t
1307 _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
1308 cairo_surface_t *source_surface,
1309 const cairo_pattern_t *source_pattern,
1310 cairo_filter_t filter,
1311 cairo_bool_t stencil_mask,
1312 const cairo_rectangle_int_t *extents,
1313 cairo_pdf_resource_t *surface_res,
1318 cairo_rectangle_int_t *source_extents)
1320 cairo_pdf_source_surface_t src_surface;
1321 cairo_pdf_source_surface_entry_t surface_key;
1322 cairo_pdf_source_surface_entry_t *surface_entry;
1323 cairo_status_t status;
1324 cairo_bool_t interpolate;
1325 unsigned char *unique_id;
1326 unsigned long unique_id_length = 0;
1328 cairo_rectangle_int_t rect;
1329 cairo_image_surface_t *image;
1334 case CAIRO_FILTER_GOOD:
1335 case CAIRO_FILTER_BEST:
1336 case CAIRO_FILTER_BILINEAR:
1339 case CAIRO_FILTER_FAST:
1340 case CAIRO_FILTER_NEAREST:
1341 case CAIRO_FILTER_GAUSSIAN:
1342 interpolate = FALSE;
1348 if (source_pattern) {
1349 if (source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1350 /* get the operation extents in pattern space */
1351 _cairo_box_from_rectangle (&box, extents);
1352 _cairo_matrix_transform_bounding_box_fixed (&source_pattern->matrix, &box, NULL);
1353 _cairo_box_round_to_rectangle (&box, &rect);
1354 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source_pattern,
1357 if (unlikely (status))
1359 source_surface = &image->base;
1360 cairo_surface_get_device_offset (source_surface, x_offset, y_offset);
1362 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source_pattern;
1363 source_surface = surface_pattern->surface;
1367 surface_key.id = source_surface->unique_id;
1368 surface_key.interpolate = interpolate;
1369 cairo_surface_get_mime_data (source_surface, CAIRO_MIME_TYPE_UNIQUE_ID,
1370 (const unsigned char **) &surface_key.unique_id,
1371 &surface_key.unique_id_length);
1372 _cairo_pdf_source_surface_init_key (&surface_key);
1373 surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base);
1374 if (surface_entry) {
1375 *surface_res = surface_entry->surface_res;
1376 *width = surface_entry->width;
1377 *height = surface_entry->height;
1378 *source_extents = surface_entry->extents;
1379 status = CAIRO_STATUS_SUCCESS;
1381 status = _get_source_surface_size (source_surface,
1385 if (unlikely(status))
1386 goto release_source;
1388 if (surface_key.unique_id && surface_key.unique_id_length > 0) {
1389 unique_id = _cairo_malloc (surface_key.unique_id_length);
1390 if (unique_id == NULL) {
1391 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1392 goto release_source;
1395 unique_id_length = surface_key.unique_id_length;
1396 memcpy (unique_id, surface_key.unique_id, unique_id_length);
1399 unique_id_length = 0;
1404 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1405 _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra);
1407 if (status || surface_entry)
1410 surface_entry = malloc (sizeof (cairo_pdf_source_surface_entry_t));
1411 if (surface_entry == NULL) {
1412 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1416 surface_entry->id = surface_key.id;
1417 surface_entry->interpolate = interpolate;
1418 surface_entry->stencil_mask = stencil_mask;
1419 surface_entry->unique_id_length = unique_id_length;
1420 surface_entry->unique_id = unique_id;
1421 surface_entry->width = *width;
1422 surface_entry->height = *height;
1423 surface_entry->x_offset = *x_offset;
1424 surface_entry->y_offset = *y_offset;
1425 surface_entry->extents = *source_extents;
1426 _cairo_pdf_source_surface_init_key (surface_entry);
1428 src_surface.hash_entry = surface_entry;
1429 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1430 src_surface.type = CAIRO_PATTERN_TYPE_RASTER_SOURCE;
1431 src_surface.surface = NULL;
1432 status = _cairo_pattern_create_copy (&src_surface.raster_pattern, source_pattern);
1433 if (unlikely (status))
1437 src_surface.type = CAIRO_PATTERN_TYPE_SURFACE;
1438 src_surface.surface = cairo_surface_reference (source_surface);
1439 src_surface.raster_pattern = NULL;
1442 surface_entry->surface_res = _cairo_pdf_surface_new_object (surface);
1443 if (surface_entry->surface_res.id == 0) {
1444 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1448 status = _cairo_array_append (&surface->page_surfaces, &src_surface);
1449 if (unlikely (status))
1452 status = _cairo_hash_table_insert (surface->all_surfaces,
1453 &surface_entry->base);
1454 if (unlikely(status))
1457 *surface_res = surface_entry->surface_res;
1462 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1463 cairo_pattern_destroy (src_surface.raster_pattern);
1465 cairo_surface_destroy (src_surface.surface);
1468 free (surface_entry);
1476 static cairo_status_t
1477 _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface,
1478 const cairo_pattern_t *pattern,
1479 const cairo_rectangle_int_t *extents,
1480 cairo_bool_t is_shading,
1481 cairo_pdf_resource_t *pattern_res,
1482 cairo_pdf_resource_t *gstate_res)
1484 cairo_pdf_pattern_t pdf_pattern;
1485 cairo_status_t status;
1487 pdf_pattern.is_shading = is_shading;
1489 /* Solid colors are emitted into the content stream */
1490 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
1491 pattern_res->id = 0;
1493 return CAIRO_STATUS_SUCCESS;
1496 status = _cairo_pattern_create_copy (&pdf_pattern.pattern, pattern);
1497 if (unlikely (status))
1500 pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface);
1501 if (pdf_pattern.pattern_res.id == 0) {
1502 cairo_pattern_destroy (pdf_pattern.pattern);
1503 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1506 pdf_pattern.gstate_res.id = 0;
1508 /* gradient patterns require an smask object to implement transparency */
1509 if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
1510 pattern->type == CAIRO_PATTERN_TYPE_RADIAL ||
1511 pattern->type == CAIRO_PATTERN_TYPE_MESH)
1515 _cairo_pattern_alpha_range (pattern, &min_alpha, NULL);
1516 if (! CAIRO_ALPHA_IS_OPAQUE (min_alpha)) {
1517 pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
1518 if (pdf_pattern.gstate_res.id == 0) {
1519 cairo_pattern_destroy (pdf_pattern.pattern);
1520 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1525 pdf_pattern.width = surface->width;
1526 pdf_pattern.height = surface->height;
1527 if (extents != NULL) {
1528 pdf_pattern.extents = *extents;
1530 pdf_pattern.extents.x = 0;
1531 pdf_pattern.extents.y = 0;
1532 pdf_pattern.extents.width = surface->width;
1533 pdf_pattern.extents.height = surface->height;
1536 *pattern_res = pdf_pattern.pattern_res;
1537 *gstate_res = pdf_pattern.gstate_res;
1539 status = _cairo_array_append (&surface->page_patterns, &pdf_pattern);
1540 if (unlikely (status)) {
1541 cairo_pattern_destroy (pdf_pattern.pattern);
1545 return CAIRO_STATUS_SUCCESS;
1548 /* Get BBox in PDF coordinates from extents in cairo coordinates */
1550 _get_bbox_from_extents (double surface_height,
1551 const cairo_rectangle_int_t *extents,
1552 cairo_box_double_t *bbox)
1554 bbox->p1.x = extents->x;
1555 bbox->p1.y = surface_height - (extents->y + extents->height);
1556 bbox->p2.x = extents->x + extents->width;
1557 bbox->p2.y = surface_height - extents->y;
1560 static cairo_status_t
1561 _cairo_pdf_surface_add_pdf_shading (cairo_pdf_surface_t *surface,
1562 const cairo_pattern_t *pattern,
1563 const cairo_rectangle_int_t *extents,
1564 cairo_pdf_resource_t *shading_res,
1565 cairo_pdf_resource_t *gstate_res)
1567 return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
1575 static cairo_status_t
1576 _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
1577 const cairo_pattern_t *pattern,
1578 const cairo_rectangle_int_t *extents,
1579 cairo_pdf_resource_t *pattern_res,
1580 cairo_pdf_resource_t *gstate_res)
1582 return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
1590 static cairo_status_t
1591 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
1592 cairo_pdf_resource_t *resource,
1593 cairo_bool_t compressed,
1598 cairo_pdf_resource_t self, length;
1599 cairo_output_stream_t *output = NULL;
1603 _cairo_pdf_surface_update_object (surface, self);
1605 self = _cairo_pdf_surface_new_object (surface);
1607 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1610 length = _cairo_pdf_surface_new_object (surface);
1612 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1615 output = _cairo_deflate_stream_create (surface->output);
1616 if (_cairo_output_stream_get_status (output))
1617 return _cairo_output_stream_destroy (output);
1620 surface->pdf_stream.active = TRUE;
1621 surface->pdf_stream.self = self;
1622 surface->pdf_stream.length = length;
1623 surface->pdf_stream.compressed = compressed;
1624 surface->current_pattern_is_solid_color = FALSE;
1625 surface->current_operator = CAIRO_OPERATOR_OVER;
1626 _cairo_pdf_operators_reset (&surface->pdf_operators);
1628 _cairo_output_stream_printf (surface->output,
1630 "<< /Length %d 0 R\n",
1631 surface->pdf_stream.self.id,
1632 surface->pdf_stream.length.id);
1634 _cairo_output_stream_printf (surface->output,
1635 " /Filter /FlateDecode\n");
1639 _cairo_output_stream_vprintf (surface->output, fmt, ap);
1643 _cairo_output_stream_printf (surface->output,
1647 surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
1650 assert (surface->pdf_stream.old_output == NULL);
1651 surface->pdf_stream.old_output = surface->output;
1652 surface->output = output;
1653 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1656 return _cairo_output_stream_get_status (surface->output);
1659 static cairo_status_t
1660 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
1662 cairo_status_t status;
1665 if (! surface->pdf_stream.active)
1666 return CAIRO_STATUS_SUCCESS;
1668 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1670 if (surface->pdf_stream.compressed) {
1671 cairo_status_t status2;
1673 status2 = _cairo_output_stream_destroy (surface->output);
1674 if (likely (status == CAIRO_STATUS_SUCCESS))
1677 surface->output = surface->pdf_stream.old_output;
1678 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1679 surface->pdf_stream.old_output = NULL;
1682 length = _cairo_output_stream_get_position (surface->output) -
1683 surface->pdf_stream.start_offset;
1684 _cairo_output_stream_printf (surface->output,
1689 _cairo_pdf_surface_update_object (surface,
1690 surface->pdf_stream.length);
1691 _cairo_output_stream_printf (surface->output,
1695 surface->pdf_stream.length.id,
1698 surface->pdf_stream.active = FALSE;
1700 if (likely (status == CAIRO_STATUS_SUCCESS))
1701 status = _cairo_output_stream_get_status (surface->output);
1707 _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface,
1708 cairo_output_stream_t *mem_stream,
1709 cairo_pdf_resource_t resource,
1710 cairo_pdf_group_resources_t *resources,
1711 cairo_bool_t is_knockout_group,
1712 const cairo_box_double_t *bbox)
1714 _cairo_pdf_surface_update_object (surface, resource);
1716 _cairo_output_stream_printf (surface->output,
1718 "<< /Type /XObject\n"
1721 _cairo_memory_stream_length (mem_stream));
1723 if (surface->compress_content) {
1724 _cairo_output_stream_printf (surface->output,
1725 " /Filter /FlateDecode\n");
1728 _cairo_output_stream_printf (surface->output,
1730 " /BBox [ %f %f %f %f ]\n"
1733 " /S /Transparency\n"
1735 " /CS /DeviceRGB\n",
1736 bbox->p1.x, bbox->p1.y, bbox->p2.x, bbox->p2.y);
1738 if (is_knockout_group)
1739 _cairo_output_stream_printf (surface->output,
1742 _cairo_output_stream_printf (surface->output,
1745 _cairo_pdf_surface_emit_group_resources (surface, resources);
1746 _cairo_output_stream_printf (surface->output,
1749 _cairo_memory_stream_copy (mem_stream, surface->output);
1750 _cairo_output_stream_printf (surface->output,
1755 static cairo_status_t
1756 _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
1757 const cairo_box_double_t *bbox,
1758 cairo_pdf_resource_t *resource)
1760 cairo_status_t status;
1762 assert (surface->pdf_stream.active == FALSE);
1763 assert (surface->group_stream.active == FALSE);
1765 surface->group_stream.active = TRUE;
1766 surface->current_pattern_is_solid_color = FALSE;
1767 surface->current_operator = CAIRO_OPERATOR_OVER;
1768 _cairo_pdf_operators_reset (&surface->pdf_operators);
1770 surface->group_stream.mem_stream = _cairo_memory_stream_create ();
1772 if (surface->compress_content) {
1773 surface->group_stream.stream =
1774 _cairo_deflate_stream_create (surface->group_stream.mem_stream);
1776 surface->group_stream.stream = surface->group_stream.mem_stream;
1778 status = _cairo_output_stream_get_status (surface->group_stream.stream);
1780 surface->group_stream.old_output = surface->output;
1781 surface->output = surface->group_stream.stream;
1782 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1783 _cairo_pdf_group_resources_clear (&surface->resources);
1786 surface->group_stream.resource = *resource;
1788 surface->group_stream.resource = _cairo_pdf_surface_new_object (surface);
1789 if (surface->group_stream.resource.id == 0)
1790 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1792 surface->group_stream.is_knockout = FALSE;
1793 surface->group_stream.bbox = *bbox;
1798 static cairo_status_t
1799 _cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface,
1800 const cairo_box_double_t *bbox)
1802 cairo_status_t status;
1804 status = _cairo_pdf_surface_open_group (surface, bbox, NULL);
1805 if (unlikely (status))
1808 surface->group_stream.is_knockout = TRUE;
1810 return CAIRO_STATUS_SUCCESS;
1813 static cairo_status_t
1814 _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
1815 cairo_pdf_resource_t *group)
1817 cairo_status_t status = CAIRO_STATUS_SUCCESS, status2;
1819 assert (surface->pdf_stream.active == FALSE);
1820 assert (surface->group_stream.active == TRUE);
1822 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1823 if (unlikely (status))
1826 if (surface->compress_content) {
1827 status = _cairo_output_stream_destroy (surface->group_stream.stream);
1828 surface->group_stream.stream = NULL;
1830 _cairo_output_stream_printf (surface->group_stream.mem_stream,
1833 surface->output = surface->group_stream.old_output;
1834 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1835 surface->group_stream.active = FALSE;
1836 _cairo_pdf_surface_write_memory_stream (surface,
1837 surface->group_stream.mem_stream,
1838 surface->group_stream.resource,
1839 &surface->resources,
1840 surface->group_stream.is_knockout,
1841 &surface->group_stream.bbox);
1843 *group = surface->group_stream.resource;
1845 status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
1846 if (status == CAIRO_STATUS_SUCCESS)
1849 surface->group_stream.mem_stream = NULL;
1850 surface->group_stream.stream = NULL;
1855 static cairo_status_t
1856 _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
1857 const cairo_box_double_t *bbox,
1858 cairo_pdf_resource_t *resource,
1859 cairo_bool_t is_form)
1861 cairo_status_t status;
1863 assert (surface->pdf_stream.active == FALSE);
1864 assert (surface->group_stream.active == FALSE);
1866 surface->content_resources = _cairo_pdf_surface_new_object (surface);
1867 if (surface->content_resources.id == 0)
1868 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1871 assert (bbox != NULL);
1874 _cairo_pdf_surface_open_stream (surface,
1876 surface->compress_content,
1879 " /BBox [ %f %f %f %f ]\n"
1882 " /S /Transparency\n"
1886 " /Resources %d 0 R\n",
1891 surface->content_resources.id);
1894 _cairo_pdf_surface_open_stream (surface,
1896 surface->compress_content,
1899 if (unlikely (status))
1902 surface->content = surface->pdf_stream.self;
1904 _cairo_output_stream_printf (surface->output, "q\n");
1906 return _cairo_output_stream_get_status (surface->output);
1909 static cairo_status_t
1910 _cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
1912 cairo_status_t status;
1914 assert (surface->pdf_stream.active == TRUE);
1915 assert (surface->group_stream.active == FALSE);
1917 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1918 if (unlikely (status))
1921 _cairo_output_stream_printf (surface->output, "Q\n");
1922 status = _cairo_pdf_surface_close_stream (surface);
1923 if (unlikely (status))
1926 _cairo_pdf_surface_update_object (surface, surface->content_resources);
1927 _cairo_output_stream_printf (surface->output,
1929 surface->content_resources.id);
1930 _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
1931 _cairo_output_stream_printf (surface->output,
1934 return _cairo_output_stream_get_status (surface->output);
1938 _cairo_pdf_source_surface_entry_pluck (void *entry, void *closure)
1940 cairo_pdf_source_surface_entry_t *surface_entry = entry;
1941 cairo_hash_table_t *patterns = closure;
1943 _cairo_hash_table_remove (patterns, &surface_entry->base);
1944 free (surface_entry->unique_id);
1946 free (surface_entry);
1949 static cairo_status_t
1950 _cairo_pdf_surface_finish (void *abstract_surface)
1952 cairo_pdf_surface_t *surface = abstract_surface;
1954 cairo_pdf_resource_t info, catalog;
1955 cairo_status_t status, status2;
1957 status = surface->base.status;
1958 if (status == CAIRO_STATUS_SUCCESS)
1959 status = _cairo_pdf_surface_emit_font_subsets (surface);
1961 _cairo_pdf_surface_write_pages (surface);
1963 info = _cairo_pdf_surface_write_info (surface);
1964 if (info.id == 0 && status == CAIRO_STATUS_SUCCESS)
1965 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1967 catalog = _cairo_pdf_surface_write_catalog (surface);
1968 if (catalog.id == 0 && status == CAIRO_STATUS_SUCCESS)
1969 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1971 offset = _cairo_pdf_surface_write_xref (surface);
1973 _cairo_output_stream_printf (surface->output,
1979 surface->next_available_resource.id,
1983 _cairo_output_stream_printf (surface->output,
1989 /* pdf_operators has already been flushed when the last stream was
1990 * closed so we should never be writing anything here - however,
1991 * the stream may itself be in an error state. */
1992 status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
1993 if (status == CAIRO_STATUS_SUCCESS)
1996 /* close any active streams still open due to fatal errors */
1997 status2 = _cairo_pdf_surface_close_stream (surface);
1998 if (status == CAIRO_STATUS_SUCCESS)
2001 if (surface->group_stream.stream != NULL) {
2002 status2 = _cairo_output_stream_destroy (surface->group_stream.stream);
2003 if (status == CAIRO_STATUS_SUCCESS)
2006 if (surface->group_stream.mem_stream != NULL) {
2007 status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
2008 if (status == CAIRO_STATUS_SUCCESS)
2011 if (surface->pdf_stream.active)
2012 surface->output = surface->pdf_stream.old_output;
2013 if (surface->group_stream.active)
2014 surface->output = surface->group_stream.old_output;
2016 /* and finish the pdf surface */
2017 status2 = _cairo_output_stream_destroy (surface->output);
2018 if (status == CAIRO_STATUS_SUCCESS)
2021 _cairo_pdf_surface_clear (surface);
2022 _cairo_pdf_group_resources_fini (&surface->resources);
2024 _cairo_array_fini (&surface->objects);
2025 _cairo_array_fini (&surface->pages);
2026 _cairo_array_fini (&surface->rgb_linear_functions);
2027 _cairo_array_fini (&surface->alpha_linear_functions);
2028 _cairo_array_fini (&surface->page_patterns);
2029 _cairo_array_fini (&surface->page_surfaces);
2030 _cairo_hash_table_foreach (surface->all_surfaces,
2031 _cairo_pdf_source_surface_entry_pluck,
2032 surface->all_surfaces);
2033 _cairo_hash_table_destroy (surface->all_surfaces);
2034 _cairo_array_fini (&surface->smask_groups);
2035 _cairo_array_fini (&surface->fonts);
2036 _cairo_array_fini (&surface->knockout_group);
2038 if (surface->font_subsets) {
2039 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
2040 surface->font_subsets = NULL;
2043 _cairo_surface_clipper_reset (&surface->clipper);
2048 static cairo_int_status_t
2049 _cairo_pdf_surface_start_page (void *abstract_surface)
2051 cairo_pdf_surface_t *surface = abstract_surface;
2053 /* Document header */
2054 if (! surface->header_emitted) {
2055 const char *version;
2057 switch (surface->pdf_version) {
2058 case CAIRO_PDF_VERSION_1_4:
2062 case CAIRO_PDF_VERSION_1_5:
2067 _cairo_output_stream_printf (surface->output,
2068 "%%PDF-%s\n", version);
2069 _cairo_output_stream_printf (surface->output,
2070 "%%%c%c%c%c\n", 181, 237, 174, 251);
2071 surface->header_emitted = TRUE;
2074 _cairo_pdf_group_resources_clear (&surface->resources);
2076 return CAIRO_STATUS_SUCCESS;
2079 static cairo_int_status_t
2080 _cairo_pdf_surface_has_fallback_images (void *abstract_surface,
2081 cairo_bool_t has_fallbacks)
2083 cairo_status_t status;
2084 cairo_pdf_surface_t *surface = abstract_surface;
2085 cairo_box_double_t bbox;
2087 surface->has_fallback_images = has_fallbacks;
2090 bbox.p2.x = surface->width;
2091 bbox.p2.y = surface->height;
2092 status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, has_fallbacks);
2093 if (unlikely (status))
2096 return CAIRO_STATUS_SUCCESS;
2100 _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
2105 static cairo_status_t
2106 _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surface,
2107 const cairo_pattern_t *source,
2108 const cairo_rectangle_int_t *extents,
2109 cairo_pdf_resource_t *surface_res,
2115 cairo_image_surface_t *image;
2116 cairo_surface_t *pad_image;
2118 cairo_int_status_t status;
2120 cairo_rectangle_int_t extents2;
2122 cairo_rectangle_int_t rect;
2123 cairo_surface_pattern_t pad_pattern;
2125 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source, extents,
2126 &image, &image_extra);
2127 if (unlikely (status))
2130 pad_image = &image->base;
2132 /* get the operation extents in pattern space */
2133 _cairo_box_from_rectangle (&box, extents);
2134 _cairo_matrix_transform_bounding_box_fixed (&source->matrix, &box, NULL);
2135 _cairo_box_round_to_rectangle (&box, &rect);
2137 /* Check if image needs padding to fill extents */
2140 if (_cairo_fixed_integer_ceil(box.p1.x) < 0 ||
2141 _cairo_fixed_integer_ceil(box.p1.y) < 0 ||
2142 _cairo_fixed_integer_floor(box.p2.y) > w ||
2143 _cairo_fixed_integer_floor(box.p2.y) > h)
2145 pad_image = _cairo_image_surface_create_with_content (cairo_surface_get_content (&image->base),
2148 if (pad_image->status) {
2149 status = pad_image->status;
2153 _cairo_pattern_init_for_surface (&pad_pattern, &image->base);
2154 cairo_matrix_init_translate (&pad_pattern.base.matrix, rect.x, rect.y);
2155 pad_pattern.base.extend = CAIRO_EXTEND_PAD;
2156 status = _cairo_surface_paint (pad_image,
2157 CAIRO_OPERATOR_SOURCE, &pad_pattern.base,
2159 _cairo_pattern_fini (&pad_pattern.base);
2160 if (unlikely (status))
2163 cairo_surface_set_device_offset (pad_image, rect.x, rect.y);
2166 status = _cairo_pdf_surface_add_source_surface (surface,
2178 if (unlikely (status))
2182 if (pad_image != &image->base)
2183 cairo_surface_destroy (pad_image);
2185 _cairo_pdf_surface_release_source_image_from_pattern (surface, source, image, image_extra);
2190 /* Emit alpha channel from the image into the given data, providing
2191 * an id that can be used to reference the resulting SMask object.
2193 * In the case that the alpha channel happens to be all opaque, then
2194 * no SMask object will be emitted and *id_ret will be set to 0.
2196 * When stencil_mask is TRUE, stream_res is an an input specifying the
2197 * resource to use. When stencil_mask is FALSE, a new resource will be
2198 * created and returned in stream_res.
2200 static cairo_status_t
2201 _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
2202 cairo_image_surface_t *image,
2203 cairo_bool_t stencil_mask,
2204 const char *interpolate,
2205 cairo_pdf_resource_t *stream_res)
2207 cairo_status_t status = CAIRO_STATUS_SUCCESS;
2209 unsigned long alpha_size;
2212 int i, x, y, bit, a;
2213 cairo_image_transparency_t transparency;
2215 /* This is the only image format we support, which simplifies things. */
2216 assert (image->format == CAIRO_FORMAT_ARGB32 ||
2217 image->format == CAIRO_FORMAT_A8 ||
2218 image->format == CAIRO_FORMAT_A1 );
2220 transparency = _cairo_image_analyze_transparency (image);
2222 assert (transparency == CAIRO_IMAGE_IS_OPAQUE ||
2223 transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA);
2225 if (transparency == CAIRO_IMAGE_IS_OPAQUE)
2229 if (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA) {
2230 alpha_size = (image->width + 7) / 8 * image->height;
2231 alpha = _cairo_malloc_ab ((image->width+7) / 8, image->height);
2233 alpha_size = image->height * image->width;
2234 alpha = _cairo_malloc_ab (image->height, image->width);
2237 if (unlikely (alpha == NULL)) {
2238 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2243 for (y = 0; y < image->height; y++) {
2244 if (image->format == CAIRO_FORMAT_A1) {
2245 pixel8 = (uint8_t *) (image->data + y * image->stride);
2247 for (x = 0; x < (image->width + 7) / 8; x++, pixel8++) {
2249 a = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a);
2253 pixel8 = (uint8_t *) (image->data + y * image->stride);
2254 pixel32 = (uint32_t *) (image->data + y * image->stride);
2256 for (x = 0; x < image->width; x++) {
2257 if (image->format == CAIRO_FORMAT_ARGB32) {
2258 a = (*pixel32 & 0xff000000) >> 24;
2265 if (transparency == CAIRO_IMAGE_HAS_ALPHA) {
2267 } else { /* transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA or CAIRO_IMAGE_IS_OPAQUE */
2271 alpha[i] |= (1 << bit);
2285 status = _cairo_pdf_surface_open_stream (surface,
2289 " /Subtype /Image\n"
2290 " /ImageMask true\n"
2293 " /Interpolate %s\n"
2294 " /BitsPerComponent 1\n"
2296 image->width, image->height, interpolate);
2299 status = _cairo_pdf_surface_open_stream (surface,
2303 " /Subtype /Image\n"
2306 " /ColorSpace /DeviceGray\n"
2307 " /Interpolate %s\n"
2308 " /BitsPerComponent %d\n",
2309 image->width, image->height, interpolate,
2310 transparency == CAIRO_IMAGE_HAS_ALPHA ? 8 : 1);
2312 if (unlikely (status))
2316 *stream_res = surface->pdf_stream.self;
2318 _cairo_output_stream_write (surface->output, alpha, alpha_size);
2319 status = _cairo_pdf_surface_close_stream (surface);
2327 /* Emit image data into the given surface, providing a resource that
2328 * can be used to reference the data in image_ret. */
2329 static cairo_status_t
2330 _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
2331 cairo_image_surface_t *image_surf,
2332 cairo_pdf_resource_t *image_res,
2333 cairo_filter_t filter,
2334 cairo_bool_t stencil_mask)
2336 cairo_status_t status = CAIRO_STATUS_SUCCESS;
2338 unsigned long data_size;
2341 cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
2342 cairo_bool_t need_smask;
2343 const char *interpolate = "true";
2344 cairo_image_color_t color;
2345 cairo_image_surface_t *image;
2348 if (image->format != CAIRO_FORMAT_RGB24 &&
2349 image->format != CAIRO_FORMAT_ARGB32 &&
2350 image->format != CAIRO_FORMAT_A8 &&
2351 image->format != CAIRO_FORMAT_A1)
2353 cairo_surface_t *surf;
2354 cairo_surface_pattern_t pattern;
2356 surf = _cairo_image_surface_create_with_content (cairo_surface_get_content (&image_surf->base),
2358 image_surf->height);
2359 image = (cairo_image_surface_t *) surf;
2361 status = surf->status;
2365 _cairo_pattern_init_for_surface (&pattern, &image_surf->base);
2366 status = _cairo_surface_paint (surf,
2367 CAIRO_OPERATOR_SOURCE, &pattern.base,
2369 _cairo_pattern_fini (&pattern.base);
2370 if (unlikely (status))
2375 case CAIRO_FILTER_GOOD:
2376 case CAIRO_FILTER_BEST:
2377 case CAIRO_FILTER_BILINEAR:
2378 interpolate = "true";
2380 case CAIRO_FILTER_FAST:
2381 case CAIRO_FILTER_NEAREST:
2382 case CAIRO_FILTER_GAUSSIAN:
2383 interpolate = "false";
2388 return _cairo_pdf_surface_emit_smask (surface, image, stencil_mask, interpolate, image_res);
2390 color = _cairo_image_analyze_color (image);
2392 case CAIRO_IMAGE_IS_COLOR:
2393 case CAIRO_IMAGE_UNKNOWN_COLOR:
2394 data_size = image->height * image->width * 3;
2395 data = _cairo_malloc_abc (image->width, image->height, 3);
2398 case CAIRO_IMAGE_IS_GRAYSCALE:
2399 data_size = image->height * image->width;
2400 data = _cairo_malloc_ab (image->width, image->height);
2402 case CAIRO_IMAGE_IS_MONOCHROME:
2403 data_size = (image->width + 7) / 8 * image->height;
2404 data = _cairo_malloc_ab ((image->width+7) / 8, image->height);
2407 if (unlikely (data == NULL)) {
2408 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2413 for (y = 0; y < image->height; y++) {
2414 pixel = (uint32_t *) (image->data + y * image->stride);
2417 for (x = 0; x < image->width; x++, pixel++) {
2420 /* XXX: We're un-premultiplying alpha here. My reading of the PDF
2421 * specification suggests that we should be able to avoid having
2422 * to do this by filling in the SMask's Matte dictionary
2423 * appropriately, but my attempts to do that so far have
2425 if (image->format == CAIRO_FORMAT_ARGB32) {
2427 a = (*pixel & 0xff000000) >> 24;
2431 r = (((*pixel & 0xff0000) >> 16) * 255 + a / 2) / a;
2432 g = (((*pixel & 0x00ff00) >> 8) * 255 + a / 2) / a;
2433 b = (((*pixel & 0x0000ff) >> 0) * 255 + a / 2) / a;
2435 } else if (image->format == CAIRO_FORMAT_RGB24) {
2436 r = (*pixel & 0x00ff0000) >> 16;
2437 g = (*pixel & 0x0000ff00) >> 8;
2438 b = (*pixel & 0x000000ff) >> 0;
2444 case CAIRO_IMAGE_IS_COLOR:
2445 case CAIRO_IMAGE_UNKNOWN_COLOR:
2451 case CAIRO_IMAGE_IS_GRAYSCALE:
2455 case CAIRO_IMAGE_IS_MONOCHROME:
2459 data[i] |= (1 << bit);
2473 if (image->format == CAIRO_FORMAT_ARGB32 ||
2474 image->format == CAIRO_FORMAT_A8 ||
2475 image->format == CAIRO_FORMAT_A1) {
2476 status = _cairo_pdf_surface_emit_smask (surface, image, FALSE, interpolate, &smask);
2477 if (unlikely (status))
2484 #define IMAGE_DICTIONARY " /Type /XObject\n" \
2485 " /Subtype /Image\n" \
2488 " /ColorSpace %s\n" \
2489 " /Interpolate %s\n" \
2490 " /BitsPerComponent %d\n"
2493 status = _cairo_pdf_surface_open_stream (surface,
2498 image->width, image->height,
2499 color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray",
2501 color == CAIRO_IMAGE_IS_MONOCHROME? 1 : 8,
2504 status = _cairo_pdf_surface_open_stream (surface,
2508 image->width, image->height,
2509 color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray",
2511 color == CAIRO_IMAGE_IS_MONOCHROME? 1 : 8);
2512 if (unlikely (status))
2515 #undef IMAGE_DICTIONARY
2517 _cairo_output_stream_write (surface->output, data, data_size);
2518 status = _cairo_pdf_surface_close_stream (surface);
2523 if (image != image_surf)
2524 cairo_surface_destroy (&image->base);
2529 static cairo_int_status_t
2530 _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface,
2531 cairo_surface_t *source,
2532 cairo_pdf_resource_t res)
2534 cairo_status_t status;
2535 const unsigned char *mime_data;
2536 unsigned long mime_data_length;
2537 cairo_image_info_t info;
2539 if (surface->pdf_version < CAIRO_PDF_VERSION_1_5)
2540 return CAIRO_INT_STATUS_UNSUPPORTED;
2542 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
2543 &mime_data, &mime_data_length);
2544 if (mime_data == NULL)
2545 return CAIRO_INT_STATUS_UNSUPPORTED;
2547 status = _cairo_image_info_get_jpx_info (&info, mime_data, mime_data_length);
2551 status = _cairo_pdf_surface_open_stream (surface,
2555 " /Subtype /Image\n"
2558 " /Filter /JPXDecode\n",
2564 _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
2565 status = _cairo_pdf_surface_close_stream (surface);
2570 static cairo_int_status_t
2571 _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
2572 cairo_surface_t *source,
2573 cairo_pdf_resource_t res)
2575 cairo_status_t status;
2576 const unsigned char *mime_data;
2577 unsigned long mime_data_length;
2578 cairo_image_info_t info;
2579 const char *colorspace;
2581 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
2582 &mime_data, &mime_data_length);
2583 if (unlikely (source->status))
2584 return source->status;
2585 if (mime_data == NULL)
2586 return CAIRO_INT_STATUS_UNSUPPORTED;
2588 status = _cairo_image_info_get_jpeg_info (&info, mime_data, mime_data_length);
2589 if (unlikely (status))
2592 switch (info.num_components) {
2594 colorspace = "/DeviceGray";
2597 colorspace = "/DeviceRGB";
2600 colorspace = "/DeviceCMYK";
2603 return CAIRO_INT_STATUS_UNSUPPORTED;
2606 status = _cairo_pdf_surface_open_stream (surface,
2610 " /Subtype /Image\n"
2614 " /BitsPerComponent %d\n"
2615 " /Filter /DCTDecode\n",
2619 info.bits_per_component);
2620 if (unlikely (status))
2623 _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
2624 status = _cairo_pdf_surface_close_stream (surface);
2629 static cairo_status_t
2630 _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
2631 cairo_pdf_source_surface_t *source)
2633 cairo_image_surface_t *image;
2635 cairo_int_status_t status;
2637 if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
2638 status = _cairo_surface_acquire_source_image (source->surface, &image, &image_extra);
2640 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source->raster_pattern,
2641 &source->hash_entry->extents,
2642 &image, &image_extra);
2644 if (unlikely (status))
2647 if (!source->hash_entry->stencil_mask) {
2648 status = _cairo_pdf_surface_emit_jpx_image (surface, &image->base, source->hash_entry->surface_res);
2649 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2650 goto release_source;
2652 status = _cairo_pdf_surface_emit_jpeg_image (surface, &image->base, source->hash_entry->surface_res);
2653 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2654 goto release_source;
2657 status = _cairo_pdf_surface_emit_image (surface, image,
2658 &source->hash_entry->surface_res,
2659 source->hash_entry->interpolate,
2660 source->hash_entry->stencil_mask);
2663 if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
2664 _cairo_surface_release_source_image (source->surface, image, image_extra);
2666 _cairo_pdf_surface_release_source_image_from_pattern (surface, source->raster_pattern,
2667 image, image_extra);
2672 static cairo_status_t
2673 _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
2674 cairo_pdf_source_surface_t *pdf_source)
2676 double old_width, old_height;
2677 cairo_paginated_mode_t old_paginated_mode;
2678 cairo_surface_clipper_t old_clipper;
2679 cairo_box_double_t bbox;
2680 cairo_int_status_t status;
2682 cairo_surface_t *free_me = NULL;
2683 cairo_surface_t *source;
2685 assert (pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE);
2686 source = pdf_source->surface;
2687 if (_cairo_surface_is_snapshot (source))
2688 free_me = source = _cairo_surface_snapshot_get_target (source);
2690 old_width = surface->width;
2691 old_height = surface->height;
2692 old_paginated_mode = surface->paginated_mode;
2693 old_clipper = surface->clipper;
2694 _cairo_surface_clipper_init (&surface->clipper,
2695 _cairo_pdf_surface_clipper_intersect_clip_path);
2697 _cairo_pdf_surface_set_size_internal (surface,
2698 pdf_source->hash_entry->width,
2699 pdf_source->hash_entry->height);
2700 /* Patterns are emitted after fallback images. The paginated mode
2701 * needs to be set to _RENDER while the recording surface is replayed
2702 * back to this surface.
2704 surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
2705 _cairo_pdf_group_resources_clear (&surface->resources);
2706 _get_bbox_from_extents (pdf_source->hash_entry->height, &pdf_source->hash_entry->extents, &bbox);
2707 status = _cairo_pdf_surface_open_content_stream (surface, &bbox, &pdf_source->hash_entry->surface_res, TRUE);
2708 if (unlikely (status))
2711 if (cairo_surface_get_content (source) == CAIRO_CONTENT_COLOR) {
2712 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
2713 if (unlikely (status))
2716 _cairo_output_stream_printf (surface->output,
2717 "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
2723 status = _cairo_recording_surface_replay_region (source,
2726 CAIRO_RECORDING_REGION_NATIVE);
2727 assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
2728 if (unlikely (status))
2731 status = _cairo_pdf_surface_close_content_stream (surface);
2733 _cairo_surface_clipper_reset (&surface->clipper);
2734 surface->clipper = old_clipper;
2735 _cairo_pdf_surface_set_size_internal (surface,
2738 surface->paginated_mode = old_paginated_mode;
2741 cairo_surface_destroy (free_me);
2745 static cairo_status_t
2746 _cairo_pdf_surface_emit_recording_subsurface (cairo_pdf_surface_t *surface,
2747 cairo_surface_t *recording_surface,
2748 const cairo_rectangle_int_t *extents,
2749 cairo_pdf_resource_t resource)
2751 double old_width, old_height;
2752 cairo_paginated_mode_t old_paginated_mode;
2753 cairo_surface_clipper_t old_clipper;
2754 cairo_box_double_t bbox;
2755 cairo_int_status_t status;
2758 old_width = surface->width;
2759 old_height = surface->height;
2760 old_paginated_mode = surface->paginated_mode;
2761 old_clipper = surface->clipper;
2762 _cairo_surface_clipper_init (&surface->clipper,
2763 _cairo_pdf_surface_clipper_intersect_clip_path);
2765 _cairo_pdf_surface_set_size_internal (surface,
2768 /* Patterns are emitted after fallback images. The paginated mode
2769 * needs to be set to _RENDER while the recording surface is replayed
2770 * back to this surface.
2772 surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
2773 _cairo_pdf_group_resources_clear (&surface->resources);
2774 _get_bbox_from_extents (extents->height, extents, &bbox);
2775 status = _cairo_pdf_surface_open_content_stream (surface, &bbox, &resource, TRUE);
2776 if (unlikely (status))
2779 if (cairo_surface_get_content (recording_surface) == CAIRO_CONTENT_COLOR) {
2780 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
2781 if (unlikely (status))
2784 _cairo_output_stream_printf (surface->output,
2785 "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
2791 status = _cairo_recording_surface_replay_region (recording_surface,
2794 CAIRO_RECORDING_REGION_NATIVE);
2795 assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
2796 if (unlikely (status))
2799 status = _cairo_pdf_surface_close_content_stream (surface);
2801 _cairo_surface_clipper_reset (&surface->clipper);
2802 surface->clipper = old_clipper;
2803 _cairo_pdf_surface_set_size_internal (surface,
2806 surface->paginated_mode = old_paginated_mode;
2811 static cairo_status_t
2812 _cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface,
2813 cairo_pdf_source_surface_t *src_surface)
2815 if (src_surface->type == CAIRO_PATTERN_TYPE_SURFACE) {
2816 if (src_surface->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
2817 if (src_surface->surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
2818 cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) src_surface->surface;
2819 return _cairo_pdf_surface_emit_recording_subsurface (surface,
2822 src_surface->hash_entry->surface_res);
2824 return _cairo_pdf_surface_emit_recording_surface (surface,
2829 return _cairo_pdf_surface_emit_image_surface (surface, src_surface);
2832 static cairo_status_t
2833 _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
2834 cairo_pdf_pattern_t *pdf_pattern)
2836 cairo_pattern_t *pattern = pdf_pattern->pattern;
2837 cairo_status_t status;
2838 cairo_pdf_resource_t pattern_resource = {0};
2839 cairo_matrix_t cairo_p2d, pdf_p2d;
2840 cairo_extend_t extend = cairo_pattern_get_extend (pattern);
2841 double xstep, ystep;
2842 cairo_rectangle_int_t pattern_extents;
2843 int pattern_width = 0; /* squelch bogus compiler warning */
2844 int pattern_height = 0; /* squelch bogus compiler warning */
2847 char draw_surface[200];
2848 cairo_box_double_t bbox;
2850 if (pattern->extend == CAIRO_EXTEND_PAD) {
2851 status = _cairo_pdf_surface_add_padded_image_surface (surface,
2853 &pdf_pattern->extents,
2859 pattern_extents.x = 0;
2860 pattern_extents.y = 0;
2861 pattern_extents.width = pattern_width;
2862 pattern_extents.height = pattern_height;
2864 status = _cairo_pdf_surface_add_source_surface (surface,
2869 &pdf_pattern->extents,
2877 if (unlikely (status))
2881 case CAIRO_EXTEND_PAD:
2882 case CAIRO_EXTEND_NONE:
2884 /* In PS/PDF, (as far as I can tell), all patterns are
2885 * repeating. So we support cairo's EXTEND_NONE semantics
2886 * by setting the repeat step size to a size large enough
2887 * to guarantee that no more than a single occurrence will
2890 * First, map the surface extents into pattern space (since
2891 * xstep and ystep are in pattern space). Then use an upper
2892 * bound on the length of the diagonal of the pattern image
2893 * and the surface as repeat size. This guarantees to never
2896 double x1 = 0.0, y1 = 0.0;
2897 double x2 = surface->width, y2 = surface->height;
2898 _cairo_matrix_transform_bounding_box (&pattern->matrix,
2902 /* Rather than computing precise bounds of the union, just
2903 * add the surface extents unconditionally. We only
2904 * required an answer that's large enough, we don't really
2905 * care if it's not as tight as possible.*/
2906 xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
2907 pattern_width + pattern_height);
2910 case CAIRO_EXTEND_REPEAT:
2911 xstep = pattern_width;
2912 ystep = pattern_height;
2914 case CAIRO_EXTEND_REFLECT:
2915 pattern_extents.x = 0;
2916 pattern_extents.y = 0;
2917 pattern_extents.width = pattern_width*2;
2918 pattern_extents.height = pattern_height*2;
2919 xstep = pattern_width*2;
2920 ystep = pattern_height*2;
2922 /* All the rest (if any) should have been analyzed away, so this
2923 * case should be unreachable. */
2930 /* At this point, (that is, within the surface backend interface),
2931 * the pattern's matrix maps from cairo's device space to cairo's
2932 * pattern space, (both with their origin at the upper-left, and
2933 * cairo's pattern space of size width,height).
2935 * Then, we must emit a PDF pattern object that maps from its own
2936 * pattern space, (which has a size that we establish in the BBox
2937 * dictionary entry), to the PDF page's *initial* space, (which
2938 * does not benefit from the Y-axis flipping matrix that we emit
2939 * on each page). So the PDF patterns matrix maps from a
2940 * (width,height) pattern space to a device space with the origin
2941 * in the lower-left corner.
2943 * So to handle all of that, we start with an identity matrix for
2944 * the PDF pattern to device matrix. We translate it up by the
2945 * image height then flip it in the Y direction, (moving us from
2946 * the PDF origin to cairo's origin). We then multiply in the
2947 * inverse of the cairo pattern matrix, (since it maps from device
2948 * to pattern, while we're setting up pattern to device). Finally,
2949 * we translate back down by the image height and flip again to
2950 * end up at the lower-left origin that PDF expects.
2952 * Additionally, within the stream that paints the pattern itself,
2953 * we are using a PDF image object that has a size of (1,1) so we
2954 * have to scale it up by the image width and height to fill our
2957 cairo_p2d = pattern->matrix;
2958 status = cairo_matrix_invert (&cairo_p2d);
2959 /* cairo_pattern_set_matrix ensures the matrix is invertible */
2960 assert (status == CAIRO_STATUS_SUCCESS);
2962 cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &surface->cairo_to_pdf);
2963 cairo_matrix_translate (&pdf_p2d, -x_offset, -y_offset);
2964 cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
2965 cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
2967 _get_bbox_from_extents (pattern_height, &pattern_extents, &bbox);
2968 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
2969 status = _cairo_pdf_surface_open_stream (surface,
2970 &pdf_pattern->pattern_res,
2973 " /BBox [ %f %f %f %f ]\n"
2978 " /Matrix [ %f %f %f %f %f %f ]\n"
2979 " /Resources << /XObject << /x%d %d 0 R >> >>\n",
2980 bbox.p1.x, bbox.p1.y, bbox.p2.x, bbox.p2.y,
2982 pdf_p2d.xx, pdf_p2d.yx,
2983 pdf_p2d.xy, pdf_p2d.yy,
2984 pdf_p2d.x0, pdf_p2d.y0,
2985 pattern_resource.id,
2986 pattern_resource.id);
2987 if (unlikely (status))
2990 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
2991 ((cairo_surface_pattern_t *) pattern)->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
2992 snprintf(draw_surface,
2993 sizeof (draw_surface),
2995 pattern_resource.id);
2997 snprintf(draw_surface,
2998 sizeof (draw_surface),
2999 "q %d 0 0 %d 0 0 cm /x%d Do Q",
3002 pattern_resource.id);
3005 if (extend == CAIRO_EXTEND_REFLECT) {
3006 _cairo_output_stream_printf (surface->output,
3007 "q 0 0 %d %d re W n %s Q\n"
3008 "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n %s Q\n"
3009 "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n %s Q\n"
3010 "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n %s Q\n",
3011 pattern_width, pattern_height,
3013 pattern_width*2, pattern_width, pattern_height,
3015 pattern_height*2, pattern_width, pattern_height,
3017 pattern_width*2, pattern_height*2, pattern_width, pattern_height,
3020 _cairo_output_stream_printf (surface->output,
3025 status = _cairo_pdf_surface_close_stream (surface);
3026 if (unlikely (status))
3029 return _cairo_output_stream_get_status (surface->output);
3032 typedef struct _cairo_pdf_color_stop {
3035 cairo_pdf_resource_t resource;
3036 } cairo_pdf_color_stop_t;
3038 static cairo_status_t
3039 cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t *surface,
3040 cairo_pdf_color_stop_t *stop1,
3041 cairo_pdf_color_stop_t *stop2,
3042 cairo_pdf_resource_t *function)
3045 cairo_pdf_rgb_linear_function_t elem;
3046 cairo_pdf_resource_t res;
3047 cairo_status_t status;
3049 num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions);
3050 for (i = 0; i < num_elems; i++) {
3051 _cairo_array_copy_element (&surface->rgb_linear_functions, i, &elem);
3052 if (memcmp (&elem.color1[0], &stop1->color[0], sizeof (double)*3) != 0)
3054 if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0)
3056 *function = elem.resource;
3057 return CAIRO_STATUS_SUCCESS;
3060 res = _cairo_pdf_surface_new_object (surface);
3062 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3064 _cairo_output_stream_printf (surface->output,
3066 "<< /FunctionType 2\n"
3067 " /Domain [ 0 1 ]\n"
3068 " /C0 [ %f %f %f ]\n"
3069 " /C1 [ %f %f %f ]\n"
3081 elem.resource = res;
3082 memcpy (&elem.color1[0], &stop1->color[0], sizeof (double)*3);
3083 memcpy (&elem.color2[0], &stop2->color[0], sizeof (double)*3);
3085 status = _cairo_array_append (&surface->rgb_linear_functions, &elem);
3091 static cairo_status_t
3092 cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t *surface,
3093 cairo_pdf_color_stop_t *stop1,
3094 cairo_pdf_color_stop_t *stop2,
3095 cairo_pdf_resource_t *function)
3098 cairo_pdf_alpha_linear_function_t elem;
3099 cairo_pdf_resource_t res;
3100 cairo_status_t status;
3102 num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions);
3103 for (i = 0; i < num_elems; i++) {
3104 _cairo_array_copy_element (&surface->alpha_linear_functions, i, &elem);
3105 if (elem.alpha1 != stop1->color[3])
3107 if (elem.alpha2 != stop2->color[3])
3109 *function = elem.resource;
3110 return CAIRO_STATUS_SUCCESS;
3113 res = _cairo_pdf_surface_new_object (surface);
3115 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3117 _cairo_output_stream_printf (surface->output,
3119 "<< /FunctionType 2\n"
3120 " /Domain [ 0 1 ]\n"
3130 elem.resource = res;
3131 elem.alpha1 = stop1->color[3];
3132 elem.alpha2 = stop2->color[3];
3134 status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
3140 static cairo_status_t
3141 _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
3142 unsigned int n_stops,
3143 cairo_pdf_color_stop_t *stops,
3144 cairo_bool_t is_alpha,
3145 cairo_pdf_resource_t *function)
3147 cairo_pdf_resource_t res;
3149 cairo_status_t status;
3151 /* emit linear gradients between pairs of subsequent stops... */
3152 for (i = 0; i < n_stops-1; i++) {
3154 status = cairo_pdf_surface_emit_alpha_linear_function (surface,
3157 &stops[i].resource);
3158 if (unlikely (status))
3161 status = cairo_pdf_surface_emit_rgb_linear_function (surface,
3164 &stops[i].resource);
3165 if (unlikely (status))
3170 /* ... and stitch them together */
3171 res = _cairo_pdf_surface_new_object (surface);
3173 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3175 _cairo_output_stream_printf (surface->output,
3177 "<< /FunctionType 3\n"
3178 " /Domain [ %f %f ]\n",
3181 stops[n_stops - 1].offset);
3183 _cairo_output_stream_printf (surface->output,
3185 for (i = 0; i < n_stops-1; i++)
3186 _cairo_output_stream_printf (surface->output,
3187 "%d 0 R ", stops[i].resource.id);
3188 _cairo_output_stream_printf (surface->output,
3191 _cairo_output_stream_printf (surface->output,
3193 for (i = 1; i < n_stops-1; i++)
3194 _cairo_output_stream_printf (surface->output,
3195 "%f ", stops[i].offset);
3196 _cairo_output_stream_printf (surface->output,
3199 _cairo_output_stream_printf (surface->output,
3201 for (i = 1; i < n_stops; i++)
3202 _cairo_output_stream_printf (surface->output,
3204 _cairo_output_stream_printf (surface->output,
3207 _cairo_output_stream_printf (surface->output,
3213 return _cairo_output_stream_get_status (surface->output);
3218 calc_gradient_color (cairo_pdf_color_stop_t *new_stop,
3219 cairo_pdf_color_stop_t *stop1,
3220 cairo_pdf_color_stop_t *stop2)
3223 double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
3225 for (i = 0; i < 4; i++)
3226 new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
3229 #define COLOR_STOP_EPSILON 1e-6
3231 static cairo_status_t
3232 _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
3233 cairo_gradient_pattern_t *pattern,
3234 cairo_pdf_resource_t *color_function,
3235 cairo_pdf_resource_t *alpha_function)
3237 cairo_pdf_color_stop_t *allstops, *stops;
3238 unsigned int n_stops;
3240 cairo_bool_t emit_alpha = FALSE;
3241 cairo_status_t status;
3243 color_function->id = 0;
3244 alpha_function->id = 0;
3246 allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t));
3247 if (unlikely (allstops == NULL))
3248 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3250 stops = &allstops[1];
3251 n_stops = pattern->n_stops;
3253 for (i = 0; i < n_stops; i++) {
3254 stops[i].color[0] = pattern->stops[i].color.red;
3255 stops[i].color[1] = pattern->stops[i].color.green;
3256 stops[i].color[2] = pattern->stops[i].color.blue;
3257 stops[i].color[3] = pattern->stops[i].color.alpha;
3258 if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
3260 stops[i].offset = pattern->stops[i].offset;
3263 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
3264 pattern->base.extend == CAIRO_EXTEND_REFLECT) {
3265 if (stops[0].offset > COLOR_STOP_EPSILON) {
3266 if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
3267 memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
3269 calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
3273 stops[0].offset = 0.0;
3275 if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
3276 if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
3277 memcpy (&stops[n_stops],
3278 &stops[n_stops - 1],
3279 sizeof (cairo_pdf_color_stop_t));
3281 calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
3285 stops[n_stops-1].offset = 1.0;
3288 if (stops[0].offset == stops[n_stops - 1].offset) {
3290 * The first and the last stops have the same offset, but we
3291 * don't want a function with an empty domain, because that
3292 * would provoke underdefined behaviour from rasterisers.
3293 * This can only happen with EXTEND_PAD, because EXTEND_NONE
3294 * is optimised into a clear pattern in cairo-gstate, and
3295 * REFLECT/REPEAT are always transformed to have the first
3296 * stop at t=0 and the last stop at t=1. Thus we want a step
3297 * function going from the first color to the last one.
3299 * This can be accomplished by stitching three functions:
3300 * - a constant first color function,
3301 * - a step from the first color to the last color (with empty domain)
3302 * - a constant last color function
3304 cairo_pdf_color_stop_t pad_stops[4];
3306 assert (pattern->base.extend == CAIRO_EXTEND_PAD);
3308 pad_stops[0] = pad_stops[1] = stops[0];
3309 pad_stops[2] = pad_stops[3] = stops[n_stops - 1];
3311 pad_stops[0].offset = 0;
3312 pad_stops[3].offset = 1;
3314 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3319 if (unlikely (status))
3323 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3328 if (unlikely (status))
3331 } else if (n_stops == 2) {
3332 /* no need for stitched function */
3333 status = cairo_pdf_surface_emit_rgb_linear_function (surface,
3335 &stops[n_stops - 1],
3337 if (unlikely (status))
3341 status = cairo_pdf_surface_emit_alpha_linear_function (surface,
3343 &stops[n_stops - 1],
3345 if (unlikely (status))
3349 /* multiple stops: stitch. XXX possible optimization: regularly spaced
3350 * stops do not require stitching. XXX */
3351 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3356 if (unlikely (status))
3360 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3365 if (unlikely (status))
3375 static cairo_status_t
3376 _cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface,
3377 cairo_gradient_pattern_t *pattern,
3378 cairo_pdf_resource_t *function,
3382 cairo_pdf_resource_t res;
3385 res = _cairo_pdf_surface_new_object (surface);
3387 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3389 _cairo_output_stream_printf (surface->output,
3391 "<< /FunctionType 3\n"
3392 " /Domain [ %d %d ]\n",
3397 _cairo_output_stream_printf (surface->output,
3399 for (i = begin; i < end; i++)
3400 _cairo_output_stream_printf (surface->output,
3401 "%d 0 R ", function->id);
3402 _cairo_output_stream_printf (surface->output,
3405 _cairo_output_stream_printf (surface->output,
3407 for (i = begin + 1; i < end; i++)
3408 _cairo_output_stream_printf (surface->output,
3410 _cairo_output_stream_printf (surface->output,
3413 _cairo_output_stream_printf (surface->output,
3415 for (i = begin; i < end; i++) {
3416 if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) {
3417 _cairo_output_stream_printf (surface->output,
3420 _cairo_output_stream_printf (surface->output,
3424 _cairo_output_stream_printf (surface->output,
3427 _cairo_output_stream_printf (surface->output,
3433 return _cairo_output_stream_get_status (surface->output);
3436 static cairo_status_t
3437 cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
3438 cairo_pdf_pattern_t *pdf_pattern,
3439 cairo_pdf_resource_t gstate_resource,
3440 cairo_pdf_resource_t gradient_mask)
3442 cairo_pdf_resource_t smask_resource;
3443 cairo_status_t status;
3446 if (pdf_pattern->is_shading) {
3447 snprintf(buf, sizeof(buf),
3449 " << /sh%d %d 0 R >>\n",
3453 snprintf(buf, sizeof(buf),
3455 " << /p%d %d 0 R >>\n",
3460 status = _cairo_pdf_surface_open_stream (surface,
3462 surface->compress_content,
3466 " /BBox [ 0 0 %f %f ]\n"
3469 " << /a0 << /ca 1 /CA 1 >>"
3474 " << /Type /Group\n"
3475 " /S /Transparency\n"
3477 " /CS /DeviceGray\n"
3482 if (unlikely (status))
3485 if (pdf_pattern->is_shading) {
3486 _cairo_output_stream_printf (surface->output,
3487 "/a0 gs /sh%d sh\n",
3490 _cairo_output_stream_printf (surface->output,
3493 "/Pattern cs /p%d scn\n"
3502 status = _cairo_pdf_surface_close_stream (surface);
3503 if (unlikely (status))
3506 smask_resource = _cairo_pdf_surface_new_object (surface);
3507 if (smask_resource.id == 0)
3508 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3510 _cairo_output_stream_printf (surface->output,
3518 surface->pdf_stream.self.id);
3520 /* Create GState which uses the transparency group as an SMask. */
3521 _cairo_pdf_surface_update_object (surface, gstate_resource);
3523 _cairo_output_stream_printf (surface->output,
3525 "<< /Type /ExtGState\n"
3535 return _cairo_output_stream_get_status (surface->output);
3539 _cairo_pdf_surface_output_gradient (cairo_pdf_surface_t *surface,
3540 const cairo_pdf_pattern_t *pdf_pattern,
3541 cairo_pdf_resource_t pattern_resource,
3542 const cairo_matrix_t *pat_to_pdf,
3543 const cairo_circle_double_t*start,
3544 const cairo_circle_double_t*end,
3545 const double *domain,
3546 const char *colorspace,
3547 cairo_pdf_resource_t color_function)
3549 _cairo_output_stream_printf (surface->output,
3551 pattern_resource.id);
3553 if (!pdf_pattern->is_shading) {
3554 _cairo_output_stream_printf (surface->output,
3555 "<< /Type /Pattern\n"
3557 " /Matrix [ %f %f %f %f %f %f ]\n"
3559 pat_to_pdf->xx, pat_to_pdf->yx,
3560 pat_to_pdf->xy, pat_to_pdf->yy,
3561 pat_to_pdf->x0, pat_to_pdf->y0);
3564 if (pdf_pattern->pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
3565 _cairo_output_stream_printf (surface->output,
3566 " << /ShadingType 2\n"
3568 " /Coords [ %f %f %f %f ]\n",
3570 start->center.x, start->center.y,
3571 end->center.x, end->center.y);
3573 _cairo_output_stream_printf (surface->output,
3574 " << /ShadingType 3\n"
3576 " /Coords [ %f %f %f %f %f %f ]\n",
3578 start->center.x, start->center.y,
3579 MAX (start->radius, 0),
3580 end->center.x, end->center.y,
3581 MAX (end->radius, 0));
3584 _cairo_output_stream_printf (surface->output,
3585 " /Domain [ %f %f ]\n",
3586 domain[0], domain[1]);
3588 if (pdf_pattern->pattern->extend != CAIRO_EXTEND_NONE) {
3589 _cairo_output_stream_printf (surface->output,
3590 " /Extend [ true true ]\n");
3592 _cairo_output_stream_printf (surface->output,
3593 " /Extend [ false false ]\n");
3596 _cairo_output_stream_printf (surface->output,
3597 " /Function %d 0 R\n"
3601 if (!pdf_pattern->is_shading) {
3602 _cairo_output_stream_printf (surface->output,
3608 static cairo_status_t
3609 _cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t *surface,
3610 cairo_pdf_pattern_t *pdf_pattern)
3612 cairo_gradient_pattern_t *pattern = (cairo_gradient_pattern_t *) pdf_pattern->pattern;
3613 cairo_pdf_resource_t color_function, alpha_function;
3614 cairo_matrix_t pat_to_pdf;
3615 cairo_circle_double_t start, end;
3617 cairo_status_t status;
3619 assert (pattern->n_stops != 0);
3621 status = _cairo_pdf_surface_emit_pattern_stops (surface,
3625 if (unlikely (status))
3628 pat_to_pdf = pattern->base.matrix;
3629 status = cairo_matrix_invert (&pat_to_pdf);
3630 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3631 assert (status == CAIRO_STATUS_SUCCESS);
3632 cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
3634 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
3635 pattern->base.extend == CAIRO_EXTEND_REFLECT)
3637 double bounds_x1, bounds_x2, bounds_y1, bounds_y2;
3638 double x_scale, y_scale, tolerance;
3640 /* TODO: use tighter extents */
3643 bounds_x2 = surface->width;
3644 bounds_y2 = surface->height;
3645 _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
3646 &bounds_x1, &bounds_y1,
3647 &bounds_x2, &bounds_y2,
3650 x_scale = surface->base.x_resolution / surface->base.x_fallback_resolution;
3651 y_scale = surface->base.y_resolution / surface->base.y_fallback_resolution;
3653 tolerance = fabs (_cairo_matrix_compute_determinant (&pattern->base.matrix));
3654 tolerance /= _cairo_matrix_transformed_circle_major_axis (&pattern->base.matrix, 1);
3655 tolerance *= MIN (x_scale, y_scale);
3657 _cairo_gradient_pattern_box_to_parameter (pattern,
3658 bounds_x1, bounds_y1,
3659 bounds_x2, bounds_y2,
3661 } else if (pattern->stops[0].offset == pattern->stops[pattern->n_stops - 1].offset) {
3663 * If the first and the last stop offset are the same, then
3664 * the color function is a step function.
3665 * _cairo_ps_surface_emit_pattern_stops emits it as a stitched
3666 * function no matter how many stops the pattern has. The
3667 * domain of the stitched function will be [0 1] in this case.
3669 * This is done to avoid emitting degenerate gradients for
3670 * EXTEND_PAD patterns having a step color function.
3675 assert (pattern->base.extend == CAIRO_EXTEND_PAD);
3677 domain[0] = pattern->stops[0].offset;
3678 domain[1] = pattern->stops[pattern->n_stops - 1].offset;
3681 /* PDF requires the first and last stop to be the same as the
3682 * extreme coordinates. For repeating patterns this moves the
3683 * extreme coordinates out to the begin/end of the repeating
3684 * function. For non repeating patterns this may move the extreme
3685 * coordinates in if there are not stops at offset 0 and 1. */
3686 _cairo_gradient_pattern_interpolate (pattern, domain[0], &start);
3687 _cairo_gradient_pattern_interpolate (pattern, domain[1], &end);
3689 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
3690 pattern->base.extend == CAIRO_EXTEND_REFLECT)
3692 int repeat_begin, repeat_end;
3694 repeat_begin = floor (domain[0]);
3695 repeat_end = ceil (domain[1]);
3697 status = _cairo_pdf_surface_emit_repeating_function (surface,
3702 if (unlikely (status))
3705 if (alpha_function.id != 0) {
3706 status = _cairo_pdf_surface_emit_repeating_function (surface,
3711 if (unlikely (status))
3714 } else if (pattern->n_stops <= 2) {
3715 /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
3716 * Type 2 function is used by itself without a stitching
3717 * function. Type 2 functions always have the domain [0 1] */
3722 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
3723 _cairo_pdf_surface_output_gradient (surface, pdf_pattern,
3724 pdf_pattern->pattern_res,
3725 &pat_to_pdf, &start, &end, domain,
3726 "/DeviceRGB", color_function);
3728 if (alpha_function.id != 0) {
3729 cairo_pdf_resource_t mask_resource;
3731 assert (pdf_pattern->gstate_res.id != 0);
3733 /* Create pattern for SMask. */
3734 mask_resource = _cairo_pdf_surface_new_object (surface);
3735 if (mask_resource.id == 0)
3736 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3738 _cairo_pdf_surface_output_gradient (surface, pdf_pattern,
3740 &pat_to_pdf, &start, &end, domain,
3741 "/DeviceGray", alpha_function);
3743 status = cairo_pdf_surface_emit_transparency_group (surface,
3745 pdf_pattern->gstate_res,
3747 if (unlikely (status))
3751 return _cairo_output_stream_get_status (surface->output);
3754 static cairo_status_t
3755 _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
3756 cairo_pdf_pattern_t *pdf_pattern)
3758 cairo_matrix_t pat_to_pdf;
3759 cairo_status_t status;
3760 cairo_pattern_t *pattern = pdf_pattern->pattern;
3761 cairo_pdf_shading_t shading;
3763 cairo_pdf_resource_t res;
3765 pat_to_pdf = pattern->matrix;
3766 status = cairo_matrix_invert (&pat_to_pdf);
3767 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3768 assert (status == CAIRO_STATUS_SUCCESS);
3770 cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
3772 status = _cairo_pdf_shading_init_color (&shading, (cairo_mesh_pattern_t *) pattern);
3773 if (unlikely (status))
3776 res = _cairo_pdf_surface_new_object (surface);
3777 if (unlikely (res.id == 0))
3778 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3780 _cairo_output_stream_printf (surface->output,
3782 "<< /ShadingType %d\n"
3783 " /ColorSpace /DeviceRGB\n"
3784 " /BitsPerCoordinate %d\n"
3785 " /BitsPerComponent %d\n"
3786 " /BitsPerFlag %d\n"
3789 shading.shading_type,
3790 shading.bits_per_coordinate,
3791 shading.bits_per_component,
3792 shading.bits_per_flag);
3794 for (i = 0; i < shading.decode_array_length; i++)
3795 _cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
3797 _cairo_output_stream_printf (surface->output,
3802 shading.data_length);
3804 _cairo_output_stream_write (surface->output, shading.data, shading.data_length);
3806 _cairo_output_stream_printf (surface->output,
3810 _cairo_pdf_shading_fini (&shading);
3812 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
3813 _cairo_output_stream_printf (surface->output,
3815 "<< /Type /Pattern\n"
3817 " /Matrix [ %f %f %f %f %f %f ]\n"
3818 " /Shading %d 0 R\n"
3821 pdf_pattern->pattern_res.id,
3822 pat_to_pdf.xx, pat_to_pdf.yx,
3823 pat_to_pdf.xy, pat_to_pdf.yy,
3824 pat_to_pdf.x0, pat_to_pdf.y0,
3827 if (pdf_pattern->gstate_res.id != 0) {
3828 cairo_pdf_resource_t mask_resource;
3830 /* Create pattern for SMask. */
3831 res = _cairo_pdf_surface_new_object (surface);
3832 if (unlikely (res.id == 0))
3833 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3835 status = _cairo_pdf_shading_init_alpha (&shading, (cairo_mesh_pattern_t *) pattern);
3836 if (unlikely (status))
3839 _cairo_output_stream_printf (surface->output,
3841 "<< /ShadingType %d\n"
3842 " /ColorSpace /DeviceGray\n"
3843 " /BitsPerCoordinate %d\n"
3844 " /BitsPerComponent %d\n"
3845 " /BitsPerFlag %d\n"
3848 shading.shading_type,
3849 shading.bits_per_coordinate,
3850 shading.bits_per_component,
3851 shading.bits_per_flag);
3853 for (i = 0; i < shading.decode_array_length; i++)
3854 _cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
3856 _cairo_output_stream_printf (surface->output,
3861 shading.data_length);
3863 _cairo_output_stream_write (surface->output, shading.data, shading.data_length);
3865 _cairo_output_stream_printf (surface->output,
3868 _cairo_pdf_shading_fini (&shading);
3870 mask_resource = _cairo_pdf_surface_new_object (surface);
3871 if (unlikely (mask_resource.id == 0))
3872 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3874 _cairo_output_stream_printf (surface->output,
3876 "<< /Type /Pattern\n"
3878 " /Matrix [ %f %f %f %f %f %f ]\n"
3879 " /Shading %d 0 R\n"
3883 pat_to_pdf.xx, pat_to_pdf.yx,
3884 pat_to_pdf.xy, pat_to_pdf.yy,
3885 pat_to_pdf.x0, pat_to_pdf.y0,
3888 status = cairo_pdf_surface_emit_transparency_group (surface,
3890 pdf_pattern->gstate_res,
3892 if (unlikely (status))
3896 return _cairo_output_stream_get_status (surface->output);
3899 static cairo_status_t
3900 _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
3902 double old_width, old_height;
3903 cairo_status_t status;
3905 old_width = surface->width;
3906 old_height = surface->height;
3907 _cairo_pdf_surface_set_size_internal (surface,
3909 pdf_pattern->height);
3911 switch (pdf_pattern->pattern->type) {
3912 case CAIRO_PATTERN_TYPE_SOLID:
3914 status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3917 case CAIRO_PATTERN_TYPE_SURFACE:
3918 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3919 status = _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
3922 case CAIRO_PATTERN_TYPE_LINEAR:
3923 case CAIRO_PATTERN_TYPE_RADIAL:
3924 status = _cairo_pdf_surface_emit_gradient (surface, pdf_pattern);
3927 case CAIRO_PATTERN_TYPE_MESH:
3928 status = _cairo_pdf_surface_emit_mesh_pattern (surface, pdf_pattern);
3933 status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3937 _cairo_pdf_surface_set_size_internal (surface,
3944 static cairo_status_t
3945 _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
3946 const cairo_pattern_t *source,
3947 const cairo_rectangle_int_t *extents,
3948 cairo_bool_t stencil_mask)
3950 cairo_pdf_resource_t surface_res;
3952 cairo_matrix_t cairo_p2d, pdf_p2d;
3953 cairo_status_t status;
3955 cairo_rectangle_int_t extents2;
3959 if (source->extend == CAIRO_EXTEND_PAD &&
3960 !(source->type == CAIRO_PATTERN_TYPE_SURFACE &&
3961 ((cairo_surface_pattern_t *)source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING))
3963 status = _cairo_pdf_surface_add_padded_image_surface (surface,
3972 status = _cairo_pdf_surface_add_source_surface (surface,
3985 if (unlikely (status))
3988 cairo_p2d = source->matrix;
3989 status = cairo_matrix_invert (&cairo_p2d);
3990 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3991 assert (status == CAIRO_STATUS_SUCCESS);
3993 pdf_p2d = surface->cairo_to_pdf;
3994 cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
3995 cairo_matrix_translate (&pdf_p2d, x_offset, y_offset);
3996 cairo_matrix_translate (&pdf_p2d, 0.0, height);
3997 cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
3998 if (!(source->type == CAIRO_PATTERN_TYPE_SURFACE &&
3999 ((cairo_surface_pattern_t *)source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING))
4001 cairo_matrix_scale (&pdf_p2d, width, height);
4004 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4005 if (unlikely (status))
4008 if (! _cairo_matrix_is_identity (&pdf_p2d)) {
4009 _cairo_output_stream_printf (surface->output,
4010 "%f %f %f %f %f %f cm\n",
4011 pdf_p2d.xx, pdf_p2d.yx,
4012 pdf_p2d.xy, pdf_p2d.yy,
4013 pdf_p2d.x0, pdf_p2d.y0);
4016 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
4017 if (unlikely (status))
4021 _cairo_output_stream_printf (surface->output,
4025 _cairo_output_stream_printf (surface->output,
4026 "/a%d gs /x%d Do\n",
4031 return _cairo_pdf_surface_add_xobject (surface, surface_res);
4034 static cairo_status_t
4035 _cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t *surface,
4036 const cairo_pattern_t *source,
4037 const cairo_rectangle_int_t *extents)
4039 cairo_pdf_resource_t shading_res, gstate_res;
4040 cairo_matrix_t pat_to_pdf;
4041 cairo_status_t status;
4044 status = _cairo_pdf_surface_add_pdf_shading (surface, source,
4046 &shading_res, &gstate_res);
4047 if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
4048 return CAIRO_STATUS_SUCCESS;
4049 if (unlikely (status))
4052 pat_to_pdf = source->matrix;
4053 status = cairo_matrix_invert (&pat_to_pdf);
4054 /* cairo_pattern_set_matrix ensures the matrix is invertible */
4055 assert (status == CAIRO_STATUS_SUCCESS);
4056 cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
4058 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4059 if (unlikely (status))
4062 if (! _cairo_matrix_is_identity (&pat_to_pdf)) {
4063 _cairo_output_stream_printf (surface->output,
4064 "%f %f %f %f %f %f cm\n",
4065 pat_to_pdf.xx, pat_to_pdf.yx,
4066 pat_to_pdf.xy, pat_to_pdf.yy,
4067 pat_to_pdf.x0, pat_to_pdf.y0);
4070 status = _cairo_pdf_surface_add_shading (surface, shading_res);
4071 if (unlikely (status))
4074 if (gstate_res.id != 0) {
4075 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
4076 if (unlikely (status))
4079 _cairo_output_stream_printf (surface->output,
4080 "/s%d gs /sh%d sh\n",
4084 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
4085 if (unlikely (status))
4088 _cairo_output_stream_printf (surface->output,
4089 "/a%d gs /sh%d sh\n",
4097 static cairo_status_t
4098 _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface,
4099 const cairo_pattern_t *source,
4100 const cairo_rectangle_int_t *extents,
4103 switch (source->type) {
4104 case CAIRO_PATTERN_TYPE_SURFACE:
4105 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4106 return _cairo_pdf_surface_paint_surface_pattern (surface,
4110 case CAIRO_PATTERN_TYPE_LINEAR:
4111 case CAIRO_PATTERN_TYPE_RADIAL:
4112 case CAIRO_PATTERN_TYPE_MESH:
4113 return _cairo_pdf_surface_paint_gradient (surface,
4117 case CAIRO_PATTERN_TYPE_SOLID:
4120 return CAIRO_STATUS_SUCCESS;
4125 _can_paint_pattern (const cairo_pattern_t *pattern)
4127 switch (pattern->type) {
4128 case CAIRO_PATTERN_TYPE_SOLID:
4131 case CAIRO_PATTERN_TYPE_SURFACE:
4132 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4133 return (pattern->extend == CAIRO_EXTEND_NONE ||
4134 pattern->extend == CAIRO_EXTEND_PAD);
4136 case CAIRO_PATTERN_TYPE_LINEAR:
4137 case CAIRO_PATTERN_TYPE_RADIAL:
4140 case CAIRO_PATTERN_TYPE_MESH:
4149 static cairo_status_t
4150 _cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface,
4151 cairo_operator_t op)
4153 cairo_status_t status;
4155 if (op == surface->current_operator)
4156 return CAIRO_STATUS_SUCCESS;
4158 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4159 if (unlikely (status))
4162 _cairo_output_stream_printf (surface->output,
4164 surface->current_operator = op;
4165 _cairo_pdf_surface_add_operator (surface, op);
4167 return CAIRO_STATUS_SUCCESS;
4170 static cairo_status_t
4171 _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
4172 const cairo_pattern_t *pattern,
4173 cairo_pdf_resource_t pattern_res,
4174 cairo_bool_t is_stroke)
4176 cairo_status_t status;
4178 const cairo_color_t *solid_color = NULL;
4180 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
4181 const cairo_solid_pattern_t *solid = (const cairo_solid_pattern_t *) pattern;
4183 solid_color = &solid->color;
4186 if (solid_color != NULL) {
4187 if (surface->current_pattern_is_solid_color == FALSE ||
4188 surface->current_color_red != solid_color->red ||
4189 surface->current_color_green != solid_color->green ||
4190 surface->current_color_blue != solid_color->blue ||
4191 surface->current_color_is_stroke != is_stroke)
4193 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4194 if (unlikely (status))
4197 _cairo_output_stream_printf (surface->output,
4204 _cairo_output_stream_printf (surface->output, "RG ");
4206 _cairo_output_stream_printf (surface->output, "rg ");
4208 surface->current_color_red = solid_color->red;
4209 surface->current_color_green = solid_color->green;
4210 surface->current_color_blue = solid_color->blue;
4211 surface->current_color_is_stroke = is_stroke;
4214 if (surface->current_pattern_is_solid_color == FALSE ||
4215 surface->current_color_alpha != solid_color->alpha)
4217 status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha);
4218 if (unlikely (status))
4221 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4222 if (unlikely (status))
4225 _cairo_output_stream_printf (surface->output,
4228 surface->current_color_alpha = solid_color->alpha;
4231 surface->current_pattern_is_solid_color = TRUE;
4233 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
4234 if (unlikely (status))
4237 status = _cairo_pdf_surface_add_pattern (surface, pattern_res);
4238 if (unlikely (status))
4241 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4242 if (unlikely (status))
4245 /* fill-stroke calls select_pattern twice. Don't save if the
4246 * gstate is already saved. */
4247 if (!surface->select_pattern_gstate_saved)
4248 _cairo_output_stream_printf (surface->output, "q ");
4251 _cairo_output_stream_printf (surface->output,
4252 "/Pattern CS /p%d SCN ",
4255 _cairo_output_stream_printf (surface->output,
4256 "/Pattern cs /p%d scn ",
4259 _cairo_output_stream_printf (surface->output,
4262 surface->select_pattern_gstate_saved = TRUE;
4263 surface->current_pattern_is_solid_color = FALSE;
4266 return _cairo_output_stream_get_status (surface->output);
4269 static cairo_int_status_t
4270 _cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
4272 cairo_int_status_t status;
4274 if (surface->select_pattern_gstate_saved) {
4275 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4276 if (unlikely (status))
4279 _cairo_output_stream_printf (surface->output, "Q\n");
4280 _cairo_pdf_operators_reset (&surface->pdf_operators);
4281 surface->current_pattern_is_solid_color = FALSE;
4283 surface->select_pattern_gstate_saved = FALSE;
4285 return CAIRO_STATUS_SUCCESS;
4288 static cairo_int_status_t
4289 _cairo_pdf_surface_show_page (void *abstract_surface)
4291 cairo_pdf_surface_t *surface = abstract_surface;
4292 cairo_int_status_t status;
4294 status = _cairo_pdf_surface_close_content_stream (surface);
4295 if (unlikely (status))
4298 _cairo_surface_clipper_reset (&surface->clipper);
4300 status = _cairo_pdf_surface_write_page (surface);
4301 if (unlikely (status))
4304 _cairo_pdf_surface_clear (surface);
4306 return CAIRO_STATUS_SUCCESS;
4310 _cairo_pdf_surface_get_extents (void *abstract_surface,
4311 cairo_rectangle_int_t *rectangle)
4313 cairo_pdf_surface_t *surface = abstract_surface;
4318 /* XXX: The conversion to integers here is pretty bogus, (not to
4319 * mention the arbitrary limitation of width to a short(!). We
4320 * may need to come up with a better interface for get_size.
4322 rectangle->width = ceil (surface->width);
4323 rectangle->height = ceil (surface->height);
4329 _cairo_pdf_surface_get_font_options (void *abstract_surface,
4330 cairo_font_options_t *options)
4332 _cairo_font_options_init_default (options);
4334 cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
4335 cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
4336 cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
4337 _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_OFF);
4340 static cairo_pdf_resource_t
4341 _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface)
4343 cairo_pdf_resource_t info;
4345 info = _cairo_pdf_surface_new_object (surface);
4349 _cairo_output_stream_printf (surface->output,
4351 "<< /Creator (cairo %s (http://cairographics.org))\n"
4352 " /Producer (cairo %s (http://cairographics.org))\n"
4356 cairo_version_string (),
4357 cairo_version_string ());
4363 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
4365 cairo_pdf_resource_t page;
4368 _cairo_pdf_surface_update_object (surface, surface->pages_resource);
4369 _cairo_output_stream_printf (surface->output,
4373 surface->pages_resource.id);
4375 num_pages = _cairo_array_num_elements (&surface->pages);
4376 for (i = 0; i < num_pages; i++) {
4377 _cairo_array_copy_element (&surface->pages, i, &page);
4378 _cairo_output_stream_printf (surface->output, "%d 0 R ", page.id);
4381 _cairo_output_stream_printf (surface->output, "]\n");
4382 _cairo_output_stream_printf (surface->output, " /Count %d\n", num_pages);
4385 /* TODO: Figure out which other defaults to be inherited by /Page
4387 _cairo_output_stream_printf (surface->output,
4392 static cairo_status_t
4393 _utf8_to_pdf_string (const char *utf8, char **str_out)
4399 cairo_status_t status = CAIRO_STATUS_SUCCESS;
4402 len = strlen (utf8);
4403 for (i = 0; i < len; i++) {
4404 unsigned c = utf8[i];
4405 if (c < 32 || c > 126 || c == '(' || c == ')' || c == '\\') {
4412 str = malloc (len + 3);
4414 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4417 for (i = 0; i < len; i++)
4422 uint16_t *utf16 = NULL;
4425 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
4426 if (unlikely (status))
4429 str = malloc (utf16_len*4 + 7);
4432 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4435 strcpy (str, "<FEFF");
4436 for (i = 0; i < utf16_len; i++)
4437 snprintf (str + 4*i + 5, 5, "%04X", utf16[i]);
4447 static cairo_status_t
4448 _cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t *surface,
4451 uint16_t *utf16 = NULL;
4453 cairo_status_t status;
4456 if (utf8 && *utf8) {
4457 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
4458 if (unlikely (status))
4462 _cairo_output_stream_printf (surface->output, "<");
4463 if (utf16 == NULL || utf16_len == 0) {
4464 /* According to the "ToUnicode Mapping File Tutorial"
4465 * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
4467 * Glyphs that do not map to a Unicode code point must be
4468 * mapped to 0xfffd "REPLACEMENT CHARACTER".
4470 _cairo_output_stream_printf (surface->output,
4473 for (i = 0; i < utf16_len; i++)
4474 _cairo_output_stream_printf (surface->output,
4475 "%04x", (int) (utf16[i]));
4477 _cairo_output_stream_printf (surface->output, ">");
4481 return CAIRO_STATUS_SUCCESS;
4486 * Public domain code from:
4487 * http://burtleburtle.net/bob/hash/doobs.html
4490 #define HASH_MIX(a,b,c) \
4492 a -= b; a -= c; a ^= (c>>13); \
4493 b -= c; b -= a; b ^= (a<<8); \
4494 c -= a; c -= b; c ^= (b>>13); \
4495 a -= b; a -= c; a ^= (c>>12); \
4496 b -= c; b -= a; b ^= (a<<16); \
4497 c -= a; c -= b; c ^= (b>>5); \
4498 a -= b; a -= c; a ^= (c>>3); \
4499 b -= c; b -= a; b ^= (a<<10); \
4500 c -= a; c -= b; c ^= (b>>15); \
4504 _hash_data (const unsigned char *data, int length, uint32_t initval)
4506 uint32_t a, b, c, len;
4509 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
4510 c = initval; /* the previous hash value */
4513 a += (data[0] + ((uint32_t)data[1]<<8) + ((uint32_t)data[2]<<16) + ((uint32_t)data[3]<<24));
4514 b += (data[4] + ((uint32_t)data[5]<<8) + ((uint32_t)data[6]<<16) + ((uint32_t)data[7]<<24));
4515 c += (data[8] + ((uint32_t)data[9]<<8) + ((uint32_t)data[10]<<16)+ ((uint32_t)data[11]<<24));
4523 case 11: c+= ((uint32_t) data[10] << 24);
4524 case 10: c+= ((uint32_t) data[9] << 16);
4525 case 9 : c+= ((uint32_t) data[8] << 8);
4526 case 8 : b+= ((uint32_t) data[7] << 24);
4527 case 7 : b+= ((uint32_t) data[6] << 16);
4528 case 6 : b+= ((uint32_t) data[5] << 8);
4529 case 5 : b+= data[4];
4530 case 4 : a+= ((uint32_t) data[3] << 24);
4531 case 3 : a+= ((uint32_t) data[2] << 16);
4532 case 2 : a+= ((uint32_t) data[1] << 8);
4533 case 1 : a+= data[0];
4541 _create_font_subset_tag (cairo_scaled_font_subset_t *font_subset,
4542 const char *font_name,
4550 hash = _hash_data ((unsigned char *) font_name, strlen(font_name), 0);
4551 hash = _hash_data ((unsigned char *) (font_subset->glyphs),
4552 font_subset->num_glyphs * sizeof(unsigned long), hash);
4554 numerator = abs (hash);
4555 for (i = 0; i < 6; i++) {
4556 d = ldiv (numerator, 26);
4558 tag[i] = 'A' + d.rem;
4563 static cairo_int_status_t
4564 _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
4565 cairo_scaled_font_subset_t *font_subset,
4566 cairo_pdf_resource_t *stream)
4568 unsigned int i, num_bfchar;
4569 cairo_int_status_t status;
4573 status = _cairo_pdf_surface_open_stream (surface,
4575 surface->compress_content,
4577 if (unlikely (status))
4580 _cairo_output_stream_printf (surface->output,
4581 "/CIDInit /ProcSet findresource begin\n"
4585 "<< /Registry (Adobe)\n"
4586 " /Ordering (UCS)\n"
4589 "/CMapName /Adobe-Identity-UCS def\n"
4591 "1 begincodespacerange\n");
4593 if (font_subset->is_composite && !font_subset->is_latin) {
4594 _cairo_output_stream_printf (surface->output,
4597 _cairo_output_stream_printf (surface->output,
4601 _cairo_output_stream_printf (surface->output,
4602 "endcodespacerange\n");
4604 if (font_subset->is_scaled) {
4605 /* Type 3 fonts include glyph 0 in the subset */
4606 num_bfchar = font_subset->num_glyphs;
4608 /* The CMap specification has a limit of 100 characters per beginbfchar operator */
4609 _cairo_output_stream_printf (surface->output,
4611 num_bfchar > 100 ? 100 : num_bfchar);
4613 for (i = 0; i < num_bfchar; i++) {
4614 if (i != 0 && i % 100 == 0) {
4615 _cairo_output_stream_printf (surface->output,
4618 num_bfchar - i > 100 ? 100 : num_bfchar - i);
4620 _cairo_output_stream_printf (surface->output, "<%02x> ", i);
4621 status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
4622 font_subset->utf8[i]);
4623 if (unlikely (status))
4626 _cairo_output_stream_printf (surface->output,
4630 /* Other fonts reserve glyph 0 for .notdef. Omit glyph 0 from the /ToUnicode map */
4631 num_bfchar = font_subset->num_glyphs - 1;
4633 /* The CMap specification has a limit of 100 characters per beginbfchar operator */
4634 _cairo_output_stream_printf (surface->output,
4636 num_bfchar > 100 ? 100 : num_bfchar);
4638 for (i = 0; i < num_bfchar; i++) {
4639 if (i != 0 && i % 100 == 0) {
4640 _cairo_output_stream_printf (surface->output,
4643 num_bfchar - i > 100 ? 100 : num_bfchar - i);
4645 if (font_subset->is_latin)
4646 _cairo_output_stream_printf (surface->output, "<%02x> ", font_subset->to_latin_char[i + 1]);
4647 else if (font_subset->is_composite)
4648 _cairo_output_stream_printf (surface->output, "<%04x> ", i + 1);
4650 _cairo_output_stream_printf (surface->output, "<%02x> ", i + 1);
4652 status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
4653 font_subset->utf8[i + 1]);
4654 if (unlikely (status))
4657 _cairo_output_stream_printf (surface->output,
4662 _cairo_output_stream_printf (surface->output,
4665 _cairo_output_stream_printf (surface->output,
4667 "CMapName currentdict /CMap defineresource pop\n"
4671 *stream = surface->pdf_stream.self;
4672 return _cairo_pdf_surface_close_stream (surface);
4675 #define PDF_UNITS_PER_EM 1000
4677 static cairo_status_t
4678 _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
4679 cairo_scaled_font_subset_t *font_subset,
4680 cairo_cff_subset_t *subset)
4682 cairo_pdf_resource_t stream, descriptor, cidfont_dict;
4683 cairo_pdf_resource_t subset_resource, to_unicode_stream;
4684 cairo_pdf_font_t font;
4685 unsigned int i, last_glyph;
4686 cairo_status_t status;
4689 _create_font_subset_tag (font_subset, subset->ps_name, tag);
4691 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
4692 font_subset->font_id,
4693 font_subset->subset_id);
4694 if (subset_resource.id == 0)
4695 return CAIRO_STATUS_SUCCESS;
4697 status = _cairo_pdf_surface_open_stream (surface,
4700 font_subset->is_latin ?
4701 " /Subtype /Type1C\n" :
4702 " /Subtype /CIDFontType0C\n");
4703 if (unlikely (status))
4706 stream = surface->pdf_stream.self;
4707 _cairo_output_stream_write (surface->output,
4708 subset->data, subset->data_length);
4709 status = _cairo_pdf_surface_close_stream (surface);
4710 if (unlikely (status))
4713 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
4715 &to_unicode_stream);
4716 if (_cairo_status_is_error (status))
4719 descriptor = _cairo_pdf_surface_new_object (surface);
4720 if (descriptor.id == 0)
4721 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4723 _cairo_output_stream_printf (surface->output,
4725 "<< /Type /FontDescriptor\n"
4726 " /FontName /%s+%s\n",
4731 if (subset->family_name_utf8) {
4734 status = _utf8_to_pdf_string (subset->family_name_utf8, &pdf_str);
4735 if (unlikely (status))
4738 _cairo_output_stream_printf (surface->output,
4739 " /FontFamily %s\n",
4744 _cairo_output_stream_printf (surface->output,
4746 " /FontBBox [ %ld %ld %ld %ld ]\n"
4753 " /FontFile3 %u 0 R\n"
4756 (long)(subset->x_min*PDF_UNITS_PER_EM),
4757 (long)(subset->y_min*PDF_UNITS_PER_EM),
4758 (long)(subset->x_max*PDF_UNITS_PER_EM),
4759 (long)(subset->y_max*PDF_UNITS_PER_EM),
4760 (long)(subset->ascent*PDF_UNITS_PER_EM),
4761 (long)(subset->descent*PDF_UNITS_PER_EM),
4762 (long)(subset->y_max*PDF_UNITS_PER_EM),
4765 if (font_subset->is_latin) {
4766 /* find last glyph used */
4767 for (i = 255; i >= 32; i--)
4768 if (font_subset->latin_to_subset_glyph_index[i] > 0)
4772 _cairo_pdf_surface_update_object (surface, subset_resource);
4773 _cairo_output_stream_printf (surface->output,
4776 " /Subtype /Type1\n"
4777 " /BaseFont /%s+%s\n"
4780 " /FontDescriptor %d 0 R\n"
4781 " /Encoding /WinAnsiEncoding\n"
4789 for (i = 32; i < last_glyph + 1; i++) {
4790 int glyph = font_subset->latin_to_subset_glyph_index[i];
4792 _cairo_output_stream_printf (surface->output,
4794 (long)(subset->widths[glyph]*PDF_UNITS_PER_EM));
4796 _cairo_output_stream_printf (surface->output, " 0");
4800 _cairo_output_stream_printf (surface->output,
4803 if (to_unicode_stream.id != 0)
4804 _cairo_output_stream_printf (surface->output,
4805 " /ToUnicode %d 0 R\n",
4806 to_unicode_stream.id);
4808 _cairo_output_stream_printf (surface->output,
4812 cidfont_dict = _cairo_pdf_surface_new_object (surface);
4813 if (cidfont_dict.id == 0)
4814 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4816 _cairo_output_stream_printf (surface->output,
4819 " /Subtype /CIDFontType0\n"
4820 " /BaseFont /%s+%s\n"
4822 " << /Registry (Adobe)\n"
4823 " /Ordering (Identity)\n"
4826 " /FontDescriptor %d 0 R\n"
4833 for (i = 0; i < font_subset->num_glyphs; i++)
4834 _cairo_output_stream_printf (surface->output,
4836 (long)(subset->widths[i]*PDF_UNITS_PER_EM));
4838 _cairo_output_stream_printf (surface->output,
4843 _cairo_pdf_surface_update_object (surface, subset_resource);
4844 _cairo_output_stream_printf (surface->output,
4847 " /Subtype /Type0\n"
4848 " /BaseFont /%s+%s\n"
4849 " /Encoding /Identity-H\n"
4850 " /DescendantFonts [ %d 0 R]\n",
4856 if (to_unicode_stream.id != 0)
4857 _cairo_output_stream_printf (surface->output,
4858 " /ToUnicode %d 0 R\n",
4859 to_unicode_stream.id);
4861 _cairo_output_stream_printf (surface->output,
4866 font.font_id = font_subset->font_id;
4867 font.subset_id = font_subset->subset_id;
4868 font.subset_resource = subset_resource;
4869 status = _cairo_array_append (&surface->fonts, &font);
4874 static cairo_status_t
4875 _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
4876 cairo_scaled_font_subset_t *font_subset)
4878 cairo_status_t status;
4879 cairo_cff_subset_t subset;
4882 snprintf (name, sizeof name, "CairoFont-%d-%d",
4883 font_subset->font_id, font_subset->subset_id);
4884 status = _cairo_cff_subset_init (&subset, name, font_subset);
4885 if (unlikely (status))
4888 status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
4890 _cairo_cff_subset_fini (&subset);
4895 static cairo_status_t
4896 _cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t *surface,
4897 cairo_scaled_font_subset_t *font_subset)
4899 cairo_status_t status;
4900 cairo_cff_subset_t subset;
4903 /* CFF fallback subsetting does not work with 8-bit glyphs unless
4904 * they are a latin subset */
4905 if (!font_subset->is_composite && !font_subset->is_latin)
4906 return CAIRO_INT_STATUS_UNSUPPORTED;
4908 snprintf (name, sizeof name, "CairoFont-%d-%d",
4909 font_subset->font_id, font_subset->subset_id);
4910 status = _cairo_cff_fallback_init (&subset, name, font_subset);
4911 if (unlikely (status))
4914 status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
4916 _cairo_cff_fallback_fini (&subset);
4921 static cairo_status_t
4922 _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
4923 cairo_scaled_font_subset_t *font_subset,
4924 cairo_type1_subset_t *subset)
4926 cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
4927 cairo_pdf_font_t font;
4928 cairo_status_t status;
4929 unsigned long length;
4930 unsigned int i, last_glyph;
4933 _create_font_subset_tag (font_subset, subset->base_font, tag);
4935 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
4936 font_subset->font_id,
4937 font_subset->subset_id);
4938 if (subset_resource.id == 0)
4939 return CAIRO_STATUS_SUCCESS;
4941 length = subset->header_length + subset->data_length + subset->trailer_length;
4942 status = _cairo_pdf_surface_open_stream (surface,
4948 subset->header_length,
4949 subset->data_length,
4950 subset->trailer_length);
4951 if (unlikely (status))
4954 stream = surface->pdf_stream.self;
4955 _cairo_output_stream_write (surface->output, subset->data, length);
4956 status = _cairo_pdf_surface_close_stream (surface);
4957 if (unlikely (status))
4960 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
4962 &to_unicode_stream);
4963 if (_cairo_status_is_error (status))
4966 last_glyph = font_subset->num_glyphs - 1;
4967 if (font_subset->is_latin) {
4968 /* find last glyph used */
4969 for (i = 255; i >= 32; i--)
4970 if (font_subset->latin_to_subset_glyph_index[i] > 0)
4976 descriptor = _cairo_pdf_surface_new_object (surface);
4977 if (descriptor.id == 0)
4978 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4980 _cairo_output_stream_printf (surface->output,
4982 "<< /Type /FontDescriptor\n"
4983 " /FontName /%s+%s\n"
4985 " /FontBBox [ %ld %ld %ld %ld ]\n"
4992 " /FontFile %u 0 R\n"
4998 (long)(subset->x_min*PDF_UNITS_PER_EM),
4999 (long)(subset->y_min*PDF_UNITS_PER_EM),
5000 (long)(subset->x_max*PDF_UNITS_PER_EM),
5001 (long)(subset->y_max*PDF_UNITS_PER_EM),
5002 (long)(subset->ascent*PDF_UNITS_PER_EM),
5003 (long)(subset->descent*PDF_UNITS_PER_EM),
5004 (long)(subset->y_max*PDF_UNITS_PER_EM),
5007 _cairo_pdf_surface_update_object (surface, subset_resource);
5008 _cairo_output_stream_printf (surface->output,
5011 " /Subtype /Type1\n"
5012 " /BaseFont /%s+%s\n"
5015 " /FontDescriptor %d 0 R\n",
5019 font_subset->is_latin ? 32 : 0,
5023 if (font_subset->is_latin)
5024 _cairo_output_stream_printf (surface->output, " /Encoding /WinAnsiEncoding\n");
5026 _cairo_output_stream_printf (surface->output, " /Widths [");
5027 if (font_subset->is_latin) {
5028 for (i = 32; i < last_glyph + 1; i++) {
5029 int glyph = font_subset->latin_to_subset_glyph_index[i];
5031 _cairo_output_stream_printf (surface->output,
5033 (long)(subset->widths[glyph]*PDF_UNITS_PER_EM));
5035 _cairo_output_stream_printf (surface->output, " 0");
5039 for (i = 0; i < font_subset->num_glyphs; i++)
5040 _cairo_output_stream_printf (surface->output,
5042 (long)(subset->widths[i]*PDF_UNITS_PER_EM));
5045 _cairo_output_stream_printf (surface->output,
5048 if (to_unicode_stream.id != 0)
5049 _cairo_output_stream_printf (surface->output,
5050 " /ToUnicode %d 0 R\n",
5051 to_unicode_stream.id);
5053 _cairo_output_stream_printf (surface->output,
5057 font.font_id = font_subset->font_id;
5058 font.subset_id = font_subset->subset_id;
5059 font.subset_resource = subset_resource;
5060 return _cairo_array_append (&surface->fonts, &font);
5063 static cairo_status_t
5064 _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
5065 cairo_scaled_font_subset_t *font_subset)
5067 cairo_status_t status;
5068 cairo_type1_subset_t subset;
5071 /* 16-bit glyphs not compatible with Type 1 fonts */
5072 if (font_subset->is_composite && !font_subset->is_latin)
5073 return CAIRO_INT_STATUS_UNSUPPORTED;
5075 snprintf (name, sizeof name, "CairoFont-%d-%d",
5076 font_subset->font_id, font_subset->subset_id);
5077 status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE);
5078 if (unlikely (status))
5081 status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
5083 _cairo_type1_subset_fini (&subset);
5087 static cairo_status_t
5088 _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
5089 cairo_scaled_font_subset_t *font_subset)
5091 cairo_status_t status;
5092 cairo_type1_subset_t subset;
5095 /* 16-bit glyphs not compatible with Type 1 fonts */
5096 if (font_subset->is_composite && !font_subset->is_latin)
5097 return CAIRO_INT_STATUS_UNSUPPORTED;
5099 snprintf (name, sizeof name, "CairoFont-%d-%d",
5100 font_subset->font_id, font_subset->subset_id);
5101 status = _cairo_type1_fallback_init_binary (&subset, name, font_subset);
5102 if (unlikely (status))
5105 status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
5107 _cairo_type1_fallback_fini (&subset);
5111 static cairo_status_t
5112 _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
5113 cairo_scaled_font_subset_t *font_subset)
5115 cairo_pdf_resource_t stream, descriptor, cidfont_dict;
5116 cairo_pdf_resource_t subset_resource, to_unicode_stream;
5117 cairo_status_t status;
5118 cairo_pdf_font_t font;
5119 cairo_truetype_subset_t subset;
5120 unsigned int i, last_glyph;
5123 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
5124 font_subset->font_id,
5125 font_subset->subset_id);
5126 if (subset_resource.id == 0)
5127 return CAIRO_STATUS_SUCCESS;
5129 status = _cairo_truetype_subset_init_pdf (&subset, font_subset);
5130 if (unlikely (status))
5133 _create_font_subset_tag (font_subset, subset.ps_name, tag);
5135 status = _cairo_pdf_surface_open_stream (surface,
5139 subset.data_length);
5140 if (unlikely (status)) {
5141 _cairo_truetype_subset_fini (&subset);
5145 stream = surface->pdf_stream.self;
5146 _cairo_output_stream_write (surface->output,
5147 subset.data, subset.data_length);
5148 status = _cairo_pdf_surface_close_stream (surface);
5149 if (unlikely (status)) {
5150 _cairo_truetype_subset_fini (&subset);
5154 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
5156 &to_unicode_stream);
5157 if (_cairo_status_is_error (status)) {
5158 _cairo_truetype_subset_fini (&subset);
5162 descriptor = _cairo_pdf_surface_new_object (surface);
5163 if (descriptor.id == 0) {
5164 _cairo_truetype_subset_fini (&subset);
5165 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5168 _cairo_output_stream_printf (surface->output,
5170 "<< /Type /FontDescriptor\n"
5171 " /FontName /%s+%s\n",
5176 if (subset.family_name_utf8) {
5179 status = _utf8_to_pdf_string (subset.family_name_utf8, &pdf_str);
5180 if (unlikely (status))
5183 _cairo_output_stream_printf (surface->output,
5184 " /FontFamily %s\n",
5189 _cairo_output_stream_printf (surface->output,
5191 " /FontBBox [ %ld %ld %ld %ld ]\n"
5198 " /FontFile2 %u 0 R\n"
5201 font_subset->is_latin ? 32 : 4,
5202 (long)(subset.x_min*PDF_UNITS_PER_EM),
5203 (long)(subset.y_min*PDF_UNITS_PER_EM),
5204 (long)(subset.x_max*PDF_UNITS_PER_EM),
5205 (long)(subset.y_max*PDF_UNITS_PER_EM),
5206 (long)(subset.ascent*PDF_UNITS_PER_EM),
5207 (long)(subset.descent*PDF_UNITS_PER_EM),
5208 (long)(subset.y_max*PDF_UNITS_PER_EM),
5211 if (font_subset->is_latin) {
5212 /* find last glyph used */
5213 for (i = 255; i >= 32; i--)
5214 if (font_subset->latin_to_subset_glyph_index[i] > 0)
5218 _cairo_pdf_surface_update_object (surface, subset_resource);
5219 _cairo_output_stream_printf (surface->output,
5222 " /Subtype /TrueType\n"
5223 " /BaseFont /%s+%s\n"
5226 " /FontDescriptor %d 0 R\n"
5227 " /Encoding /WinAnsiEncoding\n"
5235 for (i = 32; i < last_glyph + 1; i++) {
5236 int glyph = font_subset->latin_to_subset_glyph_index[i];
5238 _cairo_output_stream_printf (surface->output,
5240 (long)(subset.widths[glyph]*PDF_UNITS_PER_EM));
5242 _cairo_output_stream_printf (surface->output, " 0");
5246 _cairo_output_stream_printf (surface->output,
5249 if (to_unicode_stream.id != 0)
5250 _cairo_output_stream_printf (surface->output,
5251 " /ToUnicode %d 0 R\n",
5252 to_unicode_stream.id);
5254 _cairo_output_stream_printf (surface->output,
5258 cidfont_dict = _cairo_pdf_surface_new_object (surface);
5259 if (cidfont_dict.id == 0) {
5260 _cairo_truetype_subset_fini (&subset);
5261 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5264 _cairo_output_stream_printf (surface->output,
5267 " /Subtype /CIDFontType2\n"
5268 " /BaseFont /%s+%s\n"
5270 " << /Registry (Adobe)\n"
5271 " /Ordering (Identity)\n"
5274 " /FontDescriptor %d 0 R\n"
5281 for (i = 0; i < font_subset->num_glyphs; i++)
5282 _cairo_output_stream_printf (surface->output,
5284 (long)(subset.widths[i]*PDF_UNITS_PER_EM));
5286 _cairo_output_stream_printf (surface->output,
5291 _cairo_pdf_surface_update_object (surface, subset_resource);
5292 _cairo_output_stream_printf (surface->output,
5295 " /Subtype /Type0\n"
5296 " /BaseFont /%s+%s\n"
5297 " /Encoding /Identity-H\n"
5298 " /DescendantFonts [ %d 0 R]\n",
5304 if (to_unicode_stream.id != 0)
5305 _cairo_output_stream_printf (surface->output,
5306 " /ToUnicode %d 0 R\n",
5307 to_unicode_stream.id);
5309 _cairo_output_stream_printf (surface->output,
5314 font.font_id = font_subset->font_id;
5315 font.subset_id = font_subset->subset_id;
5316 font.subset_resource = subset_resource;
5317 status = _cairo_array_append (&surface->fonts, &font);
5319 _cairo_truetype_subset_fini (&subset);
5324 static cairo_status_t
5325 _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
5326 cairo_output_stream_t *stream)
5328 uint8_t *byte, output_byte;
5329 int row, col, num_cols;
5331 /* The only image type supported by Type 3 fonts are 1-bit image
5333 assert (image->format == CAIRO_FORMAT_A1);
5335 _cairo_output_stream_printf (stream,
5345 _cairo_output_stream_printf (stream,
5348 num_cols = (image->width + 7) / 8;
5349 for (row = 0; row < image->height; row++) {
5350 byte = image->data + row * image->stride;
5351 for (col = 0; col < num_cols; col++) {
5352 output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
5353 _cairo_output_stream_write (stream, &output_byte, 1);
5358 _cairo_output_stream_printf (stream,
5361 return _cairo_output_stream_get_status (stream);
5364 static cairo_int_status_t
5365 _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
5368 cairo_pdf_surface_t *surface = closure;
5369 cairo_status_t status = CAIRO_STATUS_SUCCESS;
5370 cairo_status_t status2;
5372 cairo_surface_t *type3_surface;
5373 cairo_output_stream_t *null_stream;
5375 null_stream = _cairo_null_stream_create ();
5376 type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
5378 _cairo_pdf_emit_imagemask,
5379 surface->font_subsets);
5380 if (unlikely (type3_surface->status)) {
5381 status2 = _cairo_output_stream_destroy (null_stream);
5382 return type3_surface->status;
5385 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
5386 _cairo_pdf_surface_add_font,
5389 for (i = 0; i < font_subset->num_glyphs; i++) {
5390 status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
5391 font_subset->glyphs[i]);
5392 if (unlikely (status))
5396 cairo_surface_destroy (type3_surface);
5397 status2 = _cairo_output_stream_destroy (null_stream);
5398 if (status == CAIRO_STATUS_SUCCESS)
5404 static cairo_int_status_t
5405 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
5406 cairo_scaled_font_subset_t *font_subset)
5408 cairo_status_t status = CAIRO_STATUS_SUCCESS;
5409 cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
5410 cairo_pdf_font_t font;
5413 cairo_box_t font_bbox = {{0,0},{0,0}};
5414 cairo_box_t bbox = {{0,0},{0,0}};
5415 cairo_surface_t *type3_surface;
5417 if (font_subset->num_glyphs == 0)
5418 return CAIRO_STATUS_SUCCESS;
5420 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
5421 font_subset->font_id,
5422 font_subset->subset_id);
5423 if (subset_resource.id == 0)
5424 return CAIRO_STATUS_SUCCESS;
5426 glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
5427 if (unlikely (glyphs == NULL))
5428 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5430 widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
5431 if (unlikely (widths == NULL)) {
5433 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5436 _cairo_pdf_group_resources_clear (&surface->resources);
5437 type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
5439 _cairo_pdf_emit_imagemask,
5440 surface->font_subsets);
5441 if (unlikely (type3_surface->status)) {
5444 return type3_surface->status;
5447 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
5448 _cairo_pdf_surface_add_font,
5451 for (i = 0; i < font_subset->num_glyphs; i++) {
5452 status = _cairo_pdf_surface_open_stream (surface,
5454 surface->compress_content,
5456 if (unlikely (status))
5459 glyphs[i] = surface->pdf_stream.self;
5460 status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
5462 font_subset->glyphs[i],
5465 if (unlikely (status))
5468 status = _cairo_pdf_surface_close_stream (surface);
5469 if (unlikely (status))
5473 font_bbox.p1.x = bbox.p1.x;
5474 font_bbox.p1.y = bbox.p1.y;
5475 font_bbox.p2.x = bbox.p2.x;
5476 font_bbox.p2.y = bbox.p2.y;
5478 if (bbox.p1.x < font_bbox.p1.x)
5479 font_bbox.p1.x = bbox.p1.x;
5480 if (bbox.p1.y < font_bbox.p1.y)
5481 font_bbox.p1.y = bbox.p1.y;
5482 if (bbox.p2.x > font_bbox.p2.x)
5483 font_bbox.p2.x = bbox.p2.x;
5484 if (bbox.p2.y > font_bbox.p2.y)
5485 font_bbox.p2.y = bbox.p2.y;
5488 cairo_surface_destroy (type3_surface);
5489 if (unlikely (status)) {
5495 encoding = _cairo_pdf_surface_new_object (surface);
5496 if (encoding.id == 0) {
5499 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5502 _cairo_output_stream_printf (surface->output,
5504 "<< /Type /Encoding\n"
5505 " /Differences [0", encoding.id);
5506 for (i = 0; i < font_subset->num_glyphs; i++)
5507 _cairo_output_stream_printf (surface->output,
5509 _cairo_output_stream_printf (surface->output,
5514 char_procs = _cairo_pdf_surface_new_object (surface);
5515 if (char_procs.id == 0) {
5518 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5521 _cairo_output_stream_printf (surface->output,
5523 "<<\n", char_procs.id);
5524 for (i = 0; i < font_subset->num_glyphs; i++)
5525 _cairo_output_stream_printf (surface->output,
5528 _cairo_output_stream_printf (surface->output,
5534 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
5536 &to_unicode_stream);
5537 if (_cairo_status_is_error (status)) {
5542 _cairo_pdf_surface_update_object (surface, subset_resource);
5543 _cairo_output_stream_printf (surface->output,
5546 " /Subtype /Type3\n"
5547 " /FontBBox [%f %f %f %f]\n"
5548 " /FontMatrix [ 1 0 0 1 0 0 ]\n"
5549 " /Encoding %d 0 R\n"
5550 " /CharProcs %d 0 R\n"
5554 _cairo_fixed_to_double (font_bbox.p1.x),
5555 - _cairo_fixed_to_double (font_bbox.p2.y),
5556 _cairo_fixed_to_double (font_bbox.p2.x),
5557 - _cairo_fixed_to_double (font_bbox.p1.y),
5560 font_subset->num_glyphs - 1);
5562 _cairo_output_stream_printf (surface->output,
5564 for (i = 0; i < font_subset->num_glyphs; i++)
5565 _cairo_output_stream_printf (surface->output, " %f", widths[i]);
5566 _cairo_output_stream_printf (surface->output,
5570 _cairo_output_stream_printf (surface->output,
5572 _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
5574 if (to_unicode_stream.id != 0)
5575 _cairo_output_stream_printf (surface->output,
5576 " /ToUnicode %d 0 R\n",
5577 to_unicode_stream.id);
5579 _cairo_output_stream_printf (surface->output,
5583 font.font_id = font_subset->font_id;
5584 font.subset_id = font_subset->subset_id;
5585 font.subset_resource = subset_resource;
5586 return _cairo_array_append (&surface->fonts, &font);
5589 static cairo_int_status_t
5590 _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
5593 cairo_pdf_surface_t *surface = closure;
5594 cairo_int_status_t status;
5596 status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
5597 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5600 status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
5601 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5604 status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
5605 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5608 status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
5609 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5612 status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
5613 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5617 return CAIRO_INT_STATUS_SUCCESS;
5620 static cairo_int_status_t
5621 _cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
5624 cairo_pdf_surface_t *surface = closure;
5625 cairo_int_status_t status;
5627 status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
5628 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5632 return CAIRO_INT_STATUS_SUCCESS;
5635 static cairo_status_t
5636 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
5638 cairo_status_t status;
5640 status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
5641 _cairo_pdf_surface_analyze_user_font_subset,
5643 if (unlikely (status))
5646 status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
5647 _cairo_pdf_surface_emit_unscaled_font_subset,
5649 if (unlikely (status))
5652 status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
5653 _cairo_pdf_surface_emit_scaled_font_subset,
5655 if (unlikely (status))
5658 status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
5659 _cairo_pdf_surface_emit_scaled_font_subset,
5663 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
5664 surface->font_subsets = NULL;
5669 static cairo_pdf_resource_t
5670 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface)
5672 cairo_pdf_resource_t catalog;
5674 catalog = _cairo_pdf_surface_new_object (surface);
5675 if (catalog.id == 0)
5678 _cairo_output_stream_printf (surface->output,
5680 "<< /Type /Catalog\n"
5685 surface->pages_resource.id);
5691 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
5693 cairo_pdf_object_t *object;
5698 num_objects = _cairo_array_num_elements (&surface->objects);
5700 offset = _cairo_output_stream_get_position (surface->output);
5701 _cairo_output_stream_printf (surface->output,
5704 0, num_objects + 1);
5706 _cairo_output_stream_printf (surface->output,
5707 "0000000000 65535 f \n");
5708 for (i = 0; i < num_objects; i++) {
5709 object = _cairo_array_index (&surface->objects, i);
5710 snprintf (buffer, sizeof buffer, "%010ld", object->offset);
5711 _cairo_output_stream_printf (surface->output,
5712 "%s 00000 n \n", buffer);
5718 static cairo_status_t
5719 _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
5720 cairo_pdf_smask_group_t *group)
5722 cairo_pdf_resource_t mask_group;
5723 cairo_pdf_resource_t smask;
5724 cairo_pdf_smask_group_t *smask_group;
5725 cairo_pdf_resource_t pattern_res, gstate_res;
5726 cairo_status_t status;
5727 cairo_box_double_t bbox;
5729 /* Create mask group */
5730 _get_bbox_from_extents (group->height, &group->extents, &bbox);
5731 status = _cairo_pdf_surface_open_group (surface, &bbox, NULL);
5732 if (unlikely (status))
5735 if (_can_paint_pattern (group->mask)) {
5736 _cairo_output_stream_printf (surface->output, "q\n");
5737 status = _cairo_pdf_surface_paint_pattern (surface,
5741 if (unlikely (status))
5744 _cairo_output_stream_printf (surface->output, "Q\n");
5748 status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, NULL,
5749 &pattern_res, &gstate_res);
5750 if (unlikely (status))
5753 if (gstate_res.id != 0) {
5754 smask_group = _cairo_pdf_surface_create_smask_group (surface, &group->extents);
5755 if (unlikely (smask_group == NULL))
5756 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5758 smask_group->width = group->width;
5759 smask_group->height = group->height;
5760 smask_group->operation = PDF_PAINT;
5761 smask_group->source = cairo_pattern_reference (group->mask);
5762 smask_group->source_res = pattern_res;
5763 status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
5764 if (unlikely (status)) {
5765 _cairo_pdf_smask_group_destroy (smask_group);
5769 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5770 if (unlikely (status))
5773 status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
5774 if (unlikely (status))
5777 _cairo_output_stream_printf (surface->output,
5778 "q /s%d gs /x%d Do Q\n",
5780 smask_group->group_res.id);
5782 status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE);
5783 if (unlikely (status))
5786 _cairo_output_stream_printf (surface->output,
5787 "%f %f %f %f re f\n",
5790 bbox.p2.x - bbox.p1.x,
5791 bbox.p2.y - bbox.p1.y);
5793 status = _cairo_pdf_surface_unselect_pattern (surface);
5794 if (unlikely (status))
5799 status = _cairo_pdf_surface_close_group (surface, &mask_group);
5800 if (unlikely (status))
5803 /* Create source group */
5804 status = _cairo_pdf_surface_open_group (surface, &bbox, &group->source_res);
5805 if (unlikely (status))
5808 if (_can_paint_pattern (group->source)) {
5809 _cairo_output_stream_printf (surface->output, "q\n");
5810 status = _cairo_pdf_surface_paint_pattern (surface,
5814 if (unlikely (status))
5817 _cairo_output_stream_printf (surface->output, "Q\n");
5821 status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, NULL,
5822 &pattern_res, &gstate_res);
5823 if (unlikely (status))
5826 if (gstate_res.id != 0) {
5827 smask_group = _cairo_pdf_surface_create_smask_group (surface, &group->extents);
5828 if (unlikely (smask_group == NULL))
5829 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5831 smask_group->operation = PDF_PAINT;
5832 smask_group->source = cairo_pattern_reference (group->source);
5833 smask_group->source_res = pattern_res;
5834 status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
5835 if (unlikely (status)) {
5836 _cairo_pdf_smask_group_destroy (smask_group);
5840 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5841 if (unlikely (status))
5844 status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
5845 if (unlikely (status))
5848 _cairo_output_stream_printf (surface->output,
5849 "q /s%d gs /x%d Do Q\n",
5851 smask_group->group_res.id);
5853 status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE);
5854 if (unlikely (status))
5857 _cairo_output_stream_printf (surface->output,
5858 "%f %f %f %f re f\n",
5861 bbox.p2.x - bbox.p1.x,
5862 bbox.p2.y - bbox.p1.y);
5864 status = _cairo_pdf_surface_unselect_pattern (surface);
5865 if (unlikely (status))
5870 status = _cairo_pdf_surface_close_group (surface, NULL);
5871 if (unlikely (status))
5874 /* Create an smask based on the alpha component of mask_group */
5875 smask = _cairo_pdf_surface_new_object (surface);
5877 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5879 _cairo_output_stream_printf (surface->output,
5889 /* Create a GState that uses the smask */
5890 _cairo_pdf_surface_update_object (surface, group->group_res);
5891 _cairo_output_stream_printf (surface->output,
5893 "<< /Type /ExtGState\n"
5900 group->group_res.id,
5903 return _cairo_output_stream_get_status (surface->output);
5906 static cairo_status_t
5907 _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
5908 cairo_pdf_smask_group_t *group)
5910 double old_width, old_height;
5911 cairo_status_t status;
5912 cairo_box_double_t bbox;
5914 old_width = surface->width;
5915 old_height = surface->height;
5916 _cairo_pdf_surface_set_size_internal (surface,
5919 /* _mask is a special case that requires two groups - source
5920 * and mask as well as a smask and gstate dictionary */
5921 if (group->operation == PDF_MASK) {
5922 status = _cairo_pdf_surface_write_mask_group (surface, group);
5926 _get_bbox_from_extents (group->height, &group->extents, &bbox);
5927 status = _cairo_pdf_surface_open_group (surface, &bbox, &group->group_res);
5928 if (unlikely (status))
5931 status = _cairo_pdf_surface_select_pattern (surface,
5934 group->operation == PDF_STROKE);
5935 if (unlikely (status))
5938 switch (group->operation) {
5940 _cairo_output_stream_printf (surface->output,
5942 surface->width, surface->height);
5948 status = _cairo_pdf_operators_fill (&surface->pdf_operators,
5953 status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
5957 &group->ctm_inverse);
5959 case PDF_SHOW_GLYPHS:
5960 status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
5961 group->utf8, group->utf8_len,
5962 group->glyphs, group->num_glyphs,
5963 group->clusters, group->num_clusters,
5964 group->cluster_flags,
5965 group->scaled_font);
5968 if (unlikely (status))
5971 status = _cairo_pdf_surface_unselect_pattern (surface);
5972 if (unlikely (status))
5975 status = _cairo_pdf_surface_close_group (surface, NULL);
5978 _cairo_pdf_surface_set_size_internal (surface,
5985 static cairo_status_t
5986 _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface)
5988 cairo_pdf_pattern_t pattern;
5989 cairo_pdf_smask_group_t *group;
5990 cairo_pdf_source_surface_t src_surface;
5991 unsigned int pattern_index, group_index, surface_index;
5992 cairo_status_t status;
5994 /* Writing out PDF_MASK groups will cause additional smask groups
5995 * to be appended to surface->smask_groups. Additional patterns
5996 * may also be appended to surface->patterns.
5998 * Writing recording surface patterns will cause additional patterns
5999 * and groups to be appended.
6004 while ((pattern_index < _cairo_array_num_elements (&surface->page_patterns)) ||
6005 (group_index < _cairo_array_num_elements (&surface->smask_groups)) ||
6006 (surface_index < _cairo_array_num_elements (&surface->page_surfaces)))
6008 for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) {
6009 _cairo_array_copy_element (&surface->smask_groups, group_index, &group);
6010 status = _cairo_pdf_surface_write_smask_group (surface, group);
6011 if (unlikely (status))
6015 for (; pattern_index < _cairo_array_num_elements (&surface->page_patterns); pattern_index++) {
6016 _cairo_array_copy_element (&surface->page_patterns, pattern_index, &pattern);
6017 status = _cairo_pdf_surface_emit_pattern (surface, &pattern);
6018 if (unlikely (status))
6022 for (; surface_index < _cairo_array_num_elements (&surface->page_surfaces); surface_index++) {
6023 _cairo_array_copy_element (&surface->page_surfaces, surface_index, &src_surface);
6024 status = _cairo_pdf_surface_emit_surface (surface, &src_surface);
6025 if (unlikely (status))
6030 return CAIRO_STATUS_SUCCESS;
6033 static cairo_status_t
6034 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
6036 cairo_pdf_resource_t page, knockout, res;
6037 cairo_status_t status;
6038 unsigned int i, len;
6040 _cairo_pdf_group_resources_clear (&surface->resources);
6041 if (surface->has_fallback_images) {
6042 cairo_rectangle_int_t extents;
6043 cairo_box_double_t bbox;
6047 extents.width = ceil (surface->width);
6048 extents.height = ceil (surface->height);
6049 _get_bbox_from_extents (surface->height, &extents, &bbox);
6050 status = _cairo_pdf_surface_open_knockout_group (surface, &bbox);
6051 if (unlikely (status))
6054 len = _cairo_array_num_elements (&surface->knockout_group);
6055 for (i = 0; i < len; i++) {
6056 _cairo_array_copy_element (&surface->knockout_group, i, &res);
6057 _cairo_output_stream_printf (surface->output,
6060 status = _cairo_pdf_surface_add_xobject (surface, res);
6061 if (unlikely (status))
6064 _cairo_output_stream_printf (surface->output,
6066 surface->content.id);
6067 status = _cairo_pdf_surface_add_xobject (surface, surface->content);
6068 if (unlikely (status))
6071 status = _cairo_pdf_surface_close_group (surface, &knockout);
6072 if (unlikely (status))
6075 _cairo_pdf_group_resources_clear (&surface->resources);
6076 status = _cairo_pdf_surface_open_content_stream (surface, NULL, NULL, FALSE);
6077 if (unlikely (status))
6080 _cairo_output_stream_printf (surface->output,
6083 status = _cairo_pdf_surface_add_xobject (surface, knockout);
6084 if (unlikely (status))
6087 status = _cairo_pdf_surface_close_content_stream (surface);
6088 if (unlikely (status))
6092 page = _cairo_pdf_surface_new_object (surface);
6094 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6096 _cairo_output_stream_printf (surface->output,
6100 " /MediaBox [ 0 0 %f %f ]\n"
6101 " /Contents %d 0 R\n"
6104 " /S /Transparency\n"
6108 " /Resources %d 0 R\n"
6112 surface->pages_resource.id,
6115 surface->content.id,
6116 surface->content_resources.id);
6118 status = _cairo_array_append (&surface->pages, &page);
6119 if (unlikely (status))
6122 status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface);
6123 if (unlikely (status))
6126 return CAIRO_STATUS_SUCCESS;
6129 static cairo_int_status_t
6130 _cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t *surface,
6131 cairo_surface_pattern_t *pattern)
6133 cairo_image_surface_t *image;
6135 cairo_int_status_t status;
6136 cairo_image_transparency_t transparency;
6138 status = _cairo_surface_acquire_source_image (pattern->surface,
6141 if (unlikely (status))
6144 if (image->base.status)
6145 return image->base.status;
6147 transparency = _cairo_image_analyze_transparency (image);
6148 if (transparency == CAIRO_IMAGE_IS_OPAQUE)
6149 status = CAIRO_STATUS_SUCCESS;
6151 status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
6153 _cairo_surface_release_source_image (pattern->surface, image, image_extra);
6159 _surface_pattern_supported (cairo_surface_pattern_t *pattern)
6161 cairo_extend_t extend;
6163 if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
6166 if (pattern->surface->backend->acquire_source_image == NULL)
6169 /* Does an ALPHA-only source surface even make sense? Maybe, but I
6170 * don't think it's worth the extra code to support it. */
6172 /* XXX: Need to write this function here...
6173 content = cairo_surface_get_content (pattern->surface);
6174 if (content == CAIRO_CONTENT_ALPHA)
6178 extend = cairo_pattern_get_extend (&pattern->base);
6180 case CAIRO_EXTEND_NONE:
6181 case CAIRO_EXTEND_REPEAT:
6182 case CAIRO_EXTEND_REFLECT:
6183 /* There's no point returning FALSE for EXTEND_PAD, as the image
6184 * surface does not currently implement it either */
6185 case CAIRO_EXTEND_PAD:
6194 _pattern_supported (const cairo_pattern_t *pattern)
6196 switch (pattern->type) {
6197 case CAIRO_PATTERN_TYPE_SOLID:
6198 case CAIRO_PATTERN_TYPE_LINEAR:
6199 case CAIRO_PATTERN_TYPE_RADIAL:
6200 case CAIRO_PATTERN_TYPE_MESH:
6201 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
6204 case CAIRO_PATTERN_TYPE_SURFACE:
6205 return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
6214 _pdf_operator_supported (cairo_operator_t op)
6217 case CAIRO_OPERATOR_OVER:
6218 case CAIRO_OPERATOR_MULTIPLY:
6219 case CAIRO_OPERATOR_SCREEN:
6220 case CAIRO_OPERATOR_OVERLAY:
6221 case CAIRO_OPERATOR_DARKEN:
6222 case CAIRO_OPERATOR_LIGHTEN:
6223 case CAIRO_OPERATOR_COLOR_DODGE:
6224 case CAIRO_OPERATOR_COLOR_BURN:
6225 case CAIRO_OPERATOR_HARD_LIGHT:
6226 case CAIRO_OPERATOR_SOFT_LIGHT:
6227 case CAIRO_OPERATOR_DIFFERENCE:
6228 case CAIRO_OPERATOR_EXCLUSION:
6229 case CAIRO_OPERATOR_HSL_HUE:
6230 case CAIRO_OPERATOR_HSL_SATURATION:
6231 case CAIRO_OPERATOR_HSL_COLOR:
6232 case CAIRO_OPERATOR_HSL_LUMINOSITY:
6236 case CAIRO_OPERATOR_CLEAR:
6237 case CAIRO_OPERATOR_SOURCE:
6238 case CAIRO_OPERATOR_IN:
6239 case CAIRO_OPERATOR_OUT:
6240 case CAIRO_OPERATOR_ATOP:
6241 case CAIRO_OPERATOR_DEST:
6242 case CAIRO_OPERATOR_DEST_OVER:
6243 case CAIRO_OPERATOR_DEST_IN:
6244 case CAIRO_OPERATOR_DEST_OUT:
6245 case CAIRO_OPERATOR_DEST_ATOP:
6246 case CAIRO_OPERATOR_XOR:
6247 case CAIRO_OPERATOR_ADD:
6248 case CAIRO_OPERATOR_SATURATE:
6253 static cairo_int_status_t
6254 _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
6255 cairo_operator_t op,
6256 const cairo_pattern_t *pattern,
6257 const cairo_rectangle_int_t *extents)
6259 if (surface->force_fallbacks &&
6260 surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
6262 return CAIRO_INT_STATUS_UNSUPPORTED;
6265 if (! _pattern_supported (pattern))
6266 return CAIRO_INT_STATUS_UNSUPPORTED;
6268 if (_pdf_operator_supported (op)) {
6269 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
6270 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
6272 if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
6273 if (pattern->extend == CAIRO_EXTEND_PAD)
6274 return CAIRO_INT_STATUS_UNSUPPORTED;
6276 return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
6280 return CAIRO_STATUS_SUCCESS;
6284 /* The SOURCE operator is supported if the pattern is opaque or if
6285 * there is nothing painted underneath. */
6286 if (op == CAIRO_OPERATOR_SOURCE) {
6287 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
6288 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
6290 if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
6291 if (_cairo_pattern_is_opaque (pattern, extents)) {
6292 return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
6294 /* FIXME: The analysis surface does not yet have
6295 * the capability to analyze a non opaque recording
6296 * surface and mark it supported if there is
6297 * nothing underneath. For now recording surfaces of
6298 * type CONTENT_COLOR_ALPHA painted with
6299 * OPERATOR_SOURCE will result in a fallback
6302 return CAIRO_INT_STATUS_UNSUPPORTED;
6305 return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
6310 if (_cairo_pattern_is_opaque (pattern, extents))
6311 return CAIRO_STATUS_SUCCESS;
6313 return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
6316 return CAIRO_INT_STATUS_UNSUPPORTED;
6320 _cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
6321 cairo_operator_t op,
6322 const cairo_pattern_t *pattern,
6323 const cairo_rectangle_int_t *extents)
6325 return _cairo_pdf_surface_analyze_operation (surface, op, pattern, extents) != CAIRO_INT_STATUS_UNSUPPORTED;
6328 static cairo_int_status_t
6329 _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
6331 cairo_box_double_t bbox;
6332 cairo_status_t status;
6334 status = _cairo_pdf_surface_close_content_stream (surface);
6335 if (unlikely (status))
6338 status = _cairo_array_append (&surface->knockout_group, &surface->content);
6339 if (unlikely (status))
6342 _cairo_pdf_group_resources_clear (&surface->resources);
6345 bbox.p2.x = surface->width;
6346 bbox.p2.y = surface->height;
6347 return _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, TRUE);
6350 /* A PDF stencil mask is an A1 mask used with the current color */
6351 static cairo_int_status_t
6352 _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface,
6353 const cairo_pattern_t *source,
6354 const cairo_pattern_t *mask,
6355 const cairo_rectangle_int_t *extents)
6357 cairo_status_t status;
6358 cairo_image_surface_t *image;
6360 cairo_image_transparency_t transparency;
6361 cairo_pdf_resource_t pattern_res = {0};
6363 if (! (source->type == CAIRO_PATTERN_TYPE_SOLID &&
6364 (mask->type == CAIRO_PATTERN_TYPE_SURFACE || mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)))
6365 return CAIRO_INT_STATUS_UNSUPPORTED;
6367 if (mask->type == CAIRO_PATTERN_TYPE_SURFACE &&
6368 ((cairo_surface_pattern_t *) mask)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
6370 return CAIRO_INT_STATUS_UNSUPPORTED;
6373 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, mask, extents,
6374 &image, &image_extra);
6375 if (unlikely (status))
6378 if (image->base.status)
6379 return image->base.status;
6381 transparency = _cairo_image_analyze_transparency (image);
6382 if (transparency != CAIRO_IMAGE_IS_OPAQUE &&
6383 transparency != CAIRO_IMAGE_HAS_BILEVEL_ALPHA)
6385 status = CAIRO_INT_STATUS_UNSUPPORTED;
6389 status = _cairo_pdf_surface_select_pattern (surface, source,
6390 pattern_res, FALSE);
6391 if (unlikely (status))
6394 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6395 if (unlikely (status))
6398 _cairo_output_stream_printf (surface->output, "q\n");
6399 status = _cairo_pdf_surface_paint_surface_pattern (surface, mask, NULL, TRUE);
6400 if (unlikely (status))
6403 _cairo_output_stream_printf (surface->output, "Q\n");
6405 status = _cairo_output_stream_get_status (surface->output);
6408 _cairo_pdf_surface_release_source_image_from_pattern (surface, mask, image, image_extra);
6413 static cairo_int_status_t
6414 _cairo_pdf_surface_set_clip (cairo_pdf_surface_t *surface,
6415 cairo_composite_rectangles_t *composite)
6417 cairo_clip_t *clip = composite->clip;
6419 if (_cairo_composite_rectangles_can_reduce_clip (composite, clip))
6423 if (_cairo_composite_rectangles_can_reduce_clip (composite,
6424 surface->clipper.clip))
6425 return CAIRO_STATUS_SUCCESS;
6428 return _cairo_surface_clipper_set_clip (&surface->clipper, clip);
6431 static cairo_int_status_t
6432 _cairo_pdf_surface_paint (void *abstract_surface,
6433 cairo_operator_t op,
6434 const cairo_pattern_t *source,
6435 const cairo_clip_t *clip)
6437 cairo_pdf_surface_t *surface = abstract_surface;
6438 cairo_pdf_smask_group_t *group;
6439 cairo_pdf_resource_t pattern_res, gstate_res;
6440 cairo_composite_rectangles_t extents;
6441 cairo_int_status_t status;
6443 status = _cairo_composite_rectangles_init_for_paint (&extents,
6446 if (unlikely (status))
6449 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
6450 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
6452 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
6453 status = _cairo_pdf_surface_start_fallback (surface);
6454 if (unlikely (status))
6458 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
6460 status = _cairo_pdf_surface_set_clip (surface, &extents);
6461 if (unlikely (status))
6464 status = _cairo_pdf_surface_select_operator (surface, op);
6465 if (unlikely (status))
6468 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6469 if (unlikely (status))
6472 if (_can_paint_pattern (source)) {
6473 _cairo_output_stream_printf (surface->output, "q\n");
6474 status = _cairo_pdf_surface_paint_pattern (surface,
6478 if (unlikely (status))
6481 _cairo_output_stream_printf (surface->output, "Q\n");
6482 _cairo_composite_rectangles_fini (&extents);
6483 return _cairo_output_stream_get_status (surface->output);
6488 status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
6490 &pattern_res, &gstate_res);
6491 if (unlikely (status))
6494 if (gstate_res.id != 0) {
6495 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
6496 if (unlikely (group == NULL)) {
6497 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
6501 group->operation = PDF_PAINT;
6502 status = _cairo_pattern_create_copy (&group->source, source);
6503 if (unlikely (status)) {
6504 _cairo_pdf_smask_group_destroy (group);
6507 group->source_res = pattern_res;
6508 status = _cairo_pdf_surface_add_smask_group (surface, group);
6509 if (unlikely (status)) {
6510 _cairo_pdf_smask_group_destroy (group);
6514 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
6515 if (unlikely (status))
6518 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
6519 if (unlikely (status))
6522 _cairo_output_stream_printf (surface->output,
6523 "q /s%d gs /x%d Do Q\n",
6525 group->group_res.id);
6527 status = _cairo_pdf_surface_select_pattern (surface, source,
6528 pattern_res, FALSE);
6529 if (unlikely (status))
6532 _cairo_output_stream_printf (surface->output,
6534 surface->width, surface->height);
6536 status = _cairo_pdf_surface_unselect_pattern (surface);
6537 if (unlikely (status))
6541 _cairo_composite_rectangles_fini (&extents);
6542 return _cairo_output_stream_get_status (surface->output);
6545 _cairo_composite_rectangles_fini (&extents);
6549 static cairo_int_status_t
6550 _cairo_pdf_surface_mask (void *abstract_surface,
6551 cairo_operator_t op,
6552 const cairo_pattern_t *source,
6553 const cairo_pattern_t *mask,
6554 const cairo_clip_t *clip)
6556 cairo_pdf_surface_t *surface = abstract_surface;
6557 cairo_pdf_smask_group_t *group;
6558 cairo_composite_rectangles_t extents;
6559 cairo_int_status_t status;
6560 cairo_rectangle_int_t r;
6563 status = _cairo_composite_rectangles_init_for_mask (&extents,
6565 op, source, mask, clip);
6566 if (unlikely (status))
6569 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
6570 cairo_status_t source_status, mask_status;
6572 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
6573 if (_cairo_int_status_is_error (status))
6575 source_status = status;
6577 if (mask->has_component_alpha) {
6578 status = CAIRO_INT_STATUS_UNSUPPORTED;
6580 status = _cairo_pdf_surface_analyze_operation (surface, op, mask, &extents.bounded);
6581 if (_cairo_int_status_is_error (status))
6584 mask_status = status;
6586 _cairo_composite_rectangles_fini (&extents);
6587 return _cairo_analysis_surface_merge_status (source_status,
6589 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
6590 status = _cairo_pdf_surface_start_fallback (surface);
6591 if (unlikely (status))
6595 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
6596 assert (_cairo_pdf_surface_operation_supported (surface, op, mask, &extents.bounded));
6598 /* get the accurate extents */
6599 status = _cairo_pattern_get_ink_extents (source, &r);
6600 if (unlikely (status))
6603 /* XXX slight impedance mismatch */
6604 _cairo_box_from_rectangle (&box, &r);
6605 status = _cairo_composite_rectangles_intersect_source_extents (&extents,
6607 if (unlikely (status))
6610 status = _cairo_pattern_get_ink_extents (mask, &r);
6611 if (unlikely (status))
6614 _cairo_box_from_rectangle (&box, &r);
6615 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
6617 if (unlikely (status))
6620 status = _cairo_pdf_surface_set_clip (surface, &extents);
6621 if (unlikely (status))
6624 status = _cairo_pdf_surface_select_operator (surface, op);
6625 if (unlikely (status))
6628 /* Check if we can use a stencil mask */
6629 status = _cairo_pdf_surface_emit_stencil_mask (surface, source, mask, &extents.bounded);
6630 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
6633 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
6634 if (unlikely (group == NULL)) {
6635 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
6639 group->operation = PDF_MASK;
6640 status = _cairo_pattern_create_copy (&group->source, source);
6641 if (unlikely (status)) {
6642 _cairo_pdf_smask_group_destroy (group);
6645 status = _cairo_pattern_create_copy (&group->mask, mask);
6646 if (unlikely (status)) {
6647 _cairo_pdf_smask_group_destroy (group);
6650 group->source_res = _cairo_pdf_surface_new_object (surface);
6651 if (group->source_res.id == 0) {
6652 _cairo_pdf_smask_group_destroy (group);
6653 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
6657 status = _cairo_pdf_surface_add_smask_group (surface, group);
6658 if (unlikely (status)) {
6659 _cairo_pdf_smask_group_destroy (group);
6663 status = _cairo_pdf_surface_add_smask (surface, group->group_res);
6664 if (unlikely (status))
6667 status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
6668 if (unlikely (status))
6671 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6672 if (unlikely (status))
6675 _cairo_output_stream_printf (surface->output,
6676 "q /s%d gs /x%d Do Q\n",
6677 group->group_res.id,
6678 group->source_res.id);
6680 _cairo_composite_rectangles_fini (&extents);
6681 return _cairo_output_stream_get_status (surface->output);
6684 _cairo_composite_rectangles_fini (&extents);
6688 static cairo_int_status_t
6689 _cairo_pdf_surface_stroke (void *abstract_surface,
6690 cairo_operator_t op,
6691 const cairo_pattern_t *source,
6692 const cairo_path_fixed_t *path,
6693 const cairo_stroke_style_t *style,
6694 const cairo_matrix_t *ctm,
6695 const cairo_matrix_t *ctm_inverse,
6697 cairo_antialias_t antialias,
6698 const cairo_clip_t *clip)
6700 cairo_pdf_surface_t *surface = abstract_surface;
6701 cairo_pdf_smask_group_t *group;
6702 cairo_pdf_resource_t pattern_res, gstate_res;
6703 cairo_composite_rectangles_t extents;
6704 cairo_int_status_t status;
6706 status = _cairo_composite_rectangles_init_for_stroke (&extents,
6711 if (unlikely (status))
6714 /* use the more accurate extents */
6715 if (extents.is_bounded) {
6716 cairo_rectangle_int_t mask;
6719 status = _cairo_path_fixed_stroke_extents (path, style,
6723 if (unlikely (status))
6726 _cairo_box_from_rectangle (&box, &mask);
6727 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
6729 if (unlikely (status))
6733 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
6734 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
6738 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
6740 status = _cairo_pdf_surface_set_clip (surface, &extents);
6741 if (unlikely (status))
6746 status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
6748 &pattern_res, &gstate_res);
6749 if (unlikely (status))
6752 status = _cairo_pdf_surface_select_operator (surface, op);
6753 if (unlikely (status))
6756 if (gstate_res.id != 0) {
6757 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
6758 if (unlikely (group == NULL)) {
6759 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
6763 group->operation = PDF_STROKE;
6764 status = _cairo_pattern_create_copy (&group->source, source);
6765 if (unlikely (status)) {
6766 _cairo_pdf_smask_group_destroy (group);
6769 group->source_res = pattern_res;
6770 status = _cairo_path_fixed_init_copy (&group->path, path);
6771 if (unlikely (status)) {
6772 _cairo_pdf_smask_group_destroy (group);
6776 group->style = *style;
6778 group->ctm_inverse = *ctm_inverse;
6779 status = _cairo_pdf_surface_add_smask_group (surface, group);
6780 if (unlikely (status)) {
6781 _cairo_pdf_smask_group_destroy (group);
6785 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
6786 if (unlikely (status))
6789 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
6790 if (unlikely (status))
6793 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6794 if (unlikely (status))
6797 _cairo_output_stream_printf (surface->output,
6798 "q /s%d gs /x%d Do Q\n",
6800 group->group_res.id);
6802 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
6803 if (unlikely (status))
6806 status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
6811 if (unlikely (status))
6814 status = _cairo_pdf_surface_unselect_pattern (surface);
6815 if (unlikely (status))
6819 _cairo_composite_rectangles_fini (&extents);
6820 return _cairo_output_stream_get_status (surface->output);
6823 _cairo_composite_rectangles_fini (&extents);
6827 static cairo_int_status_t
6828 _cairo_pdf_surface_fill (void *abstract_surface,
6829 cairo_operator_t op,
6830 const cairo_pattern_t *source,
6831 const cairo_path_fixed_t*path,
6832 cairo_fill_rule_t fill_rule,
6834 cairo_antialias_t antialias,
6835 const cairo_clip_t *clip)
6837 cairo_pdf_surface_t *surface = abstract_surface;
6838 cairo_int_status_t status;
6839 cairo_pdf_smask_group_t *group;
6840 cairo_pdf_resource_t pattern_res, gstate_res;
6841 cairo_composite_rectangles_t extents;
6843 status = _cairo_composite_rectangles_init_for_fill (&extents,
6847 if (unlikely (status))
6850 /* use the more accurate extents */
6851 if (extents.is_bounded) {
6852 cairo_rectangle_int_t mask;
6855 _cairo_path_fixed_fill_extents (path,
6860 _cairo_box_from_rectangle (&box, &mask);
6861 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
6863 if (unlikely (status))
6867 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
6868 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
6870 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
6871 status = _cairo_pdf_surface_start_fallback (surface);
6872 if (unlikely (status))
6876 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
6878 status = _cairo_pdf_surface_set_clip (surface, &extents);
6879 if (unlikely (status))
6882 status = _cairo_pdf_surface_select_operator (surface, op);
6883 if (unlikely (status))
6886 if (_can_paint_pattern (source)) {
6887 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6888 if (unlikely (status))
6891 _cairo_output_stream_printf (surface->output, "q\n");
6892 status = _cairo_pdf_operators_clip (&surface->pdf_operators,
6895 if (unlikely (status))
6898 status = _cairo_pdf_surface_paint_pattern (surface,
6902 if (unlikely (status))
6905 _cairo_output_stream_printf (surface->output, "Q\n");
6906 status = _cairo_output_stream_get_status (surface->output);
6912 status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
6914 &pattern_res, &gstate_res);
6915 if (unlikely (status))
6918 if (gstate_res.id != 0) {
6919 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
6920 if (unlikely (group == NULL)) {
6921 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
6925 group->operation = PDF_FILL;
6926 status = _cairo_pattern_create_copy (&group->source, source);
6927 if (unlikely (status)) {
6928 _cairo_pdf_smask_group_destroy (group);
6931 group->source_res = pattern_res;
6932 status = _cairo_path_fixed_init_copy (&group->path, path);
6933 if (unlikely (status)) {
6934 _cairo_pdf_smask_group_destroy (group);
6938 group->fill_rule = fill_rule;
6939 status = _cairo_pdf_surface_add_smask_group (surface, group);
6940 if (unlikely (status)) {
6941 _cairo_pdf_smask_group_destroy (group);
6945 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
6946 if (unlikely (status))
6949 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
6950 if (unlikely (status))
6953 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6954 if (unlikely (status))
6957 _cairo_output_stream_printf (surface->output,
6958 "q /s%d gs /x%d Do Q\n",
6960 group->group_res.id);
6962 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
6963 if (unlikely (status))
6966 status = _cairo_pdf_operators_fill (&surface->pdf_operators,
6969 if (unlikely (status))
6972 status = _cairo_pdf_surface_unselect_pattern (surface);
6973 if (unlikely (status))
6977 _cairo_composite_rectangles_fini (&extents);
6978 return _cairo_output_stream_get_status (surface->output);
6981 _cairo_composite_rectangles_fini (&extents);
6985 static cairo_int_status_t
6986 _cairo_pdf_surface_fill_stroke (void *abstract_surface,
6987 cairo_operator_t fill_op,
6988 const cairo_pattern_t *fill_source,
6989 cairo_fill_rule_t fill_rule,
6990 double fill_tolerance,
6991 cairo_antialias_t fill_antialias,
6992 const cairo_path_fixed_t*path,
6993 cairo_operator_t stroke_op,
6994 const cairo_pattern_t *stroke_source,
6995 const cairo_stroke_style_t *stroke_style,
6996 const cairo_matrix_t *stroke_ctm,
6997 const cairo_matrix_t *stroke_ctm_inverse,
6998 double stroke_tolerance,
6999 cairo_antialias_t stroke_antialias,
7000 const cairo_clip_t *clip)
7002 cairo_pdf_surface_t *surface = abstract_surface;
7003 cairo_int_status_t status;
7004 cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res;
7005 cairo_composite_rectangles_t extents;
7007 /* During analysis we return unsupported and let the _fill and
7008 * _stroke functions that are on the fallback path do the analysis
7009 * for us. During render we may still encounter unsupported
7010 * combinations of fill/stroke patterns. However we can return
7011 * unsupported anytime to let the _fill and _stroke functions take
7014 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
7015 return CAIRO_INT_STATUS_UNSUPPORTED;
7017 /* PDF rendering of fill-stroke is not the same as cairo when
7018 * either the fill or stroke is not opaque.
7020 if ( !_cairo_pattern_is_opaque (fill_source, NULL) ||
7021 !_cairo_pattern_is_opaque (stroke_source, NULL))
7023 return CAIRO_INT_STATUS_UNSUPPORTED;
7026 if (fill_op != stroke_op)
7027 return CAIRO_INT_STATUS_UNSUPPORTED;
7029 /* Compute the operation extents using the stroke which will naturally
7030 * be larger than the fill extents.
7032 status = _cairo_composite_rectangles_init_for_stroke (&extents,
7034 stroke_op, stroke_source,
7035 path, stroke_style, stroke_ctm,
7037 if (unlikely (status))
7040 /* use the more accurate extents */
7041 if (extents.is_bounded) {
7042 cairo_rectangle_int_t mask;
7045 status = _cairo_path_fixed_stroke_extents (path, stroke_style,
7046 stroke_ctm, stroke_ctm_inverse,
7049 if (unlikely (status))
7052 _cairo_box_from_rectangle (&box, &mask);
7053 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
7055 if (unlikely (status))
7059 status = _cairo_pdf_surface_set_clip (surface, &extents);
7060 if (unlikely (status))
7063 status = _cairo_pdf_surface_select_operator (surface, fill_op);
7064 if (unlikely (status))
7067 /* use the more accurate extents */
7068 if (extents.is_bounded) {
7069 cairo_rectangle_int_t mask;
7072 _cairo_path_fixed_fill_extents (path,
7077 _cairo_box_from_rectangle (&box, &mask);
7078 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
7080 if (unlikely (status))
7084 fill_pattern_res.id = 0;
7086 status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
7090 if (unlikely (status))
7093 assert (gstate_res.id == 0);
7095 stroke_pattern_res.id = 0;
7097 status = _cairo_pdf_surface_add_pdf_pattern (surface,
7100 &stroke_pattern_res,
7102 if (unlikely (status))
7105 assert (gstate_res.id == 0);
7107 /* As PDF has separate graphics state for fill and stroke we can
7108 * select both at the same time */
7109 status = _cairo_pdf_surface_select_pattern (surface, fill_source,
7110 fill_pattern_res, FALSE);
7111 if (unlikely (status))
7114 status = _cairo_pdf_surface_select_pattern (surface, stroke_source,
7115 stroke_pattern_res, TRUE);
7116 if (unlikely (status))
7119 status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators,
7124 stroke_ctm_inverse);
7125 if (unlikely (status))
7128 status = _cairo_pdf_surface_unselect_pattern (surface);
7129 if (unlikely (status))
7132 _cairo_composite_rectangles_fini (&extents);
7133 return _cairo_output_stream_get_status (surface->output);
7136 _cairo_composite_rectangles_fini (&extents);
7141 _cairo_pdf_surface_has_show_text_glyphs (void *abstract_surface)
7146 static cairo_int_status_t
7147 _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
7148 cairo_operator_t op,
7149 const cairo_pattern_t *source,
7152 cairo_glyph_t *glyphs,
7154 const cairo_text_cluster_t *clusters,
7156 cairo_text_cluster_flags_t cluster_flags,
7157 cairo_scaled_font_t *scaled_font,
7158 const cairo_clip_t *clip)
7160 cairo_pdf_surface_t *surface = abstract_surface;
7161 cairo_pdf_smask_group_t *group;
7162 cairo_pdf_resource_t pattern_res, gstate_res;
7163 cairo_composite_rectangles_t extents;
7164 cairo_bool_t overlap;
7165 cairo_int_status_t status;
7167 status = _cairo_composite_rectangles_init_for_glyphs (&extents,
7174 if (unlikely (status))
7177 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
7178 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
7182 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
7184 status = _cairo_pdf_surface_set_clip (surface, &extents);
7185 if (unlikely (status))
7190 status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
7192 &pattern_res, &gstate_res);
7193 if (unlikely (status))
7196 status = _cairo_pdf_surface_select_operator (surface, op);
7197 if (unlikely (status))
7200 if (gstate_res.id != 0) {
7201 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
7202 if (unlikely (group == NULL)) {
7203 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7207 group->operation = PDF_SHOW_GLYPHS;
7208 status = _cairo_pattern_create_copy (&group->source, source);
7209 if (unlikely (status)) {
7210 _cairo_pdf_smask_group_destroy (group);
7213 group->source_res = pattern_res;
7216 group->utf8 = malloc (utf8_len);
7217 if (unlikely (group->utf8 == NULL)) {
7218 _cairo_pdf_smask_group_destroy (group);
7219 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7222 memcpy (group->utf8, utf8, utf8_len);
7224 group->utf8_len = utf8_len;
7227 group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
7228 if (unlikely (group->glyphs == NULL)) {
7229 _cairo_pdf_smask_group_destroy (group);
7230 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7233 memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
7235 group->num_glyphs = num_glyphs;
7238 group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
7239 if (unlikely (group->clusters == NULL)) {
7240 _cairo_pdf_smask_group_destroy (group);
7241 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7244 memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
7246 group->num_clusters = num_clusters;
7248 group->scaled_font = cairo_scaled_font_reference (scaled_font);
7249 status = _cairo_pdf_surface_add_smask_group (surface, group);
7250 if (unlikely (status)) {
7251 _cairo_pdf_smask_group_destroy (group);
7255 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
7256 if (unlikely (status))
7259 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
7260 if (unlikely (status))
7263 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7264 if (unlikely (status))
7267 _cairo_output_stream_printf (surface->output,
7268 "q /s%d gs /x%d Do Q\n",
7270 group->group_res.id);
7272 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
7273 if (unlikely (status))
7276 /* Each call to show_glyphs() with a transclucent pattern must
7277 * be in a separate text object otherwise overlapping text
7278 * from separate calls to show_glyphs will not composite with
7280 if (! _cairo_pattern_is_opaque (source, &extents.bounded)) {
7281 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7282 if (unlikely (status))
7286 status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
7289 clusters, num_clusters,
7292 if (unlikely (status))
7295 status = _cairo_pdf_surface_unselect_pattern (surface);
7296 if (unlikely (status))
7300 _cairo_composite_rectangles_fini (&extents);
7301 return _cairo_output_stream_get_status (surface->output);
7304 _cairo_composite_rectangles_fini (&extents);
7308 static const char **
7309 _cairo_pdf_surface_get_supported_mime_types (void *abstract_surface)
7311 return _cairo_pdf_supported_mime_types;
7315 _cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
7316 cairo_paginated_mode_t paginated_mode)
7318 cairo_pdf_surface_t *surface = abstract_surface;
7320 surface->paginated_mode = paginated_mode;
7323 static const cairo_surface_backend_t cairo_pdf_surface_backend = {
7324 CAIRO_SURFACE_TYPE_PDF,
7325 _cairo_pdf_surface_finish,
7327 _cairo_default_context_create,
7329 NULL, /* create similar: handled by wrapper */
7330 NULL, /* create similar image */
7331 NULL, /* map to image */
7332 NULL, /* unmap image */
7334 _cairo_surface_default_source,
7335 NULL, /* acquire_source_image */
7336 NULL, /* release_source_image */
7337 NULL, /* snapshot */
7339 NULL, /* _cairo_pdf_surface_copy_page */
7340 _cairo_pdf_surface_show_page,
7342 _cairo_pdf_surface_get_extents,
7343 _cairo_pdf_surface_get_font_options,
7346 NULL, /* mark_dirty_rectangle */
7348 /* Here are the drawing functions */
7349 _cairo_pdf_surface_paint,
7350 _cairo_pdf_surface_mask,
7351 _cairo_pdf_surface_stroke,
7352 _cairo_pdf_surface_fill,
7353 _cairo_pdf_surface_fill_stroke,
7354 NULL, /* show_glyphs */
7355 _cairo_pdf_surface_has_show_text_glyphs,
7356 _cairo_pdf_surface_show_text_glyphs,
7357 _cairo_pdf_surface_get_supported_mime_types,
7360 static const cairo_paginated_surface_backend_t
7361 cairo_pdf_surface_paginated_backend = {
7362 _cairo_pdf_surface_start_page,
7363 _cairo_pdf_surface_set_paginated_mode,
7364 NULL, /* set_bounding_box */
7365 _cairo_pdf_surface_has_fallback_images,
7366 _cairo_pdf_surface_supports_fine_grained_fallbacks,