1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2004 Red Hat, Inc
5 * Copyright © 2006 Red Hat, Inc
6 * Copyright © 2007, 2008 Adrian Johnson
8 * This library is free software; you can redistribute it and/or
9 * modify it either under the terms of the GNU Lesser General Public
10 * License version 2.1 as published by the Free Software Foundation
11 * (the "LGPL") or, at your option, under the terms of the Mozilla
12 * Public License Version 1.1 (the "MPL"). If you do not alter this
13 * notice, a recipient may use your version of this file under either
14 * the MPL or the LGPL.
16 * You should have received a copy of the LGPL along with this library
17 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19 * You should have received a copy of the MPL along with this library
20 * in the file COPYING-MPL-1.1
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License at
25 * http://www.mozilla.org/MPL/
27 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29 * the specific language governing rights and limitations.
31 * The Original Code is the cairo graphics library.
33 * The Initial Developer of the Original Code is University of Southern
37 * Kristian Høgsberg <krh@redhat.com>
38 * Carl Worth <cworth@cworth.org>
39 * Adrian Johnson <ajohnson@redneon.com>
42 #define _BSD_SOURCE /* for snprintf() */
45 #include "cairo-pdf.h"
46 #include "cairo-pdf-surface-private.h"
47 #include "cairo-pdf-operators-private.h"
48 #include "cairo-pdf-shading-private.h"
50 #include "cairo-array-private.h"
51 #include "cairo-analysis-surface-private.h"
52 #include "cairo-composite-rectangles-private.h"
53 #include "cairo-default-context-private.h"
54 #include "cairo-error-private.h"
55 #include "cairo-image-surface-inline.h"
56 #include "cairo-image-info-private.h"
57 #include "cairo-recording-surface-private.h"
58 #include "cairo-output-stream-private.h"
59 #include "cairo-paginated-private.h"
60 #include "cairo-scaled-font-subsets-private.h"
61 #include "cairo-surface-clipper-private.h"
62 #include "cairo-surface-snapshot-inline.h"
63 #include "cairo-surface-subsurface-private.h"
64 #include "cairo-type3-glyph-surface-private.h"
71 * - We embed an image in the stream each time it's composited. We
72 * could add generation counters to surfaces and remember the stream
73 * ID for a particular generation for a particular surface.
75 * - Backend specific meta data.
79 * Page Structure of the Generated PDF:
81 * Each page requiring fallbacks images contains a knockout group at
82 * the top level. The first operation of the knockout group paints a
83 * group containing all the supported drawing operations. Fallback
84 * images (if any) are painted in the knockout group. This ensures
85 * that fallback images do not composite with any content under the
90 * This PDF surface has three types of streams:
95 * Calling _cairo_output_stream_printf (surface->output, ...) will
96 * write to the currently open stream.
99 * A PDF Stream may be opened and closed with the following functions:
100 * _cairo_pdf_surface_open stream ()
101 * _cairo_pdf_surface_close_stream ()
103 * PDF Streams are written directly to the PDF file. They are used for
104 * fonts, images and patterns.
107 * The Content Stream is opened and closed with the following functions:
108 * _cairo_pdf_surface_open_content_stream ()
109 * _cairo_pdf_surface_close_content_stream ()
111 * The Content Stream contains the text and graphics operators.
114 * A Group Stream may be opened and closed with the following functions:
115 * _cairo_pdf_surface_open_group ()
116 * _cairo_pdf_surface_close_group ()
118 * A Group Stream is a Form XObject. It is used for short sequences
119 * of operators. As the content is very short the group is stored in
120 * memory until it is closed. This allows some optimization such as
121 * including the Resource dictionary and stream length inside the
122 * XObject instead of using an indirect object.
127 * @Title: PDF Surfaces
128 * @Short_Description: Rendering PDF documents
129 * @See_Also: #cairo_surface_t
131 * The PDF surface is used to render cairo graphics to Adobe
132 * PDF files and is a multi-page vector surface backend.
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 cairo_image_surface_t **image,
1122 switch (pattern->type) {
1123 case CAIRO_PATTERN_TYPE_SURFACE: {
1124 cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
1125 return _cairo_surface_acquire_source_image (surf_pat->surface, image, image_extra);
1128 case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
1129 cairo_surface_t *surf;
1130 surf = _cairo_raster_source_pattern_acquire (pattern, &surface->base, NULL);
1132 return CAIRO_INT_STATUS_UNSUPPORTED;
1133 assert (_cairo_surface_is_image (surf));
1134 *image = (cairo_image_surface_t *) surf;
1137 case CAIRO_PATTERN_TYPE_SOLID:
1138 case CAIRO_PATTERN_TYPE_LINEAR:
1139 case CAIRO_PATTERN_TYPE_RADIAL:
1140 case CAIRO_PATTERN_TYPE_MESH:
1146 return CAIRO_STATUS_SUCCESS;
1150 _cairo_pdf_surface_release_source_image_from_pattern (cairo_pdf_surface_t *surface,
1151 const cairo_pattern_t *pattern,
1152 cairo_image_surface_t *image,
1155 switch (pattern->type) {
1156 case CAIRO_PATTERN_TYPE_SURFACE: {
1157 cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
1158 _cairo_surface_release_source_image (surf_pat->surface, image, image_extra);
1161 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1162 _cairo_raster_source_pattern_release (pattern, &image->base);
1165 case CAIRO_PATTERN_TYPE_SOLID:
1166 case CAIRO_PATTERN_TYPE_LINEAR:
1167 case CAIRO_PATTERN_TYPE_RADIAL:
1168 case CAIRO_PATTERN_TYPE_MESH:
1176 static cairo_int_status_t
1177 _get_jpx_image_info (cairo_surface_t *source,
1178 cairo_image_info_t *info,
1179 const unsigned char **mime_data,
1180 unsigned long *mime_data_length)
1182 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
1183 mime_data, mime_data_length);
1184 if (*mime_data == NULL)
1185 return CAIRO_INT_STATUS_UNSUPPORTED;
1187 return _cairo_image_info_get_jpx_info (info, *mime_data, *mime_data_length);
1190 static cairo_int_status_t
1191 _get_jpeg_image_info (cairo_surface_t *source,
1192 cairo_image_info_t *info,
1193 const unsigned char **mime_data,
1194 unsigned long *mime_data_length)
1196 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
1197 mime_data, mime_data_length);
1198 if (*mime_data == NULL)
1199 return CAIRO_INT_STATUS_UNSUPPORTED;
1201 return _cairo_image_info_get_jpeg_info (info, *mime_data, *mime_data_length);
1204 static cairo_int_status_t
1205 _get_source_surface_size (cairo_surface_t *source,
1208 cairo_rectangle_int_t *extents)
1210 cairo_int_status_t status;
1211 cairo_image_info_t info;
1212 const unsigned char *mime_data;
1213 unsigned long mime_data_length;
1215 if (source->type == CAIRO_SURFACE_TYPE_RECORDING) {
1216 if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1217 cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
1219 *extents = sub->extents;
1220 *width = extents->width;
1221 *height = extents->height;
1223 cairo_surface_t *free_me = NULL;
1224 cairo_rectangle_int_t surf_extents;
1226 cairo_bool_t bounded;
1228 if (_cairo_surface_is_snapshot (source))
1229 free_me = source = _cairo_surface_snapshot_get_target (source);
1231 status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)source,
1233 if (unlikely (status)) {
1234 cairo_surface_destroy (free_me);
1238 bounded = _cairo_surface_get_extents (source, &surf_extents);
1239 cairo_surface_destroy (free_me);
1241 *width = surf_extents.width;
1242 *height = surf_extents.height;
1244 _cairo_box_round_to_rectangle (&box, extents);
1247 return CAIRO_STATUS_SUCCESS;
1253 status = _get_jpx_image_info (source, &info, &mime_data, &mime_data_length);
1254 if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
1255 *width = info.width;
1256 *height = info.height;
1257 extents->width = info.width;
1258 extents->height = info.height;
1262 status = _get_jpeg_image_info (source, &info, &mime_data, &mime_data_length);
1263 if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
1264 *width = info.width;
1265 *height = info.height;
1266 extents->width = info.width;
1267 extents->height = info.height;
1271 if (! _cairo_surface_get_extents (source, extents))
1272 return CAIRO_INT_STATUS_UNSUPPORTED;
1274 *width = extents->width;
1275 *height = extents->height;
1277 return CAIRO_STATUS_SUCCESS;
1281 * _cairo_pdf_surface_add_source_surface:
1282 * @surface: the pdf surface
1283 * @source_surface: A #cairo_surface_t to use as the source surface
1284 * @source_pattern: A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source
1285 * @filter: filter type of the source pattern
1286 * @stencil_mask: if true, the surface will be written to the PDF as an /ImageMask
1287 * @extents: extents of the operation that is using this source
1288 * @surface_res: return PDF resource number of the surface
1289 * @width: returns width of surface
1290 * @height: returns height of surface
1291 * @x_offset: x offset of surface
1292 * @t_offset: y offset of surface
1293 * @source_extents: returns extents of source (either ink extents or extents needed to cover @extents)
1295 * Add surface or raster_source pattern to list of surfaces to be
1296 * written to the PDF file when the current page is finished. Returns
1297 * a PDF resource to reference the image. A hash table of all images
1298 * in the PDF files (keyed by CAIRO_MIME_TYPE_UNIQUE_ID or surface
1299 * unique_id) to ensure surfaces with the same id are only written
1300 * once to the PDF file.
1302 * Only one of @source_pattern or @source_surface is to be
1303 * specified. Set the other to NULL.
1305 static cairo_status_t
1306 _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
1307 cairo_surface_t *source_surface,
1308 const cairo_pattern_t *source_pattern,
1309 cairo_filter_t filter,
1310 cairo_bool_t stencil_mask,
1311 const cairo_rectangle_int_t *extents,
1312 cairo_pdf_resource_t *surface_res,
1317 cairo_rectangle_int_t *source_extents)
1319 cairo_pdf_source_surface_t src_surface;
1320 cairo_pdf_source_surface_entry_t surface_key;
1321 cairo_pdf_source_surface_entry_t *surface_entry;
1322 cairo_status_t status;
1323 cairo_bool_t interpolate;
1324 unsigned char *unique_id;
1325 unsigned long unique_id_length = 0;
1326 cairo_image_surface_t *image;
1331 case CAIRO_FILTER_GOOD:
1332 case CAIRO_FILTER_BEST:
1333 case CAIRO_FILTER_BILINEAR:
1336 case CAIRO_FILTER_FAST:
1337 case CAIRO_FILTER_NEAREST:
1338 case CAIRO_FILTER_GAUSSIAN:
1339 interpolate = FALSE;
1345 if (source_pattern) {
1346 if (source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1347 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source_pattern,
1348 &image, &image_extra);
1349 if (unlikely (status))
1351 source_surface = &image->base;
1352 cairo_surface_get_device_offset (source_surface, x_offset, y_offset);
1354 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source_pattern;
1355 source_surface = surface_pattern->surface;
1359 surface_key.id = source_surface->unique_id;
1360 surface_key.interpolate = interpolate;
1361 cairo_surface_get_mime_data (source_surface, CAIRO_MIME_TYPE_UNIQUE_ID,
1362 (const unsigned char **) &surface_key.unique_id,
1363 &surface_key.unique_id_length);
1364 _cairo_pdf_source_surface_init_key (&surface_key);
1365 surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base);
1366 if (surface_entry) {
1367 *surface_res = surface_entry->surface_res;
1368 *width = surface_entry->width;
1369 *height = surface_entry->height;
1370 *source_extents = surface_entry->extents;
1371 status = CAIRO_STATUS_SUCCESS;
1373 status = _get_source_surface_size (source_surface,
1377 if (unlikely(status))
1378 goto release_source;
1380 if (surface_key.unique_id && surface_key.unique_id_length > 0) {
1381 unique_id = _cairo_malloc (surface_key.unique_id_length);
1382 if (unique_id == NULL) {
1383 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1384 goto release_source;
1387 unique_id_length = surface_key.unique_id_length;
1388 memcpy (unique_id, surface_key.unique_id, unique_id_length);
1391 unique_id_length = 0;
1396 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1397 _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra);
1399 if (status || surface_entry)
1402 surface_entry = malloc (sizeof (cairo_pdf_source_surface_entry_t));
1403 if (surface_entry == NULL) {
1404 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1408 surface_entry->id = surface_key.id;
1409 surface_entry->interpolate = interpolate;
1410 surface_entry->stencil_mask = stencil_mask;
1411 surface_entry->unique_id_length = unique_id_length;
1412 surface_entry->unique_id = unique_id;
1413 surface_entry->width = *width;
1414 surface_entry->height = *height;
1415 surface_entry->extents = *source_extents;
1416 _cairo_pdf_source_surface_init_key (surface_entry);
1418 src_surface.hash_entry = surface_entry;
1419 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1420 src_surface.type = CAIRO_PATTERN_TYPE_RASTER_SOURCE;
1421 src_surface.surface = NULL;
1422 status = _cairo_pattern_create_copy (&src_surface.raster_pattern, source_pattern);
1423 if (unlikely (status))
1427 src_surface.type = CAIRO_PATTERN_TYPE_SURFACE;
1428 src_surface.surface = cairo_surface_reference (source_surface);
1429 src_surface.raster_pattern = NULL;
1432 surface_entry->surface_res = _cairo_pdf_surface_new_object (surface);
1433 if (surface_entry->surface_res.id == 0) {
1434 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1438 status = _cairo_array_append (&surface->page_surfaces, &src_surface);
1439 if (unlikely (status))
1442 status = _cairo_hash_table_insert (surface->all_surfaces,
1443 &surface_entry->base);
1444 if (unlikely(status))
1447 *surface_res = surface_entry->surface_res;
1452 if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1453 cairo_pattern_destroy (src_surface.raster_pattern);
1455 cairo_surface_destroy (src_surface.surface);
1458 free (surface_entry);
1466 static cairo_status_t
1467 _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface,
1468 const cairo_pattern_t *pattern,
1469 const cairo_rectangle_int_t *extents,
1470 cairo_bool_t is_shading,
1471 cairo_pdf_resource_t *pattern_res,
1472 cairo_pdf_resource_t *gstate_res)
1474 cairo_pdf_pattern_t pdf_pattern;
1475 cairo_status_t status;
1477 pdf_pattern.is_shading = is_shading;
1479 /* Solid colors are emitted into the content stream */
1480 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
1481 pattern_res->id = 0;
1483 return CAIRO_STATUS_SUCCESS;
1486 status = _cairo_pattern_create_copy (&pdf_pattern.pattern, pattern);
1487 if (unlikely (status))
1490 pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface);
1491 if (pdf_pattern.pattern_res.id == 0) {
1492 cairo_pattern_destroy (pdf_pattern.pattern);
1493 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1496 pdf_pattern.gstate_res.id = 0;
1498 /* gradient patterns require an smask object to implement transparency */
1499 if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
1500 pattern->type == CAIRO_PATTERN_TYPE_RADIAL ||
1501 pattern->type == CAIRO_PATTERN_TYPE_MESH)
1505 _cairo_pattern_alpha_range (pattern, &min_alpha, NULL);
1506 if (! CAIRO_ALPHA_IS_OPAQUE (min_alpha)) {
1507 pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
1508 if (pdf_pattern.gstate_res.id == 0) {
1509 cairo_pattern_destroy (pdf_pattern.pattern);
1510 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1515 pdf_pattern.width = surface->width;
1516 pdf_pattern.height = surface->height;
1517 if (extents != NULL) {
1518 pdf_pattern.extents = *extents;
1520 pdf_pattern.extents.x = 0;
1521 pdf_pattern.extents.y = 0;
1522 pdf_pattern.extents.width = surface->width;
1523 pdf_pattern.extents.height = surface->height;
1526 *pattern_res = pdf_pattern.pattern_res;
1527 *gstate_res = pdf_pattern.gstate_res;
1529 status = _cairo_array_append (&surface->page_patterns, &pdf_pattern);
1530 if (unlikely (status)) {
1531 cairo_pattern_destroy (pdf_pattern.pattern);
1535 return CAIRO_STATUS_SUCCESS;
1538 /* Get BBox in PDF coordinates from extents in cairo coordinates */
1540 _get_bbox_from_extents (double surface_height,
1541 const cairo_rectangle_int_t *extents,
1542 cairo_box_double_t *bbox)
1544 bbox->p1.x = extents->x;
1545 bbox->p1.y = surface_height - (extents->y + extents->height);
1546 bbox->p2.x = extents->x + extents->width;
1547 bbox->p2.y = surface_height - extents->y;
1550 static cairo_status_t
1551 _cairo_pdf_surface_add_pdf_shading (cairo_pdf_surface_t *surface,
1552 const cairo_pattern_t *pattern,
1553 const cairo_rectangle_int_t *extents,
1554 cairo_pdf_resource_t *shading_res,
1555 cairo_pdf_resource_t *gstate_res)
1557 return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
1565 static cairo_status_t
1566 _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
1567 const cairo_pattern_t *pattern,
1568 const cairo_rectangle_int_t *extents,
1569 cairo_pdf_resource_t *pattern_res,
1570 cairo_pdf_resource_t *gstate_res)
1572 return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
1580 static cairo_status_t
1581 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
1582 cairo_pdf_resource_t *resource,
1583 cairo_bool_t compressed,
1588 cairo_pdf_resource_t self, length;
1589 cairo_output_stream_t *output = NULL;
1593 _cairo_pdf_surface_update_object (surface, self);
1595 self = _cairo_pdf_surface_new_object (surface);
1597 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1600 length = _cairo_pdf_surface_new_object (surface);
1602 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1605 output = _cairo_deflate_stream_create (surface->output);
1606 if (_cairo_output_stream_get_status (output))
1607 return _cairo_output_stream_destroy (output);
1610 surface->pdf_stream.active = TRUE;
1611 surface->pdf_stream.self = self;
1612 surface->pdf_stream.length = length;
1613 surface->pdf_stream.compressed = compressed;
1614 surface->current_pattern_is_solid_color = FALSE;
1615 surface->current_operator = CAIRO_OPERATOR_OVER;
1616 _cairo_pdf_operators_reset (&surface->pdf_operators);
1618 _cairo_output_stream_printf (surface->output,
1620 "<< /Length %d 0 R\n",
1621 surface->pdf_stream.self.id,
1622 surface->pdf_stream.length.id);
1624 _cairo_output_stream_printf (surface->output,
1625 " /Filter /FlateDecode\n");
1629 _cairo_output_stream_vprintf (surface->output, fmt, ap);
1633 _cairo_output_stream_printf (surface->output,
1637 surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
1640 assert (surface->pdf_stream.old_output == NULL);
1641 surface->pdf_stream.old_output = surface->output;
1642 surface->output = output;
1643 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1646 return _cairo_output_stream_get_status (surface->output);
1649 static cairo_status_t
1650 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
1652 cairo_status_t status;
1655 if (! surface->pdf_stream.active)
1656 return CAIRO_STATUS_SUCCESS;
1658 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1660 if (surface->pdf_stream.compressed) {
1661 cairo_status_t status2;
1663 status2 = _cairo_output_stream_destroy (surface->output);
1664 if (likely (status == CAIRO_STATUS_SUCCESS))
1667 surface->output = surface->pdf_stream.old_output;
1668 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1669 surface->pdf_stream.old_output = NULL;
1672 length = _cairo_output_stream_get_position (surface->output) -
1673 surface->pdf_stream.start_offset;
1674 _cairo_output_stream_printf (surface->output,
1679 _cairo_pdf_surface_update_object (surface,
1680 surface->pdf_stream.length);
1681 _cairo_output_stream_printf (surface->output,
1685 surface->pdf_stream.length.id,
1688 surface->pdf_stream.active = FALSE;
1690 if (likely (status == CAIRO_STATUS_SUCCESS))
1691 status = _cairo_output_stream_get_status (surface->output);
1697 _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface,
1698 cairo_output_stream_t *mem_stream,
1699 cairo_pdf_resource_t resource,
1700 cairo_pdf_group_resources_t *resources,
1701 cairo_bool_t is_knockout_group,
1702 const cairo_box_double_t *bbox)
1704 _cairo_pdf_surface_update_object (surface, resource);
1706 _cairo_output_stream_printf (surface->output,
1708 "<< /Type /XObject\n"
1711 _cairo_memory_stream_length (mem_stream));
1713 if (surface->compress_content) {
1714 _cairo_output_stream_printf (surface->output,
1715 " /Filter /FlateDecode\n");
1718 _cairo_output_stream_printf (surface->output,
1720 " /BBox [ %f %f %f %f ]\n"
1723 " /S /Transparency\n"
1725 " /CS /DeviceRGB\n",
1726 bbox->p1.x, bbox->p1.y, bbox->p2.x, bbox->p2.y);
1728 if (is_knockout_group)
1729 _cairo_output_stream_printf (surface->output,
1732 _cairo_output_stream_printf (surface->output,
1735 _cairo_pdf_surface_emit_group_resources (surface, resources);
1736 _cairo_output_stream_printf (surface->output,
1739 _cairo_memory_stream_copy (mem_stream, surface->output);
1740 _cairo_output_stream_printf (surface->output,
1745 static cairo_status_t
1746 _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
1747 const cairo_box_double_t *bbox,
1748 cairo_pdf_resource_t *resource)
1750 cairo_status_t status;
1752 assert (surface->pdf_stream.active == FALSE);
1753 assert (surface->group_stream.active == FALSE);
1755 surface->group_stream.active = TRUE;
1756 surface->current_pattern_is_solid_color = FALSE;
1757 surface->current_operator = CAIRO_OPERATOR_OVER;
1758 _cairo_pdf_operators_reset (&surface->pdf_operators);
1760 surface->group_stream.mem_stream = _cairo_memory_stream_create ();
1762 if (surface->compress_content) {
1763 surface->group_stream.stream =
1764 _cairo_deflate_stream_create (surface->group_stream.mem_stream);
1766 surface->group_stream.stream = surface->group_stream.mem_stream;
1768 status = _cairo_output_stream_get_status (surface->group_stream.stream);
1770 surface->group_stream.old_output = surface->output;
1771 surface->output = surface->group_stream.stream;
1772 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1773 _cairo_pdf_group_resources_clear (&surface->resources);
1776 surface->group_stream.resource = *resource;
1778 surface->group_stream.resource = _cairo_pdf_surface_new_object (surface);
1779 if (surface->group_stream.resource.id == 0)
1780 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1782 surface->group_stream.is_knockout = FALSE;
1783 surface->group_stream.bbox = *bbox;
1788 static cairo_status_t
1789 _cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface,
1790 const cairo_box_double_t *bbox)
1792 cairo_status_t status;
1794 status = _cairo_pdf_surface_open_group (surface, bbox, NULL);
1795 if (unlikely (status))
1798 surface->group_stream.is_knockout = TRUE;
1800 return CAIRO_STATUS_SUCCESS;
1803 static cairo_status_t
1804 _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
1805 cairo_pdf_resource_t *group)
1807 cairo_status_t status = CAIRO_STATUS_SUCCESS, status2;
1809 assert (surface->pdf_stream.active == FALSE);
1810 assert (surface->group_stream.active == TRUE);
1812 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1813 if (unlikely (status))
1816 if (surface->compress_content) {
1817 status = _cairo_output_stream_destroy (surface->group_stream.stream);
1818 surface->group_stream.stream = NULL;
1820 _cairo_output_stream_printf (surface->group_stream.mem_stream,
1823 surface->output = surface->group_stream.old_output;
1824 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1825 surface->group_stream.active = FALSE;
1826 _cairo_pdf_surface_write_memory_stream (surface,
1827 surface->group_stream.mem_stream,
1828 surface->group_stream.resource,
1829 &surface->resources,
1830 surface->group_stream.is_knockout,
1831 &surface->group_stream.bbox);
1833 *group = surface->group_stream.resource;
1835 status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
1836 if (status == CAIRO_STATUS_SUCCESS)
1839 surface->group_stream.mem_stream = NULL;
1840 surface->group_stream.stream = NULL;
1845 static cairo_status_t
1846 _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
1847 const cairo_box_double_t *bbox,
1848 cairo_pdf_resource_t *resource,
1849 cairo_bool_t is_form)
1851 cairo_status_t status;
1853 assert (surface->pdf_stream.active == FALSE);
1854 assert (surface->group_stream.active == FALSE);
1856 surface->content_resources = _cairo_pdf_surface_new_object (surface);
1857 if (surface->content_resources.id == 0)
1858 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1861 assert (bbox != NULL);
1864 _cairo_pdf_surface_open_stream (surface,
1866 surface->compress_content,
1869 " /BBox [ %f %f %f %f ]\n"
1872 " /S /Transparency\n"
1876 " /Resources %d 0 R\n",
1881 surface->content_resources.id);
1884 _cairo_pdf_surface_open_stream (surface,
1886 surface->compress_content,
1889 if (unlikely (status))
1892 surface->content = surface->pdf_stream.self;
1894 _cairo_output_stream_printf (surface->output, "q\n");
1896 return _cairo_output_stream_get_status (surface->output);
1899 static cairo_status_t
1900 _cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
1902 cairo_status_t status;
1904 assert (surface->pdf_stream.active == TRUE);
1905 assert (surface->group_stream.active == FALSE);
1907 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1908 if (unlikely (status))
1911 _cairo_output_stream_printf (surface->output, "Q\n");
1912 status = _cairo_pdf_surface_close_stream (surface);
1913 if (unlikely (status))
1916 _cairo_pdf_surface_update_object (surface, surface->content_resources);
1917 _cairo_output_stream_printf (surface->output,
1919 surface->content_resources.id);
1920 _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
1921 _cairo_output_stream_printf (surface->output,
1924 return _cairo_output_stream_get_status (surface->output);
1928 _cairo_pdf_source_surface_entry_pluck (void *entry, void *closure)
1930 cairo_pdf_source_surface_entry_t *surface_entry = entry;
1931 cairo_hash_table_t *patterns = closure;
1933 _cairo_hash_table_remove (patterns, &surface_entry->base);
1934 free (surface_entry->unique_id);
1936 free (surface_entry);
1939 static cairo_status_t
1940 _cairo_pdf_surface_finish (void *abstract_surface)
1942 cairo_pdf_surface_t *surface = abstract_surface;
1944 cairo_pdf_resource_t info, catalog;
1945 cairo_status_t status, status2;
1947 status = surface->base.status;
1948 if (status == CAIRO_STATUS_SUCCESS)
1949 status = _cairo_pdf_surface_emit_font_subsets (surface);
1951 _cairo_pdf_surface_write_pages (surface);
1953 info = _cairo_pdf_surface_write_info (surface);
1954 if (info.id == 0 && status == CAIRO_STATUS_SUCCESS)
1955 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1957 catalog = _cairo_pdf_surface_write_catalog (surface);
1958 if (catalog.id == 0 && status == CAIRO_STATUS_SUCCESS)
1959 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1961 offset = _cairo_pdf_surface_write_xref (surface);
1963 _cairo_output_stream_printf (surface->output,
1969 surface->next_available_resource.id,
1973 _cairo_output_stream_printf (surface->output,
1979 /* pdf_operators has already been flushed when the last stream was
1980 * closed so we should never be writing anything here - however,
1981 * the stream may itself be in an error state. */
1982 status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
1983 if (status == CAIRO_STATUS_SUCCESS)
1986 /* close any active streams still open due to fatal errors */
1987 status2 = _cairo_pdf_surface_close_stream (surface);
1988 if (status == CAIRO_STATUS_SUCCESS)
1991 if (surface->group_stream.stream != NULL) {
1992 status2 = _cairo_output_stream_destroy (surface->group_stream.stream);
1993 if (status == CAIRO_STATUS_SUCCESS)
1996 if (surface->group_stream.mem_stream != NULL) {
1997 status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
1998 if (status == CAIRO_STATUS_SUCCESS)
2001 if (surface->pdf_stream.active)
2002 surface->output = surface->pdf_stream.old_output;
2003 if (surface->group_stream.active)
2004 surface->output = surface->group_stream.old_output;
2006 /* and finish the pdf surface */
2007 status2 = _cairo_output_stream_destroy (surface->output);
2008 if (status == CAIRO_STATUS_SUCCESS)
2011 _cairo_pdf_surface_clear (surface);
2012 _cairo_pdf_group_resources_fini (&surface->resources);
2014 _cairo_array_fini (&surface->objects);
2015 _cairo_array_fini (&surface->pages);
2016 _cairo_array_fini (&surface->rgb_linear_functions);
2017 _cairo_array_fini (&surface->alpha_linear_functions);
2018 _cairo_array_fini (&surface->page_patterns);
2019 _cairo_array_fini (&surface->page_surfaces);
2020 _cairo_hash_table_foreach (surface->all_surfaces,
2021 _cairo_pdf_source_surface_entry_pluck,
2022 surface->all_surfaces);
2023 _cairo_hash_table_destroy (surface->all_surfaces);
2024 _cairo_array_fini (&surface->smask_groups);
2025 _cairo_array_fini (&surface->fonts);
2026 _cairo_array_fini (&surface->knockout_group);
2028 if (surface->font_subsets) {
2029 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
2030 surface->font_subsets = NULL;
2033 _cairo_surface_clipper_reset (&surface->clipper);
2038 static cairo_int_status_t
2039 _cairo_pdf_surface_start_page (void *abstract_surface)
2041 cairo_pdf_surface_t *surface = abstract_surface;
2043 /* Document header */
2044 if (! surface->header_emitted) {
2045 const char *version;
2047 switch (surface->pdf_version) {
2048 case CAIRO_PDF_VERSION_1_4:
2052 case CAIRO_PDF_VERSION_1_5:
2057 _cairo_output_stream_printf (surface->output,
2058 "%%PDF-%s\n", version);
2059 _cairo_output_stream_printf (surface->output,
2060 "%%%c%c%c%c\n", 181, 237, 174, 251);
2061 surface->header_emitted = TRUE;
2064 _cairo_pdf_group_resources_clear (&surface->resources);
2066 return CAIRO_STATUS_SUCCESS;
2069 static cairo_int_status_t
2070 _cairo_pdf_surface_has_fallback_images (void *abstract_surface,
2071 cairo_bool_t has_fallbacks)
2073 cairo_status_t status;
2074 cairo_pdf_surface_t *surface = abstract_surface;
2075 cairo_box_double_t bbox;
2077 surface->has_fallback_images = has_fallbacks;
2080 bbox.p2.x = surface->width;
2081 bbox.p2.y = surface->height;
2082 status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, has_fallbacks);
2083 if (unlikely (status))
2086 return CAIRO_STATUS_SUCCESS;
2090 _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
2095 static cairo_status_t
2096 _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surface,
2097 const cairo_pattern_t *source,
2098 const cairo_rectangle_int_t *extents,
2099 cairo_pdf_resource_t *surface_res,
2105 cairo_image_surface_t *image;
2106 cairo_surface_t *pad_image;
2108 cairo_int_status_t status;
2110 cairo_rectangle_int_t extents2;
2112 cairo_rectangle_int_t rect;
2113 cairo_surface_pattern_t pad_pattern;
2115 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source,
2116 &image, &image_extra);
2117 if (unlikely (status))
2120 pad_image = &image->base;
2122 /* get the operation extents in pattern space */
2123 _cairo_box_from_rectangle (&box, extents);
2124 _cairo_matrix_transform_bounding_box_fixed (&source->matrix, &box, NULL);
2125 _cairo_box_round_to_rectangle (&box, &rect);
2127 /* Check if image needs padding to fill extents */
2130 if (_cairo_fixed_integer_ceil(box.p1.x) < 0 ||
2131 _cairo_fixed_integer_ceil(box.p1.y) < 0 ||
2132 _cairo_fixed_integer_floor(box.p2.y) > w ||
2133 _cairo_fixed_integer_floor(box.p2.y) > h)
2135 pad_image = _cairo_image_surface_create_with_content (image->base.content,
2138 if (pad_image->status) {
2139 status = pad_image->status;
2143 _cairo_pattern_init_for_surface (&pad_pattern, &image->base);
2144 cairo_matrix_init_translate (&pad_pattern.base.matrix, rect.x, rect.y);
2145 pad_pattern.base.extend = CAIRO_EXTEND_PAD;
2146 status = _cairo_surface_paint (pad_image,
2147 CAIRO_OPERATOR_SOURCE, &pad_pattern.base,
2149 _cairo_pattern_fini (&pad_pattern.base);
2150 if (unlikely (status))
2154 status = _cairo_pdf_surface_add_source_surface (surface,
2166 if (unlikely (status))
2169 if (pad_image != &image->base) {
2170 /* If using a padded image, replace _add_source_surface
2171 * x/y_offset with padded image offset. Note:
2172 * _add_source_surface only sets a non zero x/y_offset for
2173 * RASTER_SOURCE patterns. _add_source_surface will always set
2174 * x/y_offset to 0 for surfaces so we can ignore the returned
2175 * offset and replace it with the offset required for the
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 (image_surf->base.content,
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 &image, &image_extra);
2643 if (unlikely (status))
2646 if (!source->hash_entry->stencil_mask) {
2647 status = _cairo_pdf_surface_emit_jpx_image (surface, &image->base, source->hash_entry->surface_res);
2648 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2649 goto release_source;
2651 status = _cairo_pdf_surface_emit_jpeg_image (surface, &image->base, source->hash_entry->surface_res);
2652 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2653 goto release_source;
2656 status = _cairo_pdf_surface_emit_image (surface, image,
2657 &source->hash_entry->surface_res,
2658 source->hash_entry->interpolate,
2659 source->hash_entry->stencil_mask);
2662 if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
2663 _cairo_surface_release_source_image (source->surface, image, image_extra);
2665 _cairo_pdf_surface_release_source_image_from_pattern (surface, source->raster_pattern,
2666 image, image_extra);
2671 static cairo_status_t
2672 _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
2673 cairo_pdf_source_surface_t *pdf_source)
2675 double old_width, old_height;
2676 cairo_paginated_mode_t old_paginated_mode;
2677 cairo_surface_clipper_t old_clipper;
2678 cairo_box_double_t bbox;
2679 cairo_int_status_t status;
2681 cairo_surface_t *free_me = NULL;
2682 cairo_surface_t *source;
2683 const cairo_rectangle_int_t *extents;
2686 cairo_bool_t is_subsurface;
2688 assert (pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE);
2689 extents = &pdf_source->hash_entry->extents;
2690 width = pdf_source->hash_entry->width;
2691 height = pdf_source->hash_entry->height;
2692 is_subsurface = FALSE;
2693 source = pdf_source->surface;
2694 if (_cairo_surface_is_snapshot (source)) {
2695 free_me = source = _cairo_surface_snapshot_get_target (source);
2696 } else if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
2697 cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
2699 source = sub->target;
2700 extents = &sub->extents;
2701 width = extents->width;
2702 height = extents->height;
2703 is_subsurface = TRUE;
2706 old_width = surface->width;
2707 old_height = surface->height;
2708 old_paginated_mode = surface->paginated_mode;
2709 old_clipper = surface->clipper;
2710 _cairo_surface_clipper_init (&surface->clipper,
2711 _cairo_pdf_surface_clipper_intersect_clip_path);
2713 _cairo_pdf_surface_set_size_internal (surface, width, height);
2715 /* Patterns are emitted after fallback images. The paginated mode
2716 * needs to be set to _RENDER while the recording surface is replayed
2717 * back to this surface.
2719 surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
2720 _cairo_pdf_group_resources_clear (&surface->resources);
2721 _get_bbox_from_extents (height, extents, &bbox);
2722 status = _cairo_pdf_surface_open_content_stream (surface, &bbox, &pdf_source->hash_entry->surface_res, TRUE);
2723 if (unlikely (status))
2726 if (source->content == CAIRO_CONTENT_COLOR) {
2727 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
2728 if (unlikely (status))
2731 _cairo_output_stream_printf (surface->output,
2732 "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
2738 status = _cairo_recording_surface_replay_region (source,
2739 is_subsurface ? extents : NULL,
2741 CAIRO_RECORDING_REGION_NATIVE);
2742 assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
2743 if (unlikely (status))
2746 status = _cairo_pdf_surface_close_content_stream (surface);
2748 _cairo_surface_clipper_reset (&surface->clipper);
2749 surface->clipper = old_clipper;
2750 _cairo_pdf_surface_set_size_internal (surface,
2753 surface->paginated_mode = old_paginated_mode;
2756 cairo_surface_destroy (free_me);
2760 static cairo_status_t
2761 _cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface,
2762 cairo_pdf_source_surface_t *src_surface)
2764 if (src_surface->type == CAIRO_PATTERN_TYPE_SURFACE &&
2765 src_surface->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
2766 return _cairo_pdf_surface_emit_recording_surface (surface, src_surface);
2768 return _cairo_pdf_surface_emit_image_surface (surface, src_surface);
2771 static cairo_status_t
2772 _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
2773 cairo_pdf_pattern_t *pdf_pattern)
2775 cairo_pattern_t *pattern = pdf_pattern->pattern;
2776 cairo_status_t status;
2777 cairo_pdf_resource_t pattern_resource = {0};
2778 cairo_matrix_t cairo_p2d, pdf_p2d;
2779 cairo_extend_t extend = cairo_pattern_get_extend (pattern);
2780 double xstep, ystep;
2781 cairo_rectangle_int_t pattern_extents;
2782 int pattern_width = 0; /* squelch bogus compiler warning */
2783 int pattern_height = 0; /* squelch bogus compiler warning */
2786 char draw_surface[200];
2787 cairo_box_double_t bbox;
2789 if (pattern->extend == CAIRO_EXTEND_PAD) {
2790 status = _cairo_pdf_surface_add_padded_image_surface (surface,
2792 &pdf_pattern->extents,
2798 pattern_extents.x = 0;
2799 pattern_extents.y = 0;
2800 pattern_extents.width = pattern_width;
2801 pattern_extents.height = pattern_height;
2803 status = _cairo_pdf_surface_add_source_surface (surface,
2808 &pdf_pattern->extents,
2816 if (unlikely (status))
2820 case CAIRO_EXTEND_PAD:
2821 case CAIRO_EXTEND_NONE:
2823 /* In PS/PDF, (as far as I can tell), all patterns are
2824 * repeating. So we support cairo's EXTEND_NONE semantics
2825 * by setting the repeat step size to a size large enough
2826 * to guarantee that no more than a single occurrence will
2829 * First, map the surface extents into pattern space (since
2830 * xstep and ystep are in pattern space). Then use an upper
2831 * bound on the length of the diagonal of the pattern image
2832 * and the surface as repeat size. This guarantees to never
2835 double x1 = 0.0, y1 = 0.0;
2836 double x2 = surface->width, y2 = surface->height;
2837 _cairo_matrix_transform_bounding_box (&pattern->matrix,
2841 /* Rather than computing precise bounds of the union, just
2842 * add the surface extents unconditionally. We only
2843 * required an answer that's large enough, we don't really
2844 * care if it's not as tight as possible.*/
2845 xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
2846 pattern_width + pattern_height);
2849 case CAIRO_EXTEND_REPEAT:
2850 xstep = pattern_width;
2851 ystep = pattern_height;
2853 case CAIRO_EXTEND_REFLECT:
2854 pattern_extents.x = 0;
2855 pattern_extents.y = 0;
2856 pattern_extents.width = pattern_width*2;
2857 pattern_extents.height = pattern_height*2;
2858 xstep = pattern_width*2;
2859 ystep = pattern_height*2;
2861 /* All the rest (if any) should have been analyzed away, so this
2862 * case should be unreachable. */
2869 /* At this point, (that is, within the surface backend interface),
2870 * the pattern's matrix maps from cairo's device space to cairo's
2871 * pattern space, (both with their origin at the upper-left, and
2872 * cairo's pattern space of size width,height).
2874 * Then, we must emit a PDF pattern object that maps from its own
2875 * pattern space, (which has a size that we establish in the BBox
2876 * dictionary entry), to the PDF page's *initial* space, (which
2877 * does not benefit from the Y-axis flipping matrix that we emit
2878 * on each page). So the PDF patterns matrix maps from a
2879 * (width,height) pattern space to a device space with the origin
2880 * in the lower-left corner.
2882 * So to handle all of that, we start with an identity matrix for
2883 * the PDF pattern to device matrix. We translate it up by the
2884 * image height then flip it in the Y direction, (moving us from
2885 * the PDF origin to cairo's origin). We then multiply in the
2886 * inverse of the cairo pattern matrix, (since it maps from device
2887 * to pattern, while we're setting up pattern to device). Finally,
2888 * we translate back down by the image height and flip again to
2889 * end up at the lower-left origin that PDF expects.
2891 * Additionally, within the stream that paints the pattern itself,
2892 * we are using a PDF image object that has a size of (1,1) so we
2893 * have to scale it up by the image width and height to fill our
2896 cairo_p2d = pattern->matrix;
2897 status = cairo_matrix_invert (&cairo_p2d);
2898 /* cairo_pattern_set_matrix ensures the matrix is invertible */
2899 assert (status == CAIRO_STATUS_SUCCESS);
2901 cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &surface->cairo_to_pdf);
2902 cairo_matrix_translate (&pdf_p2d, -x_offset, -y_offset);
2903 cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
2904 cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
2906 _get_bbox_from_extents (pattern_height, &pattern_extents, &bbox);
2907 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
2908 status = _cairo_pdf_surface_open_stream (surface,
2909 &pdf_pattern->pattern_res,
2912 " /BBox [ %f %f %f %f ]\n"
2917 " /Matrix [ %f %f %f %f %f %f ]\n"
2918 " /Resources << /XObject << /x%d %d 0 R >> >>\n",
2919 bbox.p1.x, bbox.p1.y, bbox.p2.x, bbox.p2.y,
2921 pdf_p2d.xx, pdf_p2d.yx,
2922 pdf_p2d.xy, pdf_p2d.yy,
2923 pdf_p2d.x0, pdf_p2d.y0,
2924 pattern_resource.id,
2925 pattern_resource.id);
2926 if (unlikely (status))
2929 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
2930 ((cairo_surface_pattern_t *) pattern)->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
2931 snprintf(draw_surface,
2932 sizeof (draw_surface),
2934 pattern_resource.id);
2936 snprintf(draw_surface,
2937 sizeof (draw_surface),
2938 "q %d 0 0 %d 0 0 cm /x%d Do Q",
2941 pattern_resource.id);
2944 if (extend == CAIRO_EXTEND_REFLECT) {
2945 _cairo_output_stream_printf (surface->output,
2946 "q 0 0 %d %d re W n %s Q\n"
2947 "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n %s Q\n"
2948 "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n %s Q\n"
2949 "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n %s Q\n",
2950 pattern_width, pattern_height,
2952 pattern_width*2, pattern_width, pattern_height,
2954 pattern_height*2, pattern_width, pattern_height,
2956 pattern_width*2, pattern_height*2, pattern_width, pattern_height,
2959 _cairo_output_stream_printf (surface->output,
2964 status = _cairo_pdf_surface_close_stream (surface);
2965 if (unlikely (status))
2968 return _cairo_output_stream_get_status (surface->output);
2971 typedef struct _cairo_pdf_color_stop {
2974 cairo_pdf_resource_t resource;
2975 } cairo_pdf_color_stop_t;
2977 static cairo_status_t
2978 cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t *surface,
2979 cairo_pdf_color_stop_t *stop1,
2980 cairo_pdf_color_stop_t *stop2,
2981 cairo_pdf_resource_t *function)
2984 cairo_pdf_rgb_linear_function_t elem;
2985 cairo_pdf_resource_t res;
2986 cairo_status_t status;
2988 num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions);
2989 for (i = 0; i < num_elems; i++) {
2990 _cairo_array_copy_element (&surface->rgb_linear_functions, i, &elem);
2991 if (memcmp (&elem.color1[0], &stop1->color[0], sizeof (double)*3) != 0)
2993 if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0)
2995 *function = elem.resource;
2996 return CAIRO_STATUS_SUCCESS;
2999 res = _cairo_pdf_surface_new_object (surface);
3001 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3003 _cairo_output_stream_printf (surface->output,
3005 "<< /FunctionType 2\n"
3006 " /Domain [ 0 1 ]\n"
3007 " /C0 [ %f %f %f ]\n"
3008 " /C1 [ %f %f %f ]\n"
3020 elem.resource = res;
3021 memcpy (&elem.color1[0], &stop1->color[0], sizeof (double)*3);
3022 memcpy (&elem.color2[0], &stop2->color[0], sizeof (double)*3);
3024 status = _cairo_array_append (&surface->rgb_linear_functions, &elem);
3030 static cairo_status_t
3031 cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t *surface,
3032 cairo_pdf_color_stop_t *stop1,
3033 cairo_pdf_color_stop_t *stop2,
3034 cairo_pdf_resource_t *function)
3037 cairo_pdf_alpha_linear_function_t elem;
3038 cairo_pdf_resource_t res;
3039 cairo_status_t status;
3041 num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions);
3042 for (i = 0; i < num_elems; i++) {
3043 _cairo_array_copy_element (&surface->alpha_linear_functions, i, &elem);
3044 if (elem.alpha1 != stop1->color[3])
3046 if (elem.alpha2 != stop2->color[3])
3048 *function = elem.resource;
3049 return CAIRO_STATUS_SUCCESS;
3052 res = _cairo_pdf_surface_new_object (surface);
3054 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3056 _cairo_output_stream_printf (surface->output,
3058 "<< /FunctionType 2\n"
3059 " /Domain [ 0 1 ]\n"
3069 elem.resource = res;
3070 elem.alpha1 = stop1->color[3];
3071 elem.alpha2 = stop2->color[3];
3073 status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
3079 static cairo_status_t
3080 _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
3081 unsigned int n_stops,
3082 cairo_pdf_color_stop_t *stops,
3083 cairo_bool_t is_alpha,
3084 cairo_pdf_resource_t *function)
3086 cairo_pdf_resource_t res;
3088 cairo_status_t status;
3090 /* emit linear gradients between pairs of subsequent stops... */
3091 for (i = 0; i < n_stops-1; i++) {
3093 status = cairo_pdf_surface_emit_alpha_linear_function (surface,
3096 &stops[i].resource);
3097 if (unlikely (status))
3100 status = cairo_pdf_surface_emit_rgb_linear_function (surface,
3103 &stops[i].resource);
3104 if (unlikely (status))
3109 /* ... and stitch them together */
3110 res = _cairo_pdf_surface_new_object (surface);
3112 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3114 _cairo_output_stream_printf (surface->output,
3116 "<< /FunctionType 3\n"
3117 " /Domain [ %f %f ]\n",
3120 stops[n_stops - 1].offset);
3122 _cairo_output_stream_printf (surface->output,
3124 for (i = 0; i < n_stops-1; i++)
3125 _cairo_output_stream_printf (surface->output,
3126 "%d 0 R ", stops[i].resource.id);
3127 _cairo_output_stream_printf (surface->output,
3130 _cairo_output_stream_printf (surface->output,
3132 for (i = 1; i < n_stops-1; i++)
3133 _cairo_output_stream_printf (surface->output,
3134 "%f ", stops[i].offset);
3135 _cairo_output_stream_printf (surface->output,
3138 _cairo_output_stream_printf (surface->output,
3140 for (i = 1; i < n_stops; i++)
3141 _cairo_output_stream_printf (surface->output,
3143 _cairo_output_stream_printf (surface->output,
3146 _cairo_output_stream_printf (surface->output,
3152 return _cairo_output_stream_get_status (surface->output);
3157 calc_gradient_color (cairo_pdf_color_stop_t *new_stop,
3158 cairo_pdf_color_stop_t *stop1,
3159 cairo_pdf_color_stop_t *stop2)
3162 double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
3164 for (i = 0; i < 4; i++)
3165 new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
3168 #define COLOR_STOP_EPSILON 1e-6
3170 static cairo_status_t
3171 _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
3172 cairo_gradient_pattern_t *pattern,
3173 cairo_pdf_resource_t *color_function,
3174 cairo_pdf_resource_t *alpha_function)
3176 cairo_pdf_color_stop_t *allstops, *stops;
3177 unsigned int n_stops;
3179 cairo_bool_t emit_alpha = FALSE;
3180 cairo_status_t status;
3182 color_function->id = 0;
3183 alpha_function->id = 0;
3185 allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t));
3186 if (unlikely (allstops == NULL))
3187 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3189 stops = &allstops[1];
3190 n_stops = pattern->n_stops;
3192 for (i = 0; i < n_stops; i++) {
3193 stops[i].color[0] = pattern->stops[i].color.red;
3194 stops[i].color[1] = pattern->stops[i].color.green;
3195 stops[i].color[2] = pattern->stops[i].color.blue;
3196 stops[i].color[3] = pattern->stops[i].color.alpha;
3197 if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
3199 stops[i].offset = pattern->stops[i].offset;
3202 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
3203 pattern->base.extend == CAIRO_EXTEND_REFLECT) {
3204 if (stops[0].offset > COLOR_STOP_EPSILON) {
3205 if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
3206 memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
3208 calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
3212 stops[0].offset = 0.0;
3214 if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
3215 if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
3216 memcpy (&stops[n_stops],
3217 &stops[n_stops - 1],
3218 sizeof (cairo_pdf_color_stop_t));
3220 calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
3224 stops[n_stops-1].offset = 1.0;
3227 if (stops[0].offset == stops[n_stops - 1].offset) {
3229 * The first and the last stops have the same offset, but we
3230 * don't want a function with an empty domain, because that
3231 * would provoke underdefined behaviour from rasterisers.
3232 * This can only happen with EXTEND_PAD, because EXTEND_NONE
3233 * is optimised into a clear pattern in cairo-gstate, and
3234 * REFLECT/REPEAT are always transformed to have the first
3235 * stop at t=0 and the last stop at t=1. Thus we want a step
3236 * function going from the first color to the last one.
3238 * This can be accomplished by stitching three functions:
3239 * - a constant first color function,
3240 * - a step from the first color to the last color (with empty domain)
3241 * - a constant last color function
3243 cairo_pdf_color_stop_t pad_stops[4];
3245 assert (pattern->base.extend == CAIRO_EXTEND_PAD);
3247 pad_stops[0] = pad_stops[1] = stops[0];
3248 pad_stops[2] = pad_stops[3] = stops[n_stops - 1];
3250 pad_stops[0].offset = 0;
3251 pad_stops[3].offset = 1;
3253 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3258 if (unlikely (status))
3262 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3267 if (unlikely (status))
3270 } else if (n_stops == 2) {
3271 /* no need for stitched function */
3272 status = cairo_pdf_surface_emit_rgb_linear_function (surface,
3274 &stops[n_stops - 1],
3276 if (unlikely (status))
3280 status = cairo_pdf_surface_emit_alpha_linear_function (surface,
3282 &stops[n_stops - 1],
3284 if (unlikely (status))
3288 /* multiple stops: stitch. XXX possible optimization: regularly spaced
3289 * stops do not require stitching. XXX */
3290 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3295 if (unlikely (status))
3299 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
3304 if (unlikely (status))
3314 static cairo_status_t
3315 _cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface,
3316 cairo_gradient_pattern_t *pattern,
3317 cairo_pdf_resource_t *function,
3321 cairo_pdf_resource_t res;
3324 res = _cairo_pdf_surface_new_object (surface);
3326 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3328 _cairo_output_stream_printf (surface->output,
3330 "<< /FunctionType 3\n"
3331 " /Domain [ %d %d ]\n",
3336 _cairo_output_stream_printf (surface->output,
3338 for (i = begin; i < end; i++)
3339 _cairo_output_stream_printf (surface->output,
3340 "%d 0 R ", function->id);
3341 _cairo_output_stream_printf (surface->output,
3344 _cairo_output_stream_printf (surface->output,
3346 for (i = begin + 1; i < end; i++)
3347 _cairo_output_stream_printf (surface->output,
3349 _cairo_output_stream_printf (surface->output,
3352 _cairo_output_stream_printf (surface->output,
3354 for (i = begin; i < end; i++) {
3355 if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) {
3356 _cairo_output_stream_printf (surface->output,
3359 _cairo_output_stream_printf (surface->output,
3363 _cairo_output_stream_printf (surface->output,
3366 _cairo_output_stream_printf (surface->output,
3372 return _cairo_output_stream_get_status (surface->output);
3375 static cairo_status_t
3376 cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
3377 cairo_pdf_pattern_t *pdf_pattern,
3378 cairo_pdf_resource_t gstate_resource,
3379 cairo_pdf_resource_t gradient_mask)
3381 cairo_pdf_resource_t smask_resource;
3382 cairo_status_t status;
3384 double x1, y1, x2, y2;
3386 if (pdf_pattern->is_shading) {
3387 snprintf(buf, sizeof(buf),
3389 " << /sh%d %d 0 R >>\n",
3393 snprintf(buf, sizeof(buf),
3395 " << /p%d %d 0 R >>\n",
3400 if (pdf_pattern->is_shading) {
3403 /* When emitting a shading operator we are in cairo pattern
3404 * coordinates. _cairo_pdf_surface_paint_gradient has set the
3405 * ctm to the pattern matrix (including the convertion from
3406 * pdf to cairo coordinates) */
3407 _cairo_box_from_rectangle (&box, &pdf_pattern->extents);
3408 _cairo_box_to_doubles (&box, &x1, &y1, &x2, &y2);
3409 _cairo_matrix_transform_bounding_box (&pdf_pattern->pattern->matrix, &x1, &y1, &x2, &y2, NULL);
3411 cairo_box_double_t box;
3413 /* When emitting a shading pattern we are in pdf page
3414 * coordinates. The color and alpha shading patterns painted
3415 * in the XObject below contain the cairo pattern to pdf page
3416 * matrix in the /Matrix entry of the pattern. */
3417 _get_bbox_from_extents (pdf_pattern->height, &pdf_pattern->extents, &box);
3423 status = _cairo_pdf_surface_open_stream (surface,
3425 surface->compress_content,
3429 " /BBox [ %f %f %f %f ]\n"
3432 " << /a0 << /ca 1 /CA 1 >>"
3437 " << /Type /Group\n"
3438 " /S /Transparency\n"
3440 " /CS /DeviceGray\n"
3444 if (unlikely (status))
3447 if (pdf_pattern->is_shading) {
3448 _cairo_output_stream_printf (surface->output,
3449 "/a0 gs /sh%d sh\n",
3452 _cairo_output_stream_printf (surface->output,
3455 "/Pattern cs /p%d scn\n"
3464 status = _cairo_pdf_surface_close_stream (surface);
3465 if (unlikely (status))
3468 smask_resource = _cairo_pdf_surface_new_object (surface);
3469 if (smask_resource.id == 0)
3470 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3472 _cairo_output_stream_printf (surface->output,
3480 surface->pdf_stream.self.id);
3482 /* Create GState which uses the transparency group as an SMask. */
3483 _cairo_pdf_surface_update_object (surface, gstate_resource);
3485 _cairo_output_stream_printf (surface->output,
3487 "<< /Type /ExtGState\n"
3497 return _cairo_output_stream_get_status (surface->output);
3501 _cairo_pdf_surface_output_gradient (cairo_pdf_surface_t *surface,
3502 const cairo_pdf_pattern_t *pdf_pattern,
3503 cairo_pdf_resource_t pattern_resource,
3504 const cairo_matrix_t *pat_to_pdf,
3505 const cairo_circle_double_t*start,
3506 const cairo_circle_double_t*end,
3507 const double *domain,
3508 const char *colorspace,
3509 cairo_pdf_resource_t color_function)
3511 _cairo_output_stream_printf (surface->output,
3513 pattern_resource.id);
3515 if (!pdf_pattern->is_shading) {
3516 _cairo_output_stream_printf (surface->output,
3517 "<< /Type /Pattern\n"
3519 " /Matrix [ %f %f %f %f %f %f ]\n"
3521 pat_to_pdf->xx, pat_to_pdf->yx,
3522 pat_to_pdf->xy, pat_to_pdf->yy,
3523 pat_to_pdf->x0, pat_to_pdf->y0);
3526 if (pdf_pattern->pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
3527 _cairo_output_stream_printf (surface->output,
3528 " << /ShadingType 2\n"
3530 " /Coords [ %f %f %f %f ]\n",
3532 start->center.x, start->center.y,
3533 end->center.x, end->center.y);
3535 _cairo_output_stream_printf (surface->output,
3536 " << /ShadingType 3\n"
3538 " /Coords [ %f %f %f %f %f %f ]\n",
3540 start->center.x, start->center.y,
3541 MAX (start->radius, 0),
3542 end->center.x, end->center.y,
3543 MAX (end->radius, 0));
3546 _cairo_output_stream_printf (surface->output,
3547 " /Domain [ %f %f ]\n",
3548 domain[0], domain[1]);
3550 if (pdf_pattern->pattern->extend != CAIRO_EXTEND_NONE) {
3551 _cairo_output_stream_printf (surface->output,
3552 " /Extend [ true true ]\n");
3554 _cairo_output_stream_printf (surface->output,
3555 " /Extend [ false false ]\n");
3558 _cairo_output_stream_printf (surface->output,
3559 " /Function %d 0 R\n"
3563 if (!pdf_pattern->is_shading) {
3564 _cairo_output_stream_printf (surface->output,
3570 static cairo_status_t
3571 _cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t *surface,
3572 cairo_pdf_pattern_t *pdf_pattern)
3574 cairo_gradient_pattern_t *pattern = (cairo_gradient_pattern_t *) pdf_pattern->pattern;
3575 cairo_pdf_resource_t color_function, alpha_function;
3576 cairo_matrix_t pat_to_pdf;
3577 cairo_circle_double_t start, end;
3579 cairo_status_t status;
3581 assert (pattern->n_stops != 0);
3583 status = _cairo_pdf_surface_emit_pattern_stops (surface,
3587 if (unlikely (status))
3590 pat_to_pdf = pattern->base.matrix;
3591 status = cairo_matrix_invert (&pat_to_pdf);
3592 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3593 assert (status == CAIRO_STATUS_SUCCESS);
3594 cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
3596 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
3597 pattern->base.extend == CAIRO_EXTEND_REFLECT)
3599 double bounds_x1, bounds_x2, bounds_y1, bounds_y2;
3600 double x_scale, y_scale, tolerance;
3602 /* TODO: use tighter extents */
3605 bounds_x2 = surface->width;
3606 bounds_y2 = surface->height;
3607 _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
3608 &bounds_x1, &bounds_y1,
3609 &bounds_x2, &bounds_y2,
3612 x_scale = surface->base.x_resolution / surface->base.x_fallback_resolution;
3613 y_scale = surface->base.y_resolution / surface->base.y_fallback_resolution;
3615 tolerance = fabs (_cairo_matrix_compute_determinant (&pattern->base.matrix));
3616 tolerance /= _cairo_matrix_transformed_circle_major_axis (&pattern->base.matrix, 1);
3617 tolerance *= MIN (x_scale, y_scale);
3619 _cairo_gradient_pattern_box_to_parameter (pattern,
3620 bounds_x1, bounds_y1,
3621 bounds_x2, bounds_y2,
3623 } else if (pattern->stops[0].offset == pattern->stops[pattern->n_stops - 1].offset) {
3625 * If the first and the last stop offset are the same, then
3626 * the color function is a step function.
3627 * _cairo_ps_surface_emit_pattern_stops emits it as a stitched
3628 * function no matter how many stops the pattern has. The
3629 * domain of the stitched function will be [0 1] in this case.
3631 * This is done to avoid emitting degenerate gradients for
3632 * EXTEND_PAD patterns having a step color function.
3637 assert (pattern->base.extend == CAIRO_EXTEND_PAD);
3639 domain[0] = pattern->stops[0].offset;
3640 domain[1] = pattern->stops[pattern->n_stops - 1].offset;
3643 /* PDF requires the first and last stop to be the same as the
3644 * extreme coordinates. For repeating patterns this moves the
3645 * extreme coordinates out to the begin/end of the repeating
3646 * function. For non repeating patterns this may move the extreme
3647 * coordinates in if there are not stops at offset 0 and 1. */
3648 _cairo_gradient_pattern_interpolate (pattern, domain[0], &start);
3649 _cairo_gradient_pattern_interpolate (pattern, domain[1], &end);
3651 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
3652 pattern->base.extend == CAIRO_EXTEND_REFLECT)
3654 int repeat_begin, repeat_end;
3656 repeat_begin = floor (domain[0]);
3657 repeat_end = ceil (domain[1]);
3659 status = _cairo_pdf_surface_emit_repeating_function (surface,
3664 if (unlikely (status))
3667 if (alpha_function.id != 0) {
3668 status = _cairo_pdf_surface_emit_repeating_function (surface,
3673 if (unlikely (status))
3676 } else if (pattern->n_stops <= 2) {
3677 /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
3678 * Type 2 function is used by itself without a stitching
3679 * function. Type 2 functions always have the domain [0 1] */
3684 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
3685 _cairo_pdf_surface_output_gradient (surface, pdf_pattern,
3686 pdf_pattern->pattern_res,
3687 &pat_to_pdf, &start, &end, domain,
3688 "/DeviceRGB", color_function);
3690 if (alpha_function.id != 0) {
3691 cairo_pdf_resource_t mask_resource;
3693 assert (pdf_pattern->gstate_res.id != 0);
3695 /* Create pattern for SMask. */
3696 mask_resource = _cairo_pdf_surface_new_object (surface);
3697 if (mask_resource.id == 0)
3698 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3700 _cairo_pdf_surface_output_gradient (surface, pdf_pattern,
3702 &pat_to_pdf, &start, &end, domain,
3703 "/DeviceGray", alpha_function);
3705 status = cairo_pdf_surface_emit_transparency_group (surface,
3707 pdf_pattern->gstate_res,
3709 if (unlikely (status))
3713 return _cairo_output_stream_get_status (surface->output);
3716 static cairo_status_t
3717 _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
3718 cairo_pdf_pattern_t *pdf_pattern)
3720 cairo_matrix_t pat_to_pdf;
3721 cairo_status_t status;
3722 cairo_pattern_t *pattern = pdf_pattern->pattern;
3723 cairo_pdf_shading_t shading;
3725 cairo_pdf_resource_t res;
3727 pat_to_pdf = pattern->matrix;
3728 status = cairo_matrix_invert (&pat_to_pdf);
3729 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3730 assert (status == CAIRO_STATUS_SUCCESS);
3732 cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
3734 status = _cairo_pdf_shading_init_color (&shading, (cairo_mesh_pattern_t *) pattern);
3735 if (unlikely (status))
3738 res = _cairo_pdf_surface_new_object (surface);
3739 if (unlikely (res.id == 0))
3740 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3742 _cairo_output_stream_printf (surface->output,
3744 "<< /ShadingType %d\n"
3745 " /ColorSpace /DeviceRGB\n"
3746 " /BitsPerCoordinate %d\n"
3747 " /BitsPerComponent %d\n"
3748 " /BitsPerFlag %d\n"
3751 shading.shading_type,
3752 shading.bits_per_coordinate,
3753 shading.bits_per_component,
3754 shading.bits_per_flag);
3756 for (i = 0; i < shading.decode_array_length; i++)
3757 _cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
3759 _cairo_output_stream_printf (surface->output,
3764 shading.data_length);
3766 _cairo_output_stream_write (surface->output, shading.data, shading.data_length);
3768 _cairo_output_stream_printf (surface->output,
3772 _cairo_pdf_shading_fini (&shading);
3774 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
3775 _cairo_output_stream_printf (surface->output,
3777 "<< /Type /Pattern\n"
3779 " /Matrix [ %f %f %f %f %f %f ]\n"
3780 " /Shading %d 0 R\n"
3783 pdf_pattern->pattern_res.id,
3784 pat_to_pdf.xx, pat_to_pdf.yx,
3785 pat_to_pdf.xy, pat_to_pdf.yy,
3786 pat_to_pdf.x0, pat_to_pdf.y0,
3789 if (pdf_pattern->gstate_res.id != 0) {
3790 cairo_pdf_resource_t mask_resource;
3792 /* Create pattern for SMask. */
3793 res = _cairo_pdf_surface_new_object (surface);
3794 if (unlikely (res.id == 0))
3795 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3797 status = _cairo_pdf_shading_init_alpha (&shading, (cairo_mesh_pattern_t *) pattern);
3798 if (unlikely (status))
3801 _cairo_output_stream_printf (surface->output,
3803 "<< /ShadingType %d\n"
3804 " /ColorSpace /DeviceGray\n"
3805 " /BitsPerCoordinate %d\n"
3806 " /BitsPerComponent %d\n"
3807 " /BitsPerFlag %d\n"
3810 shading.shading_type,
3811 shading.bits_per_coordinate,
3812 shading.bits_per_component,
3813 shading.bits_per_flag);
3815 for (i = 0; i < shading.decode_array_length; i++)
3816 _cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
3818 _cairo_output_stream_printf (surface->output,
3823 shading.data_length);
3825 _cairo_output_stream_write (surface->output, shading.data, shading.data_length);
3827 _cairo_output_stream_printf (surface->output,
3830 _cairo_pdf_shading_fini (&shading);
3832 mask_resource = _cairo_pdf_surface_new_object (surface);
3833 if (unlikely (mask_resource.id == 0))
3834 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3836 _cairo_output_stream_printf (surface->output,
3838 "<< /Type /Pattern\n"
3840 " /Matrix [ %f %f %f %f %f %f ]\n"
3841 " /Shading %d 0 R\n"
3845 pat_to_pdf.xx, pat_to_pdf.yx,
3846 pat_to_pdf.xy, pat_to_pdf.yy,
3847 pat_to_pdf.x0, pat_to_pdf.y0,
3850 status = cairo_pdf_surface_emit_transparency_group (surface,
3852 pdf_pattern->gstate_res,
3854 if (unlikely (status))
3858 return _cairo_output_stream_get_status (surface->output);
3861 static cairo_status_t
3862 _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
3864 double old_width, old_height;
3865 cairo_status_t status;
3867 old_width = surface->width;
3868 old_height = surface->height;
3869 _cairo_pdf_surface_set_size_internal (surface,
3871 pdf_pattern->height);
3873 switch (pdf_pattern->pattern->type) {
3874 case CAIRO_PATTERN_TYPE_SOLID:
3876 status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3879 case CAIRO_PATTERN_TYPE_SURFACE:
3880 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3881 status = _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
3884 case CAIRO_PATTERN_TYPE_LINEAR:
3885 case CAIRO_PATTERN_TYPE_RADIAL:
3886 status = _cairo_pdf_surface_emit_gradient (surface, pdf_pattern);
3889 case CAIRO_PATTERN_TYPE_MESH:
3890 status = _cairo_pdf_surface_emit_mesh_pattern (surface, pdf_pattern);
3895 status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3899 _cairo_pdf_surface_set_size_internal (surface,
3906 static cairo_status_t
3907 _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
3908 const cairo_pattern_t *source,
3909 const cairo_rectangle_int_t *extents,
3910 cairo_bool_t stencil_mask)
3912 cairo_pdf_resource_t surface_res;
3914 cairo_matrix_t cairo_p2d, pdf_p2d;
3915 cairo_status_t status;
3917 cairo_rectangle_int_t extents2;
3921 if (source->extend == CAIRO_EXTEND_PAD &&
3922 !(source->type == CAIRO_PATTERN_TYPE_SURFACE &&
3923 ((cairo_surface_pattern_t *)source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING))
3925 status = _cairo_pdf_surface_add_padded_image_surface (surface,
3934 status = _cairo_pdf_surface_add_source_surface (surface,
3947 if (unlikely (status))
3950 cairo_p2d = source->matrix;
3951 status = cairo_matrix_invert (&cairo_p2d);
3952 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3953 assert (status == CAIRO_STATUS_SUCCESS);
3955 pdf_p2d = surface->cairo_to_pdf;
3956 cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
3957 cairo_matrix_translate (&pdf_p2d, x_offset, y_offset);
3958 cairo_matrix_translate (&pdf_p2d, 0.0, height);
3959 cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
3960 if (!(source->type == CAIRO_PATTERN_TYPE_SURFACE &&
3961 ((cairo_surface_pattern_t *)source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING))
3963 cairo_matrix_scale (&pdf_p2d, width, height);
3966 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3967 if (unlikely (status))
3970 if (! _cairo_matrix_is_identity (&pdf_p2d)) {
3971 _cairo_output_stream_printf (surface->output,
3972 "%f %f %f %f %f %f cm\n",
3973 pdf_p2d.xx, pdf_p2d.yx,
3974 pdf_p2d.xy, pdf_p2d.yy,
3975 pdf_p2d.x0, pdf_p2d.y0);
3978 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
3979 if (unlikely (status))
3983 _cairo_output_stream_printf (surface->output,
3987 _cairo_output_stream_printf (surface->output,
3988 "/a%d gs /x%d Do\n",
3993 return _cairo_pdf_surface_add_xobject (surface, surface_res);
3996 static cairo_status_t
3997 _cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t *surface,
3998 const cairo_pattern_t *source,
3999 const cairo_rectangle_int_t *extents)
4001 cairo_pdf_resource_t shading_res, gstate_res;
4002 cairo_matrix_t pat_to_pdf;
4003 cairo_status_t status;
4006 status = _cairo_pdf_surface_add_pdf_shading (surface, source,
4008 &shading_res, &gstate_res);
4009 if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
4010 return CAIRO_STATUS_SUCCESS;
4011 if (unlikely (status))
4014 pat_to_pdf = source->matrix;
4015 status = cairo_matrix_invert (&pat_to_pdf);
4016 /* cairo_pattern_set_matrix ensures the matrix is invertible */
4017 assert (status == CAIRO_STATUS_SUCCESS);
4018 cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
4020 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4021 if (unlikely (status))
4024 if (! _cairo_matrix_is_identity (&pat_to_pdf)) {
4025 _cairo_output_stream_printf (surface->output,
4026 "%f %f %f %f %f %f cm\n",
4027 pat_to_pdf.xx, pat_to_pdf.yx,
4028 pat_to_pdf.xy, pat_to_pdf.yy,
4029 pat_to_pdf.x0, pat_to_pdf.y0);
4032 status = _cairo_pdf_surface_add_shading (surface, shading_res);
4033 if (unlikely (status))
4036 if (gstate_res.id != 0) {
4037 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
4038 if (unlikely (status))
4041 _cairo_output_stream_printf (surface->output,
4042 "/s%d gs /sh%d sh\n",
4046 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
4047 if (unlikely (status))
4050 _cairo_output_stream_printf (surface->output,
4051 "/a%d gs /sh%d sh\n",
4059 static cairo_status_t
4060 _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface,
4061 const cairo_pattern_t *source,
4062 const cairo_rectangle_int_t *extents,
4065 switch (source->type) {
4066 case CAIRO_PATTERN_TYPE_SURFACE:
4067 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4068 return _cairo_pdf_surface_paint_surface_pattern (surface,
4072 case CAIRO_PATTERN_TYPE_LINEAR:
4073 case CAIRO_PATTERN_TYPE_RADIAL:
4074 case CAIRO_PATTERN_TYPE_MESH:
4075 return _cairo_pdf_surface_paint_gradient (surface,
4079 case CAIRO_PATTERN_TYPE_SOLID:
4082 return CAIRO_STATUS_SUCCESS;
4087 _can_paint_pattern (const cairo_pattern_t *pattern)
4089 switch (pattern->type) {
4090 case CAIRO_PATTERN_TYPE_SOLID:
4093 case CAIRO_PATTERN_TYPE_SURFACE:
4094 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4095 return (pattern->extend == CAIRO_EXTEND_NONE ||
4096 pattern->extend == CAIRO_EXTEND_PAD);
4098 case CAIRO_PATTERN_TYPE_LINEAR:
4099 case CAIRO_PATTERN_TYPE_RADIAL:
4102 case CAIRO_PATTERN_TYPE_MESH:
4111 static cairo_status_t
4112 _cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface,
4113 cairo_operator_t op)
4115 cairo_status_t status;
4117 if (op == surface->current_operator)
4118 return CAIRO_STATUS_SUCCESS;
4120 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4121 if (unlikely (status))
4124 _cairo_output_stream_printf (surface->output,
4126 surface->current_operator = op;
4127 _cairo_pdf_surface_add_operator (surface, op);
4129 return CAIRO_STATUS_SUCCESS;
4132 static cairo_status_t
4133 _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
4134 const cairo_pattern_t *pattern,
4135 cairo_pdf_resource_t pattern_res,
4136 cairo_bool_t is_stroke)
4138 cairo_status_t status;
4140 const cairo_color_t *solid_color = NULL;
4142 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
4143 const cairo_solid_pattern_t *solid = (const cairo_solid_pattern_t *) pattern;
4145 solid_color = &solid->color;
4148 if (solid_color != NULL) {
4149 if (surface->current_pattern_is_solid_color == FALSE ||
4150 surface->current_color_red != solid_color->red ||
4151 surface->current_color_green != solid_color->green ||
4152 surface->current_color_blue != solid_color->blue ||
4153 surface->current_color_is_stroke != is_stroke)
4155 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4156 if (unlikely (status))
4159 _cairo_output_stream_printf (surface->output,
4166 _cairo_output_stream_printf (surface->output, "RG ");
4168 _cairo_output_stream_printf (surface->output, "rg ");
4170 surface->current_color_red = solid_color->red;
4171 surface->current_color_green = solid_color->green;
4172 surface->current_color_blue = solid_color->blue;
4173 surface->current_color_is_stroke = is_stroke;
4176 if (surface->current_pattern_is_solid_color == FALSE ||
4177 surface->current_color_alpha != solid_color->alpha)
4179 status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha);
4180 if (unlikely (status))
4183 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4184 if (unlikely (status))
4187 _cairo_output_stream_printf (surface->output,
4190 surface->current_color_alpha = solid_color->alpha;
4193 surface->current_pattern_is_solid_color = TRUE;
4195 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
4196 if (unlikely (status))
4199 status = _cairo_pdf_surface_add_pattern (surface, pattern_res);
4200 if (unlikely (status))
4203 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4204 if (unlikely (status))
4207 /* fill-stroke calls select_pattern twice. Don't save if the
4208 * gstate is already saved. */
4209 if (!surface->select_pattern_gstate_saved)
4210 _cairo_output_stream_printf (surface->output, "q ");
4213 _cairo_output_stream_printf (surface->output,
4214 "/Pattern CS /p%d SCN ",
4217 _cairo_output_stream_printf (surface->output,
4218 "/Pattern cs /p%d scn ",
4221 _cairo_output_stream_printf (surface->output,
4224 surface->select_pattern_gstate_saved = TRUE;
4225 surface->current_pattern_is_solid_color = FALSE;
4228 return _cairo_output_stream_get_status (surface->output);
4231 static cairo_int_status_t
4232 _cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
4234 cairo_int_status_t status;
4236 if (surface->select_pattern_gstate_saved) {
4237 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4238 if (unlikely (status))
4241 _cairo_output_stream_printf (surface->output, "Q\n");
4242 _cairo_pdf_operators_reset (&surface->pdf_operators);
4243 surface->current_pattern_is_solid_color = FALSE;
4245 surface->select_pattern_gstate_saved = FALSE;
4247 return CAIRO_STATUS_SUCCESS;
4250 static cairo_int_status_t
4251 _cairo_pdf_surface_show_page (void *abstract_surface)
4253 cairo_pdf_surface_t *surface = abstract_surface;
4254 cairo_int_status_t status;
4256 status = _cairo_pdf_surface_close_content_stream (surface);
4257 if (unlikely (status))
4260 _cairo_surface_clipper_reset (&surface->clipper);
4262 status = _cairo_pdf_surface_write_page (surface);
4263 if (unlikely (status))
4266 _cairo_pdf_surface_clear (surface);
4268 return CAIRO_STATUS_SUCCESS;
4272 _cairo_pdf_surface_get_extents (void *abstract_surface,
4273 cairo_rectangle_int_t *rectangle)
4275 cairo_pdf_surface_t *surface = abstract_surface;
4280 /* XXX: The conversion to integers here is pretty bogus, (not to
4281 * mention the arbitrary limitation of width to a short(!). We
4282 * may need to come up with a better interface for get_size.
4284 rectangle->width = ceil (surface->width);
4285 rectangle->height = ceil (surface->height);
4291 _cairo_pdf_surface_get_font_options (void *abstract_surface,
4292 cairo_font_options_t *options)
4294 _cairo_font_options_init_default (options);
4296 cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
4297 cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
4298 cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
4299 _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_OFF);
4302 static cairo_pdf_resource_t
4303 _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface)
4305 cairo_pdf_resource_t info;
4307 info = _cairo_pdf_surface_new_object (surface);
4311 _cairo_output_stream_printf (surface->output,
4313 "<< /Creator (cairo %s (http://cairographics.org))\n"
4314 " /Producer (cairo %s (http://cairographics.org))\n"
4318 cairo_version_string (),
4319 cairo_version_string ());
4325 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
4327 cairo_pdf_resource_t page;
4330 _cairo_pdf_surface_update_object (surface, surface->pages_resource);
4331 _cairo_output_stream_printf (surface->output,
4335 surface->pages_resource.id);
4337 num_pages = _cairo_array_num_elements (&surface->pages);
4338 for (i = 0; i < num_pages; i++) {
4339 _cairo_array_copy_element (&surface->pages, i, &page);
4340 _cairo_output_stream_printf (surface->output, "%d 0 R ", page.id);
4343 _cairo_output_stream_printf (surface->output, "]\n");
4344 _cairo_output_stream_printf (surface->output, " /Count %d\n", num_pages);
4347 /* TODO: Figure out which other defaults to be inherited by /Page
4349 _cairo_output_stream_printf (surface->output,
4354 static cairo_status_t
4355 _utf8_to_pdf_string (const char *utf8, char **str_out)
4361 cairo_status_t status = CAIRO_STATUS_SUCCESS;
4364 len = strlen (utf8);
4365 for (i = 0; i < len; i++) {
4366 unsigned c = utf8[i];
4367 if (c < 32 || c > 126 || c == '(' || c == ')' || c == '\\') {
4374 str = malloc (len + 3);
4376 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4379 for (i = 0; i < len; i++)
4384 uint16_t *utf16 = NULL;
4387 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
4388 if (unlikely (status))
4391 str = malloc (utf16_len*4 + 7);
4394 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4397 strcpy (str, "<FEFF");
4398 for (i = 0; i < utf16_len; i++)
4399 snprintf (str + 4*i + 5, 5, "%04X", utf16[i]);
4409 static cairo_status_t
4410 _cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t *surface,
4413 uint16_t *utf16 = NULL;
4415 cairo_status_t status;
4418 if (utf8 && *utf8) {
4419 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
4420 if (unlikely (status))
4424 _cairo_output_stream_printf (surface->output, "<");
4425 if (utf16 == NULL || utf16_len == 0) {
4426 /* According to the "ToUnicode Mapping File Tutorial"
4427 * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
4429 * Glyphs that do not map to a Unicode code point must be
4430 * mapped to 0xfffd "REPLACEMENT CHARACTER".
4432 _cairo_output_stream_printf (surface->output,
4435 for (i = 0; i < utf16_len; i++)
4436 _cairo_output_stream_printf (surface->output,
4437 "%04x", (int) (utf16[i]));
4439 _cairo_output_stream_printf (surface->output, ">");
4443 return CAIRO_STATUS_SUCCESS;
4448 * Public domain code from:
4449 * http://burtleburtle.net/bob/hash/doobs.html
4452 #define HASH_MIX(a,b,c) \
4454 a -= b; a -= c; a ^= (c>>13); \
4455 b -= c; b -= a; b ^= (a<<8); \
4456 c -= a; c -= b; c ^= (b>>13); \
4457 a -= b; a -= c; a ^= (c>>12); \
4458 b -= c; b -= a; b ^= (a<<16); \
4459 c -= a; c -= b; c ^= (b>>5); \
4460 a -= b; a -= c; a ^= (c>>3); \
4461 b -= c; b -= a; b ^= (a<<10); \
4462 c -= a; c -= b; c ^= (b>>15); \
4466 _hash_data (const unsigned char *data, int length, uint32_t initval)
4468 uint32_t a, b, c, len;
4471 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
4472 c = initval; /* the previous hash value */
4475 a += (data[0] + ((uint32_t)data[1]<<8) + ((uint32_t)data[2]<<16) + ((uint32_t)data[3]<<24));
4476 b += (data[4] + ((uint32_t)data[5]<<8) + ((uint32_t)data[6]<<16) + ((uint32_t)data[7]<<24));
4477 c += (data[8] + ((uint32_t)data[9]<<8) + ((uint32_t)data[10]<<16)+ ((uint32_t)data[11]<<24));
4485 case 11: c+= ((uint32_t) data[10] << 24);
4486 case 10: c+= ((uint32_t) data[9] << 16);
4487 case 9 : c+= ((uint32_t) data[8] << 8);
4488 case 8 : b+= ((uint32_t) data[7] << 24);
4489 case 7 : b+= ((uint32_t) data[6] << 16);
4490 case 6 : b+= ((uint32_t) data[5] << 8);
4491 case 5 : b+= data[4];
4492 case 4 : a+= ((uint32_t) data[3] << 24);
4493 case 3 : a+= ((uint32_t) data[2] << 16);
4494 case 2 : a+= ((uint32_t) data[1] << 8);
4495 case 1 : a+= data[0];
4503 _create_font_subset_tag (cairo_scaled_font_subset_t *font_subset,
4504 const char *font_name,
4512 hash = _hash_data ((unsigned char *) font_name, strlen(font_name), 0);
4513 hash = _hash_data ((unsigned char *) (font_subset->glyphs),
4514 font_subset->num_glyphs * sizeof(unsigned long), hash);
4516 numerator = abs (hash);
4517 for (i = 0; i < 6; i++) {
4518 d = ldiv (numerator, 26);
4520 tag[i] = 'A' + d.rem;
4525 static cairo_int_status_t
4526 _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
4527 cairo_scaled_font_subset_t *font_subset,
4528 cairo_pdf_resource_t *stream)
4530 unsigned int i, num_bfchar;
4531 cairo_int_status_t status;
4535 status = _cairo_pdf_surface_open_stream (surface,
4537 surface->compress_content,
4539 if (unlikely (status))
4542 _cairo_output_stream_printf (surface->output,
4543 "/CIDInit /ProcSet findresource begin\n"
4547 "<< /Registry (Adobe)\n"
4548 " /Ordering (UCS)\n"
4551 "/CMapName /Adobe-Identity-UCS def\n"
4553 "1 begincodespacerange\n");
4555 if (font_subset->is_composite && !font_subset->is_latin) {
4556 _cairo_output_stream_printf (surface->output,
4559 _cairo_output_stream_printf (surface->output,
4563 _cairo_output_stream_printf (surface->output,
4564 "endcodespacerange\n");
4566 if (font_subset->is_scaled) {
4567 /* Type 3 fonts include glyph 0 in the subset */
4568 num_bfchar = font_subset->num_glyphs;
4570 /* The CMap specification has a limit of 100 characters per beginbfchar operator */
4571 _cairo_output_stream_printf (surface->output,
4573 num_bfchar > 100 ? 100 : num_bfchar);
4575 for (i = 0; i < num_bfchar; i++) {
4576 if (i != 0 && i % 100 == 0) {
4577 _cairo_output_stream_printf (surface->output,
4580 num_bfchar - i > 100 ? 100 : num_bfchar - i);
4582 _cairo_output_stream_printf (surface->output, "<%02x> ", i);
4583 status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
4584 font_subset->utf8[i]);
4585 if (unlikely (status))
4588 _cairo_output_stream_printf (surface->output,
4592 /* Other fonts reserve glyph 0 for .notdef. Omit glyph 0 from the /ToUnicode map */
4593 num_bfchar = font_subset->num_glyphs - 1;
4595 /* The CMap specification has a limit of 100 characters per beginbfchar operator */
4596 _cairo_output_stream_printf (surface->output,
4598 num_bfchar > 100 ? 100 : num_bfchar);
4600 for (i = 0; i < num_bfchar; i++) {
4601 if (i != 0 && i % 100 == 0) {
4602 _cairo_output_stream_printf (surface->output,
4605 num_bfchar - i > 100 ? 100 : num_bfchar - i);
4607 if (font_subset->is_latin)
4608 _cairo_output_stream_printf (surface->output, "<%02x> ", font_subset->to_latin_char[i + 1]);
4609 else if (font_subset->is_composite)
4610 _cairo_output_stream_printf (surface->output, "<%04x> ", i + 1);
4612 _cairo_output_stream_printf (surface->output, "<%02x> ", i + 1);
4614 status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
4615 font_subset->utf8[i + 1]);
4616 if (unlikely (status))
4619 _cairo_output_stream_printf (surface->output,
4624 _cairo_output_stream_printf (surface->output,
4627 _cairo_output_stream_printf (surface->output,
4629 "CMapName currentdict /CMap defineresource pop\n"
4633 *stream = surface->pdf_stream.self;
4634 return _cairo_pdf_surface_close_stream (surface);
4637 #define PDF_UNITS_PER_EM 1000
4639 static cairo_status_t
4640 _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
4641 cairo_scaled_font_subset_t *font_subset,
4642 cairo_cff_subset_t *subset)
4644 cairo_pdf_resource_t stream, descriptor, cidfont_dict;
4645 cairo_pdf_resource_t subset_resource, to_unicode_stream;
4646 cairo_pdf_font_t font;
4647 unsigned int i, last_glyph;
4648 cairo_status_t status;
4651 _create_font_subset_tag (font_subset, subset->ps_name, tag);
4653 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
4654 font_subset->font_id,
4655 font_subset->subset_id);
4656 if (subset_resource.id == 0)
4657 return CAIRO_STATUS_SUCCESS;
4659 status = _cairo_pdf_surface_open_stream (surface,
4662 font_subset->is_latin ?
4663 " /Subtype /Type1C\n" :
4664 " /Subtype /CIDFontType0C\n");
4665 if (unlikely (status))
4668 stream = surface->pdf_stream.self;
4669 _cairo_output_stream_write (surface->output,
4670 subset->data, subset->data_length);
4671 status = _cairo_pdf_surface_close_stream (surface);
4672 if (unlikely (status))
4675 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
4677 &to_unicode_stream);
4678 if (_cairo_status_is_error (status))
4681 descriptor = _cairo_pdf_surface_new_object (surface);
4682 if (descriptor.id == 0)
4683 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4685 _cairo_output_stream_printf (surface->output,
4687 "<< /Type /FontDescriptor\n"
4688 " /FontName /%s+%s\n",
4693 if (subset->family_name_utf8) {
4696 status = _utf8_to_pdf_string (subset->family_name_utf8, &pdf_str);
4697 if (unlikely (status))
4700 _cairo_output_stream_printf (surface->output,
4701 " /FontFamily %s\n",
4706 _cairo_output_stream_printf (surface->output,
4708 " /FontBBox [ %ld %ld %ld %ld ]\n"
4715 " /FontFile3 %u 0 R\n"
4718 (long)(subset->x_min*PDF_UNITS_PER_EM),
4719 (long)(subset->y_min*PDF_UNITS_PER_EM),
4720 (long)(subset->x_max*PDF_UNITS_PER_EM),
4721 (long)(subset->y_max*PDF_UNITS_PER_EM),
4722 (long)(subset->ascent*PDF_UNITS_PER_EM),
4723 (long)(subset->descent*PDF_UNITS_PER_EM),
4724 (long)(subset->y_max*PDF_UNITS_PER_EM),
4727 if (font_subset->is_latin) {
4728 /* find last glyph used */
4729 for (i = 255; i >= 32; i--)
4730 if (font_subset->latin_to_subset_glyph_index[i] > 0)
4734 _cairo_pdf_surface_update_object (surface, subset_resource);
4735 _cairo_output_stream_printf (surface->output,
4738 " /Subtype /Type1\n"
4739 " /BaseFont /%s+%s\n"
4742 " /FontDescriptor %d 0 R\n"
4743 " /Encoding /WinAnsiEncoding\n"
4751 for (i = 32; i < last_glyph + 1; i++) {
4752 int glyph = font_subset->latin_to_subset_glyph_index[i];
4754 _cairo_output_stream_printf (surface->output,
4756 (long)(subset->widths[glyph]*PDF_UNITS_PER_EM));
4758 _cairo_output_stream_printf (surface->output, " 0");
4762 _cairo_output_stream_printf (surface->output,
4765 if (to_unicode_stream.id != 0)
4766 _cairo_output_stream_printf (surface->output,
4767 " /ToUnicode %d 0 R\n",
4768 to_unicode_stream.id);
4770 _cairo_output_stream_printf (surface->output,
4774 cidfont_dict = _cairo_pdf_surface_new_object (surface);
4775 if (cidfont_dict.id == 0)
4776 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4778 _cairo_output_stream_printf (surface->output,
4781 " /Subtype /CIDFontType0\n"
4782 " /BaseFont /%s+%s\n"
4784 " << /Registry (Adobe)\n"
4785 " /Ordering (Identity)\n"
4788 " /FontDescriptor %d 0 R\n"
4795 for (i = 0; i < font_subset->num_glyphs; i++)
4796 _cairo_output_stream_printf (surface->output,
4798 (long)(subset->widths[i]*PDF_UNITS_PER_EM));
4800 _cairo_output_stream_printf (surface->output,
4805 _cairo_pdf_surface_update_object (surface, subset_resource);
4806 _cairo_output_stream_printf (surface->output,
4809 " /Subtype /Type0\n"
4810 " /BaseFont /%s+%s\n"
4811 " /Encoding /Identity-H\n"
4812 " /DescendantFonts [ %d 0 R]\n",
4818 if (to_unicode_stream.id != 0)
4819 _cairo_output_stream_printf (surface->output,
4820 " /ToUnicode %d 0 R\n",
4821 to_unicode_stream.id);
4823 _cairo_output_stream_printf (surface->output,
4828 font.font_id = font_subset->font_id;
4829 font.subset_id = font_subset->subset_id;
4830 font.subset_resource = subset_resource;
4831 status = _cairo_array_append (&surface->fonts, &font);
4836 static cairo_status_t
4837 _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
4838 cairo_scaled_font_subset_t *font_subset)
4840 cairo_status_t status;
4841 cairo_cff_subset_t subset;
4844 snprintf (name, sizeof name, "CairoFont-%d-%d",
4845 font_subset->font_id, font_subset->subset_id);
4846 status = _cairo_cff_subset_init (&subset, name, font_subset);
4847 if (unlikely (status))
4850 status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
4852 _cairo_cff_subset_fini (&subset);
4857 static cairo_status_t
4858 _cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t *surface,
4859 cairo_scaled_font_subset_t *font_subset)
4861 cairo_status_t status;
4862 cairo_cff_subset_t subset;
4865 /* CFF fallback subsetting does not work with 8-bit glyphs unless
4866 * they are a latin subset */
4867 if (!font_subset->is_composite && !font_subset->is_latin)
4868 return CAIRO_INT_STATUS_UNSUPPORTED;
4870 snprintf (name, sizeof name, "CairoFont-%d-%d",
4871 font_subset->font_id, font_subset->subset_id);
4872 status = _cairo_cff_fallback_init (&subset, name, font_subset);
4873 if (unlikely (status))
4876 status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
4878 _cairo_cff_fallback_fini (&subset);
4883 static cairo_status_t
4884 _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
4885 cairo_scaled_font_subset_t *font_subset,
4886 cairo_type1_subset_t *subset)
4888 cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
4889 cairo_pdf_font_t font;
4890 cairo_status_t status;
4891 unsigned long length;
4892 unsigned int i, last_glyph;
4895 _create_font_subset_tag (font_subset, subset->base_font, tag);
4897 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
4898 font_subset->font_id,
4899 font_subset->subset_id);
4900 if (subset_resource.id == 0)
4901 return CAIRO_STATUS_SUCCESS;
4903 length = subset->header_length + subset->data_length + subset->trailer_length;
4904 status = _cairo_pdf_surface_open_stream (surface,
4910 subset->header_length,
4911 subset->data_length,
4912 subset->trailer_length);
4913 if (unlikely (status))
4916 stream = surface->pdf_stream.self;
4917 _cairo_output_stream_write (surface->output, subset->data, length);
4918 status = _cairo_pdf_surface_close_stream (surface);
4919 if (unlikely (status))
4922 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
4924 &to_unicode_stream);
4925 if (_cairo_status_is_error (status))
4928 last_glyph = font_subset->num_glyphs - 1;
4929 if (font_subset->is_latin) {
4930 /* find last glyph used */
4931 for (i = 255; i >= 32; i--)
4932 if (font_subset->latin_to_subset_glyph_index[i] > 0)
4938 descriptor = _cairo_pdf_surface_new_object (surface);
4939 if (descriptor.id == 0)
4940 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4942 _cairo_output_stream_printf (surface->output,
4944 "<< /Type /FontDescriptor\n"
4945 " /FontName /%s+%s\n"
4947 " /FontBBox [ %ld %ld %ld %ld ]\n"
4954 " /FontFile %u 0 R\n"
4960 (long)(subset->x_min*PDF_UNITS_PER_EM),
4961 (long)(subset->y_min*PDF_UNITS_PER_EM),
4962 (long)(subset->x_max*PDF_UNITS_PER_EM),
4963 (long)(subset->y_max*PDF_UNITS_PER_EM),
4964 (long)(subset->ascent*PDF_UNITS_PER_EM),
4965 (long)(subset->descent*PDF_UNITS_PER_EM),
4966 (long)(subset->y_max*PDF_UNITS_PER_EM),
4969 _cairo_pdf_surface_update_object (surface, subset_resource);
4970 _cairo_output_stream_printf (surface->output,
4973 " /Subtype /Type1\n"
4974 " /BaseFont /%s+%s\n"
4977 " /FontDescriptor %d 0 R\n",
4981 font_subset->is_latin ? 32 : 0,
4985 if (font_subset->is_latin)
4986 _cairo_output_stream_printf (surface->output, " /Encoding /WinAnsiEncoding\n");
4988 _cairo_output_stream_printf (surface->output, " /Widths [");
4989 if (font_subset->is_latin) {
4990 for (i = 32; i < last_glyph + 1; i++) {
4991 int glyph = font_subset->latin_to_subset_glyph_index[i];
4993 _cairo_output_stream_printf (surface->output,
4995 (long)(subset->widths[glyph]*PDF_UNITS_PER_EM));
4997 _cairo_output_stream_printf (surface->output, " 0");
5001 for (i = 0; i < font_subset->num_glyphs; i++)
5002 _cairo_output_stream_printf (surface->output,
5004 (long)(subset->widths[i]*PDF_UNITS_PER_EM));
5007 _cairo_output_stream_printf (surface->output,
5010 if (to_unicode_stream.id != 0)
5011 _cairo_output_stream_printf (surface->output,
5012 " /ToUnicode %d 0 R\n",
5013 to_unicode_stream.id);
5015 _cairo_output_stream_printf (surface->output,
5019 font.font_id = font_subset->font_id;
5020 font.subset_id = font_subset->subset_id;
5021 font.subset_resource = subset_resource;
5022 return _cairo_array_append (&surface->fonts, &font);
5025 static cairo_status_t
5026 _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
5027 cairo_scaled_font_subset_t *font_subset)
5029 cairo_status_t status;
5030 cairo_type1_subset_t subset;
5033 /* 16-bit glyphs not compatible with Type 1 fonts */
5034 if (font_subset->is_composite && !font_subset->is_latin)
5035 return CAIRO_INT_STATUS_UNSUPPORTED;
5037 snprintf (name, sizeof name, "CairoFont-%d-%d",
5038 font_subset->font_id, font_subset->subset_id);
5039 status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE);
5040 if (unlikely (status))
5043 status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
5045 _cairo_type1_subset_fini (&subset);
5049 static cairo_status_t
5050 _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
5051 cairo_scaled_font_subset_t *font_subset)
5053 cairo_status_t status;
5054 cairo_type1_subset_t subset;
5057 /* 16-bit glyphs not compatible with Type 1 fonts */
5058 if (font_subset->is_composite && !font_subset->is_latin)
5059 return CAIRO_INT_STATUS_UNSUPPORTED;
5061 snprintf (name, sizeof name, "CairoFont-%d-%d",
5062 font_subset->font_id, font_subset->subset_id);
5063 status = _cairo_type1_fallback_init_binary (&subset, name, font_subset);
5064 if (unlikely (status))
5067 status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
5069 _cairo_type1_fallback_fini (&subset);
5073 static cairo_status_t
5074 _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
5075 cairo_scaled_font_subset_t *font_subset)
5077 cairo_pdf_resource_t stream, descriptor, cidfont_dict;
5078 cairo_pdf_resource_t subset_resource, to_unicode_stream;
5079 cairo_status_t status;
5080 cairo_pdf_font_t font;
5081 cairo_truetype_subset_t subset;
5082 unsigned int i, last_glyph;
5085 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
5086 font_subset->font_id,
5087 font_subset->subset_id);
5088 if (subset_resource.id == 0)
5089 return CAIRO_STATUS_SUCCESS;
5091 status = _cairo_truetype_subset_init_pdf (&subset, font_subset);
5092 if (unlikely (status))
5095 _create_font_subset_tag (font_subset, subset.ps_name, tag);
5097 status = _cairo_pdf_surface_open_stream (surface,
5101 subset.data_length);
5102 if (unlikely (status)) {
5103 _cairo_truetype_subset_fini (&subset);
5107 stream = surface->pdf_stream.self;
5108 _cairo_output_stream_write (surface->output,
5109 subset.data, subset.data_length);
5110 status = _cairo_pdf_surface_close_stream (surface);
5111 if (unlikely (status)) {
5112 _cairo_truetype_subset_fini (&subset);
5116 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
5118 &to_unicode_stream);
5119 if (_cairo_status_is_error (status)) {
5120 _cairo_truetype_subset_fini (&subset);
5124 descriptor = _cairo_pdf_surface_new_object (surface);
5125 if (descriptor.id == 0) {
5126 _cairo_truetype_subset_fini (&subset);
5127 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5130 _cairo_output_stream_printf (surface->output,
5132 "<< /Type /FontDescriptor\n"
5133 " /FontName /%s+%s\n",
5138 if (subset.family_name_utf8) {
5141 status = _utf8_to_pdf_string (subset.family_name_utf8, &pdf_str);
5142 if (unlikely (status))
5145 _cairo_output_stream_printf (surface->output,
5146 " /FontFamily %s\n",
5151 _cairo_output_stream_printf (surface->output,
5153 " /FontBBox [ %ld %ld %ld %ld ]\n"
5160 " /FontFile2 %u 0 R\n"
5163 font_subset->is_latin ? 32 : 4,
5164 (long)(subset.x_min*PDF_UNITS_PER_EM),
5165 (long)(subset.y_min*PDF_UNITS_PER_EM),
5166 (long)(subset.x_max*PDF_UNITS_PER_EM),
5167 (long)(subset.y_max*PDF_UNITS_PER_EM),
5168 (long)(subset.ascent*PDF_UNITS_PER_EM),
5169 (long)(subset.descent*PDF_UNITS_PER_EM),
5170 (long)(subset.y_max*PDF_UNITS_PER_EM),
5173 if (font_subset->is_latin) {
5174 /* find last glyph used */
5175 for (i = 255; i >= 32; i--)
5176 if (font_subset->latin_to_subset_glyph_index[i] > 0)
5180 _cairo_pdf_surface_update_object (surface, subset_resource);
5181 _cairo_output_stream_printf (surface->output,
5184 " /Subtype /TrueType\n"
5185 " /BaseFont /%s+%s\n"
5188 " /FontDescriptor %d 0 R\n"
5189 " /Encoding /WinAnsiEncoding\n"
5197 for (i = 32; i < last_glyph + 1; i++) {
5198 int glyph = font_subset->latin_to_subset_glyph_index[i];
5200 _cairo_output_stream_printf (surface->output,
5202 (long)(subset.widths[glyph]*PDF_UNITS_PER_EM));
5204 _cairo_output_stream_printf (surface->output, " 0");
5208 _cairo_output_stream_printf (surface->output,
5211 if (to_unicode_stream.id != 0)
5212 _cairo_output_stream_printf (surface->output,
5213 " /ToUnicode %d 0 R\n",
5214 to_unicode_stream.id);
5216 _cairo_output_stream_printf (surface->output,
5220 cidfont_dict = _cairo_pdf_surface_new_object (surface);
5221 if (cidfont_dict.id == 0) {
5222 _cairo_truetype_subset_fini (&subset);
5223 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5226 _cairo_output_stream_printf (surface->output,
5229 " /Subtype /CIDFontType2\n"
5230 " /BaseFont /%s+%s\n"
5232 " << /Registry (Adobe)\n"
5233 " /Ordering (Identity)\n"
5236 " /FontDescriptor %d 0 R\n"
5243 for (i = 0; i < font_subset->num_glyphs; i++)
5244 _cairo_output_stream_printf (surface->output,
5246 (long)(subset.widths[i]*PDF_UNITS_PER_EM));
5248 _cairo_output_stream_printf (surface->output,
5253 _cairo_pdf_surface_update_object (surface, subset_resource);
5254 _cairo_output_stream_printf (surface->output,
5257 " /Subtype /Type0\n"
5258 " /BaseFont /%s+%s\n"
5259 " /Encoding /Identity-H\n"
5260 " /DescendantFonts [ %d 0 R]\n",
5266 if (to_unicode_stream.id != 0)
5267 _cairo_output_stream_printf (surface->output,
5268 " /ToUnicode %d 0 R\n",
5269 to_unicode_stream.id);
5271 _cairo_output_stream_printf (surface->output,
5276 font.font_id = font_subset->font_id;
5277 font.subset_id = font_subset->subset_id;
5278 font.subset_resource = subset_resource;
5279 status = _cairo_array_append (&surface->fonts, &font);
5281 _cairo_truetype_subset_fini (&subset);
5286 static cairo_status_t
5287 _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
5288 cairo_output_stream_t *stream)
5290 uint8_t *byte, output_byte;
5291 int row, col, num_cols;
5293 /* The only image type supported by Type 3 fonts are 1-bit image
5295 assert (image->format == CAIRO_FORMAT_A1);
5297 _cairo_output_stream_printf (stream,
5307 _cairo_output_stream_printf (stream,
5310 num_cols = (image->width + 7) / 8;
5311 for (row = 0; row < image->height; row++) {
5312 byte = image->data + row * image->stride;
5313 for (col = 0; col < num_cols; col++) {
5314 output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
5315 _cairo_output_stream_write (stream, &output_byte, 1);
5320 _cairo_output_stream_printf (stream,
5323 return _cairo_output_stream_get_status (stream);
5326 static cairo_int_status_t
5327 _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
5330 cairo_pdf_surface_t *surface = closure;
5331 cairo_status_t status = CAIRO_STATUS_SUCCESS;
5332 cairo_status_t status2;
5334 cairo_surface_t *type3_surface;
5335 cairo_output_stream_t *null_stream;
5337 null_stream = _cairo_null_stream_create ();
5338 type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
5340 _cairo_pdf_emit_imagemask,
5341 surface->font_subsets);
5342 if (unlikely (type3_surface->status)) {
5343 status2 = _cairo_output_stream_destroy (null_stream);
5344 return type3_surface->status;
5347 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
5348 _cairo_pdf_surface_add_font,
5351 for (i = 0; i < font_subset->num_glyphs; i++) {
5352 status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
5353 font_subset->glyphs[i]);
5354 if (unlikely (status))
5358 cairo_surface_destroy (type3_surface);
5359 status2 = _cairo_output_stream_destroy (null_stream);
5360 if (status == CAIRO_STATUS_SUCCESS)
5366 static cairo_int_status_t
5367 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
5368 cairo_scaled_font_subset_t *font_subset)
5370 cairo_status_t status = CAIRO_STATUS_SUCCESS;
5371 cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
5372 cairo_pdf_font_t font;
5375 cairo_box_t font_bbox = {{0,0},{0,0}};
5376 cairo_box_t bbox = {{0,0},{0,0}};
5377 cairo_surface_t *type3_surface;
5379 if (font_subset->num_glyphs == 0)
5380 return CAIRO_STATUS_SUCCESS;
5382 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
5383 font_subset->font_id,
5384 font_subset->subset_id);
5385 if (subset_resource.id == 0)
5386 return CAIRO_STATUS_SUCCESS;
5388 glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
5389 if (unlikely (glyphs == NULL))
5390 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5392 widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
5393 if (unlikely (widths == NULL)) {
5395 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5398 _cairo_pdf_group_resources_clear (&surface->resources);
5399 type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
5401 _cairo_pdf_emit_imagemask,
5402 surface->font_subsets);
5403 if (unlikely (type3_surface->status)) {
5406 return type3_surface->status;
5409 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
5410 _cairo_pdf_surface_add_font,
5413 for (i = 0; i < font_subset->num_glyphs; i++) {
5414 status = _cairo_pdf_surface_open_stream (surface,
5416 surface->compress_content,
5418 if (unlikely (status))
5421 glyphs[i] = surface->pdf_stream.self;
5422 status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
5424 font_subset->glyphs[i],
5427 if (unlikely (status))
5430 status = _cairo_pdf_surface_close_stream (surface);
5431 if (unlikely (status))
5435 font_bbox.p1.x = bbox.p1.x;
5436 font_bbox.p1.y = bbox.p1.y;
5437 font_bbox.p2.x = bbox.p2.x;
5438 font_bbox.p2.y = bbox.p2.y;
5440 if (bbox.p1.x < font_bbox.p1.x)
5441 font_bbox.p1.x = bbox.p1.x;
5442 if (bbox.p1.y < font_bbox.p1.y)
5443 font_bbox.p1.y = bbox.p1.y;
5444 if (bbox.p2.x > font_bbox.p2.x)
5445 font_bbox.p2.x = bbox.p2.x;
5446 if (bbox.p2.y > font_bbox.p2.y)
5447 font_bbox.p2.y = bbox.p2.y;
5450 cairo_surface_destroy (type3_surface);
5451 if (unlikely (status)) {
5457 encoding = _cairo_pdf_surface_new_object (surface);
5458 if (encoding.id == 0) {
5461 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5464 _cairo_output_stream_printf (surface->output,
5466 "<< /Type /Encoding\n"
5467 " /Differences [0", encoding.id);
5468 for (i = 0; i < font_subset->num_glyphs; i++)
5469 _cairo_output_stream_printf (surface->output,
5471 _cairo_output_stream_printf (surface->output,
5476 char_procs = _cairo_pdf_surface_new_object (surface);
5477 if (char_procs.id == 0) {
5480 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5483 _cairo_output_stream_printf (surface->output,
5485 "<<\n", char_procs.id);
5486 for (i = 0; i < font_subset->num_glyphs; i++)
5487 _cairo_output_stream_printf (surface->output,
5490 _cairo_output_stream_printf (surface->output,
5496 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
5498 &to_unicode_stream);
5499 if (_cairo_status_is_error (status)) {
5504 _cairo_pdf_surface_update_object (surface, subset_resource);
5505 _cairo_output_stream_printf (surface->output,
5508 " /Subtype /Type3\n"
5509 " /FontBBox [%f %f %f %f]\n"
5510 " /FontMatrix [ 1 0 0 1 0 0 ]\n"
5511 " /Encoding %d 0 R\n"
5512 " /CharProcs %d 0 R\n"
5516 _cairo_fixed_to_double (font_bbox.p1.x),
5517 - _cairo_fixed_to_double (font_bbox.p2.y),
5518 _cairo_fixed_to_double (font_bbox.p2.x),
5519 - _cairo_fixed_to_double (font_bbox.p1.y),
5522 font_subset->num_glyphs - 1);
5524 _cairo_output_stream_printf (surface->output,
5526 for (i = 0; i < font_subset->num_glyphs; i++)
5527 _cairo_output_stream_printf (surface->output, " %f", widths[i]);
5528 _cairo_output_stream_printf (surface->output,
5532 _cairo_output_stream_printf (surface->output,
5534 _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
5536 if (to_unicode_stream.id != 0)
5537 _cairo_output_stream_printf (surface->output,
5538 " /ToUnicode %d 0 R\n",
5539 to_unicode_stream.id);
5541 _cairo_output_stream_printf (surface->output,
5545 font.font_id = font_subset->font_id;
5546 font.subset_id = font_subset->subset_id;
5547 font.subset_resource = subset_resource;
5548 return _cairo_array_append (&surface->fonts, &font);
5551 static cairo_int_status_t
5552 _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
5555 cairo_pdf_surface_t *surface = closure;
5556 cairo_int_status_t status;
5558 status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
5559 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5562 status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
5563 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5566 status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
5567 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5570 status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
5571 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5574 status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
5575 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5579 return CAIRO_INT_STATUS_SUCCESS;
5582 static cairo_int_status_t
5583 _cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
5586 cairo_pdf_surface_t *surface = closure;
5587 cairo_int_status_t status;
5589 status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
5590 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
5594 return CAIRO_INT_STATUS_SUCCESS;
5597 static cairo_status_t
5598 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
5600 cairo_status_t status;
5602 status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
5603 _cairo_pdf_surface_analyze_user_font_subset,
5605 if (unlikely (status))
5608 status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
5609 _cairo_pdf_surface_emit_unscaled_font_subset,
5611 if (unlikely (status))
5614 status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
5615 _cairo_pdf_surface_emit_scaled_font_subset,
5617 if (unlikely (status))
5620 status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
5621 _cairo_pdf_surface_emit_scaled_font_subset,
5625 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
5626 surface->font_subsets = NULL;
5631 static cairo_pdf_resource_t
5632 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface)
5634 cairo_pdf_resource_t catalog;
5636 catalog = _cairo_pdf_surface_new_object (surface);
5637 if (catalog.id == 0)
5640 _cairo_output_stream_printf (surface->output,
5642 "<< /Type /Catalog\n"
5647 surface->pages_resource.id);
5653 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
5655 cairo_pdf_object_t *object;
5660 num_objects = _cairo_array_num_elements (&surface->objects);
5662 offset = _cairo_output_stream_get_position (surface->output);
5663 _cairo_output_stream_printf (surface->output,
5666 0, num_objects + 1);
5668 _cairo_output_stream_printf (surface->output,
5669 "0000000000 65535 f \n");
5670 for (i = 0; i < num_objects; i++) {
5671 object = _cairo_array_index (&surface->objects, i);
5672 snprintf (buffer, sizeof buffer, "%010ld", object->offset);
5673 _cairo_output_stream_printf (surface->output,
5674 "%s 00000 n \n", buffer);
5680 static cairo_status_t
5681 _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
5682 cairo_pdf_smask_group_t *group)
5684 cairo_pdf_resource_t mask_group;
5685 cairo_pdf_resource_t smask;
5686 cairo_pdf_smask_group_t *smask_group;
5687 cairo_pdf_resource_t pattern_res, gstate_res;
5688 cairo_status_t status;
5689 cairo_box_double_t bbox;
5691 /* Create mask group */
5692 _get_bbox_from_extents (group->height, &group->extents, &bbox);
5693 status = _cairo_pdf_surface_open_group (surface, &bbox, NULL);
5694 if (unlikely (status))
5697 if (_can_paint_pattern (group->mask)) {
5698 _cairo_output_stream_printf (surface->output, "q\n");
5699 status = _cairo_pdf_surface_paint_pattern (surface,
5703 if (unlikely (status))
5706 _cairo_output_stream_printf (surface->output, "Q\n");
5710 status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, NULL,
5711 &pattern_res, &gstate_res);
5712 if (unlikely (status))
5715 if (gstate_res.id != 0) {
5716 smask_group = _cairo_pdf_surface_create_smask_group (surface, &group->extents);
5717 if (unlikely (smask_group == NULL))
5718 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5720 smask_group->width = group->width;
5721 smask_group->height = group->height;
5722 smask_group->operation = PDF_PAINT;
5723 smask_group->source = cairo_pattern_reference (group->mask);
5724 smask_group->source_res = pattern_res;
5725 status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
5726 if (unlikely (status)) {
5727 _cairo_pdf_smask_group_destroy (smask_group);
5731 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5732 if (unlikely (status))
5735 status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
5736 if (unlikely (status))
5739 _cairo_output_stream_printf (surface->output,
5740 "q /s%d gs /x%d Do Q\n",
5742 smask_group->group_res.id);
5744 status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE);
5745 if (unlikely (status))
5748 _cairo_output_stream_printf (surface->output,
5749 "%f %f %f %f re f\n",
5752 bbox.p2.x - bbox.p1.x,
5753 bbox.p2.y - bbox.p1.y);
5755 status = _cairo_pdf_surface_unselect_pattern (surface);
5756 if (unlikely (status))
5761 status = _cairo_pdf_surface_close_group (surface, &mask_group);
5762 if (unlikely (status))
5765 /* Create source group */
5766 status = _cairo_pdf_surface_open_group (surface, &bbox, &group->source_res);
5767 if (unlikely (status))
5770 if (_can_paint_pattern (group->source)) {
5771 _cairo_output_stream_printf (surface->output, "q\n");
5772 status = _cairo_pdf_surface_paint_pattern (surface,
5776 if (unlikely (status))
5779 _cairo_output_stream_printf (surface->output, "Q\n");
5783 status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, NULL,
5784 &pattern_res, &gstate_res);
5785 if (unlikely (status))
5788 if (gstate_res.id != 0) {
5789 smask_group = _cairo_pdf_surface_create_smask_group (surface, &group->extents);
5790 if (unlikely (smask_group == NULL))
5791 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5793 smask_group->operation = PDF_PAINT;
5794 smask_group->source = cairo_pattern_reference (group->source);
5795 smask_group->source_res = pattern_res;
5796 status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
5797 if (unlikely (status)) {
5798 _cairo_pdf_smask_group_destroy (smask_group);
5802 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5803 if (unlikely (status))
5806 status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
5807 if (unlikely (status))
5810 _cairo_output_stream_printf (surface->output,
5811 "q /s%d gs /x%d Do Q\n",
5813 smask_group->group_res.id);
5815 status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE);
5816 if (unlikely (status))
5819 _cairo_output_stream_printf (surface->output,
5820 "%f %f %f %f re f\n",
5823 bbox.p2.x - bbox.p1.x,
5824 bbox.p2.y - bbox.p1.y);
5826 status = _cairo_pdf_surface_unselect_pattern (surface);
5827 if (unlikely (status))
5832 status = _cairo_pdf_surface_close_group (surface, NULL);
5833 if (unlikely (status))
5836 /* Create an smask based on the alpha component of mask_group */
5837 smask = _cairo_pdf_surface_new_object (surface);
5839 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5841 _cairo_output_stream_printf (surface->output,
5851 /* Create a GState that uses the smask */
5852 _cairo_pdf_surface_update_object (surface, group->group_res);
5853 _cairo_output_stream_printf (surface->output,
5855 "<< /Type /ExtGState\n"
5862 group->group_res.id,
5865 return _cairo_output_stream_get_status (surface->output);
5868 static cairo_status_t
5869 _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
5870 cairo_pdf_smask_group_t *group)
5872 double old_width, old_height;
5873 cairo_status_t status;
5874 cairo_box_double_t bbox;
5876 old_width = surface->width;
5877 old_height = surface->height;
5878 _cairo_pdf_surface_set_size_internal (surface,
5881 /* _mask is a special case that requires two groups - source
5882 * and mask as well as a smask and gstate dictionary */
5883 if (group->operation == PDF_MASK) {
5884 status = _cairo_pdf_surface_write_mask_group (surface, group);
5888 _get_bbox_from_extents (group->height, &group->extents, &bbox);
5889 status = _cairo_pdf_surface_open_group (surface, &bbox, &group->group_res);
5890 if (unlikely (status))
5893 status = _cairo_pdf_surface_select_pattern (surface,
5896 group->operation == PDF_STROKE);
5897 if (unlikely (status))
5900 switch (group->operation) {
5902 _cairo_output_stream_printf (surface->output,
5904 surface->width, surface->height);
5910 status = _cairo_pdf_operators_fill (&surface->pdf_operators,
5915 status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
5919 &group->ctm_inverse);
5921 case PDF_SHOW_GLYPHS:
5922 status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
5923 group->utf8, group->utf8_len,
5924 group->glyphs, group->num_glyphs,
5925 group->clusters, group->num_clusters,
5926 group->cluster_flags,
5927 group->scaled_font);
5930 if (unlikely (status))
5933 status = _cairo_pdf_surface_unselect_pattern (surface);
5934 if (unlikely (status))
5937 status = _cairo_pdf_surface_close_group (surface, NULL);
5940 _cairo_pdf_surface_set_size_internal (surface,
5947 static cairo_status_t
5948 _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface)
5950 cairo_pdf_pattern_t pattern;
5951 cairo_pdf_smask_group_t *group;
5952 cairo_pdf_source_surface_t src_surface;
5953 unsigned int pattern_index, group_index, surface_index;
5954 cairo_status_t status;
5956 /* Writing out PDF_MASK groups will cause additional smask groups
5957 * to be appended to surface->smask_groups. Additional patterns
5958 * may also be appended to surface->patterns.
5960 * Writing recording surface patterns will cause additional patterns
5961 * and groups to be appended.
5966 while ((pattern_index < _cairo_array_num_elements (&surface->page_patterns)) ||
5967 (group_index < _cairo_array_num_elements (&surface->smask_groups)) ||
5968 (surface_index < _cairo_array_num_elements (&surface->page_surfaces)))
5970 for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) {
5971 _cairo_array_copy_element (&surface->smask_groups, group_index, &group);
5972 status = _cairo_pdf_surface_write_smask_group (surface, group);
5973 if (unlikely (status))
5977 for (; pattern_index < _cairo_array_num_elements (&surface->page_patterns); pattern_index++) {
5978 _cairo_array_copy_element (&surface->page_patterns, pattern_index, &pattern);
5979 status = _cairo_pdf_surface_emit_pattern (surface, &pattern);
5980 if (unlikely (status))
5984 for (; surface_index < _cairo_array_num_elements (&surface->page_surfaces); surface_index++) {
5985 _cairo_array_copy_element (&surface->page_surfaces, surface_index, &src_surface);
5986 status = _cairo_pdf_surface_emit_surface (surface, &src_surface);
5987 if (unlikely (status))
5992 return CAIRO_STATUS_SUCCESS;
5995 static cairo_status_t
5996 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
5998 cairo_pdf_resource_t page, knockout, res;
5999 cairo_status_t status;
6000 unsigned int i, len;
6002 _cairo_pdf_group_resources_clear (&surface->resources);
6003 if (surface->has_fallback_images) {
6004 cairo_rectangle_int_t extents;
6005 cairo_box_double_t bbox;
6009 extents.width = ceil (surface->width);
6010 extents.height = ceil (surface->height);
6011 _get_bbox_from_extents (surface->height, &extents, &bbox);
6012 status = _cairo_pdf_surface_open_knockout_group (surface, &bbox);
6013 if (unlikely (status))
6016 len = _cairo_array_num_elements (&surface->knockout_group);
6017 for (i = 0; i < len; i++) {
6018 _cairo_array_copy_element (&surface->knockout_group, i, &res);
6019 _cairo_output_stream_printf (surface->output,
6022 status = _cairo_pdf_surface_add_xobject (surface, res);
6023 if (unlikely (status))
6026 _cairo_output_stream_printf (surface->output,
6028 surface->content.id);
6029 status = _cairo_pdf_surface_add_xobject (surface, surface->content);
6030 if (unlikely (status))
6033 status = _cairo_pdf_surface_close_group (surface, &knockout);
6034 if (unlikely (status))
6037 _cairo_pdf_group_resources_clear (&surface->resources);
6038 status = _cairo_pdf_surface_open_content_stream (surface, NULL, NULL, FALSE);
6039 if (unlikely (status))
6042 _cairo_output_stream_printf (surface->output,
6045 status = _cairo_pdf_surface_add_xobject (surface, knockout);
6046 if (unlikely (status))
6049 status = _cairo_pdf_surface_close_content_stream (surface);
6050 if (unlikely (status))
6054 page = _cairo_pdf_surface_new_object (surface);
6056 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6058 _cairo_output_stream_printf (surface->output,
6062 " /MediaBox [ 0 0 %f %f ]\n"
6063 " /Contents %d 0 R\n"
6066 " /S /Transparency\n"
6070 " /Resources %d 0 R\n"
6074 surface->pages_resource.id,
6077 surface->content.id,
6078 surface->content_resources.id);
6080 status = _cairo_array_append (&surface->pages, &page);
6081 if (unlikely (status))
6084 status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface);
6085 if (unlikely (status))
6088 return CAIRO_STATUS_SUCCESS;
6091 static cairo_int_status_t
6092 _cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t *surface,
6093 cairo_surface_pattern_t *pattern)
6095 cairo_image_surface_t *image;
6097 cairo_int_status_t status;
6098 cairo_image_transparency_t transparency;
6100 status = _cairo_surface_acquire_source_image (pattern->surface,
6103 if (unlikely (status))
6106 if (image->base.status)
6107 return image->base.status;
6109 transparency = _cairo_image_analyze_transparency (image);
6110 if (transparency == CAIRO_IMAGE_IS_OPAQUE)
6111 status = CAIRO_STATUS_SUCCESS;
6113 status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
6115 _cairo_surface_release_source_image (pattern->surface, image, image_extra);
6121 _surface_pattern_supported (cairo_surface_pattern_t *pattern)
6123 cairo_extend_t extend;
6125 if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
6128 if (pattern->surface->backend->acquire_source_image == NULL)
6131 /* Does an ALPHA-only source surface even make sense? Maybe, but I
6132 * don't think it's worth the extra code to support it. */
6134 /* XXX: Need to write this function here...
6135 if (pattern->surface->content == CAIRO_CONTENT_ALPHA)
6139 extend = cairo_pattern_get_extend (&pattern->base);
6141 case CAIRO_EXTEND_NONE:
6142 case CAIRO_EXTEND_REPEAT:
6143 case CAIRO_EXTEND_REFLECT:
6144 /* There's no point returning FALSE for EXTEND_PAD, as the image
6145 * surface does not currently implement it either */
6146 case CAIRO_EXTEND_PAD:
6155 _pattern_supported (const cairo_pattern_t *pattern)
6157 switch (pattern->type) {
6158 case CAIRO_PATTERN_TYPE_SOLID:
6159 case CAIRO_PATTERN_TYPE_LINEAR:
6160 case CAIRO_PATTERN_TYPE_RADIAL:
6161 case CAIRO_PATTERN_TYPE_MESH:
6162 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
6165 case CAIRO_PATTERN_TYPE_SURFACE:
6166 return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
6175 _pdf_operator_supported (cairo_operator_t op)
6178 case CAIRO_OPERATOR_OVER:
6179 case CAIRO_OPERATOR_MULTIPLY:
6180 case CAIRO_OPERATOR_SCREEN:
6181 case CAIRO_OPERATOR_OVERLAY:
6182 case CAIRO_OPERATOR_DARKEN:
6183 case CAIRO_OPERATOR_LIGHTEN:
6184 case CAIRO_OPERATOR_COLOR_DODGE:
6185 case CAIRO_OPERATOR_COLOR_BURN:
6186 case CAIRO_OPERATOR_HARD_LIGHT:
6187 case CAIRO_OPERATOR_SOFT_LIGHT:
6188 case CAIRO_OPERATOR_DIFFERENCE:
6189 case CAIRO_OPERATOR_EXCLUSION:
6190 case CAIRO_OPERATOR_HSL_HUE:
6191 case CAIRO_OPERATOR_HSL_SATURATION:
6192 case CAIRO_OPERATOR_HSL_COLOR:
6193 case CAIRO_OPERATOR_HSL_LUMINOSITY:
6197 case CAIRO_OPERATOR_CLEAR:
6198 case CAIRO_OPERATOR_SOURCE:
6199 case CAIRO_OPERATOR_IN:
6200 case CAIRO_OPERATOR_OUT:
6201 case CAIRO_OPERATOR_ATOP:
6202 case CAIRO_OPERATOR_DEST:
6203 case CAIRO_OPERATOR_DEST_OVER:
6204 case CAIRO_OPERATOR_DEST_IN:
6205 case CAIRO_OPERATOR_DEST_OUT:
6206 case CAIRO_OPERATOR_DEST_ATOP:
6207 case CAIRO_OPERATOR_XOR:
6208 case CAIRO_OPERATOR_ADD:
6209 case CAIRO_OPERATOR_SATURATE:
6214 static cairo_int_status_t
6215 _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
6216 cairo_operator_t op,
6217 const cairo_pattern_t *pattern,
6218 const cairo_rectangle_int_t *extents)
6220 if (surface->force_fallbacks &&
6221 surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
6223 return CAIRO_INT_STATUS_UNSUPPORTED;
6226 if (! _pattern_supported (pattern))
6227 return CAIRO_INT_STATUS_UNSUPPORTED;
6229 if (_pdf_operator_supported (op)) {
6230 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
6231 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
6233 if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
6234 if (pattern->extend == CAIRO_EXTEND_PAD) {
6236 cairo_rectangle_int_t rect;
6237 cairo_rectangle_int_t rec_extents;
6239 /* get the operation extents in pattern space */
6240 _cairo_box_from_rectangle (&box, extents);
6241 _cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &box, NULL);
6242 _cairo_box_round_to_rectangle (&box, &rect);
6244 /* Check if surface needs padding to fill extents */
6245 if (_cairo_surface_get_extents (surface_pattern->surface, &rec_extents)) {
6246 if (_cairo_fixed_integer_ceil(box.p1.x) < rec_extents.x ||
6247 _cairo_fixed_integer_ceil(box.p1.y) < rec_extents.y ||
6248 _cairo_fixed_integer_floor(box.p2.y) > rec_extents.x + rec_extents.width ||
6249 _cairo_fixed_integer_floor(box.p2.y) > rec_extents.y + rec_extents.height)
6251 return CAIRO_INT_STATUS_UNSUPPORTED;
6255 return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
6259 return CAIRO_STATUS_SUCCESS;
6263 /* The SOURCE operator is supported if the pattern is opaque or if
6264 * there is nothing painted underneath. */
6265 if (op == CAIRO_OPERATOR_SOURCE) {
6266 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
6267 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
6269 if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
6270 if (_cairo_pattern_is_opaque (pattern, extents)) {
6271 return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
6273 /* FIXME: The analysis surface does not yet have
6274 * the capability to analyze a non opaque recording
6275 * surface and mark it supported if there is
6276 * nothing underneath. For now recording surfaces of
6277 * type CONTENT_COLOR_ALPHA painted with
6278 * OPERATOR_SOURCE will result in a fallback
6281 return CAIRO_INT_STATUS_UNSUPPORTED;
6284 return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
6289 if (_cairo_pattern_is_opaque (pattern, extents))
6290 return CAIRO_STATUS_SUCCESS;
6292 return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
6295 return CAIRO_INT_STATUS_UNSUPPORTED;
6299 _cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
6300 cairo_operator_t op,
6301 const cairo_pattern_t *pattern,
6302 const cairo_rectangle_int_t *extents)
6304 return _cairo_pdf_surface_analyze_operation (surface, op, pattern, extents) != CAIRO_INT_STATUS_UNSUPPORTED;
6307 static cairo_int_status_t
6308 _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
6310 cairo_box_double_t bbox;
6311 cairo_status_t status;
6313 status = _cairo_pdf_surface_close_content_stream (surface);
6314 if (unlikely (status))
6317 status = _cairo_array_append (&surface->knockout_group, &surface->content);
6318 if (unlikely (status))
6321 _cairo_pdf_group_resources_clear (&surface->resources);
6324 bbox.p2.x = surface->width;
6325 bbox.p2.y = surface->height;
6326 return _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, TRUE);
6329 /* A PDF stencil mask is an A1 mask used with the current color */
6330 static cairo_int_status_t
6331 _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface,
6332 const cairo_pattern_t *source,
6333 const cairo_pattern_t *mask,
6334 const cairo_rectangle_int_t *extents)
6336 cairo_status_t status;
6337 cairo_image_surface_t *image;
6339 cairo_image_transparency_t transparency;
6340 cairo_pdf_resource_t pattern_res = {0};
6342 if (! (source->type == CAIRO_PATTERN_TYPE_SOLID &&
6343 (mask->type == CAIRO_PATTERN_TYPE_SURFACE || mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)))
6344 return CAIRO_INT_STATUS_UNSUPPORTED;
6346 if (mask->type == CAIRO_PATTERN_TYPE_SURFACE &&
6347 ((cairo_surface_pattern_t *) mask)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
6349 return CAIRO_INT_STATUS_UNSUPPORTED;
6352 status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, mask,
6353 &image, &image_extra);
6354 if (unlikely (status))
6357 if (image->base.status)
6358 return image->base.status;
6360 transparency = _cairo_image_analyze_transparency (image);
6361 if (transparency != CAIRO_IMAGE_IS_OPAQUE &&
6362 transparency != CAIRO_IMAGE_HAS_BILEVEL_ALPHA)
6364 status = CAIRO_INT_STATUS_UNSUPPORTED;
6368 status = _cairo_pdf_surface_select_pattern (surface, source,
6369 pattern_res, FALSE);
6370 if (unlikely (status))
6373 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6374 if (unlikely (status))
6377 _cairo_output_stream_printf (surface->output, "q\n");
6378 status = _cairo_pdf_surface_paint_surface_pattern (surface, mask, NULL, TRUE);
6379 if (unlikely (status))
6382 _cairo_output_stream_printf (surface->output, "Q\n");
6384 status = _cairo_output_stream_get_status (surface->output);
6387 _cairo_pdf_surface_release_source_image_from_pattern (surface, mask, image, image_extra);
6392 static cairo_int_status_t
6393 _cairo_pdf_surface_set_clip (cairo_pdf_surface_t *surface,
6394 cairo_composite_rectangles_t *composite)
6396 cairo_clip_t *clip = composite->clip;
6398 if (_cairo_composite_rectangles_can_reduce_clip (composite, clip))
6402 if (_cairo_composite_rectangles_can_reduce_clip (composite,
6403 surface->clipper.clip))
6404 return CAIRO_STATUS_SUCCESS;
6407 return _cairo_surface_clipper_set_clip (&surface->clipper, clip);
6410 static cairo_int_status_t
6411 _cairo_pdf_surface_paint (void *abstract_surface,
6412 cairo_operator_t op,
6413 const cairo_pattern_t *source,
6414 const cairo_clip_t *clip)
6416 cairo_pdf_surface_t *surface = abstract_surface;
6417 cairo_pdf_smask_group_t *group;
6418 cairo_pdf_resource_t pattern_res, gstate_res;
6419 cairo_composite_rectangles_t extents;
6420 cairo_int_status_t status;
6422 status = _cairo_composite_rectangles_init_for_paint (&extents,
6425 if (unlikely (status))
6428 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
6429 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
6431 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
6432 status = _cairo_pdf_surface_start_fallback (surface);
6433 if (unlikely (status))
6437 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
6439 status = _cairo_pdf_surface_set_clip (surface, &extents);
6440 if (unlikely (status))
6443 status = _cairo_pdf_surface_select_operator (surface, op);
6444 if (unlikely (status))
6447 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6448 if (unlikely (status))
6451 if (_can_paint_pattern (source)) {
6452 _cairo_output_stream_printf (surface->output, "q\n");
6453 status = _cairo_pdf_surface_paint_pattern (surface,
6457 if (unlikely (status))
6460 _cairo_output_stream_printf (surface->output, "Q\n");
6461 _cairo_composite_rectangles_fini (&extents);
6462 return _cairo_output_stream_get_status (surface->output);
6467 status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
6469 &pattern_res, &gstate_res);
6470 if (unlikely (status))
6473 if (gstate_res.id != 0) {
6474 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
6475 if (unlikely (group == NULL)) {
6476 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
6480 group->operation = PDF_PAINT;
6481 status = _cairo_pattern_create_copy (&group->source, source);
6482 if (unlikely (status)) {
6483 _cairo_pdf_smask_group_destroy (group);
6486 group->source_res = pattern_res;
6487 status = _cairo_pdf_surface_add_smask_group (surface, group);
6488 if (unlikely (status)) {
6489 _cairo_pdf_smask_group_destroy (group);
6493 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
6494 if (unlikely (status))
6497 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
6498 if (unlikely (status))
6501 _cairo_output_stream_printf (surface->output,
6502 "q /s%d gs /x%d Do Q\n",
6504 group->group_res.id);
6506 status = _cairo_pdf_surface_select_pattern (surface, source,
6507 pattern_res, FALSE);
6508 if (unlikely (status))
6511 _cairo_output_stream_printf (surface->output,
6513 surface->width, surface->height);
6515 status = _cairo_pdf_surface_unselect_pattern (surface);
6516 if (unlikely (status))
6520 _cairo_composite_rectangles_fini (&extents);
6521 return _cairo_output_stream_get_status (surface->output);
6524 _cairo_composite_rectangles_fini (&extents);
6528 static cairo_int_status_t
6529 _cairo_pdf_surface_mask (void *abstract_surface,
6530 cairo_operator_t op,
6531 const cairo_pattern_t *source,
6532 const cairo_pattern_t *mask,
6533 const cairo_clip_t *clip)
6535 cairo_pdf_surface_t *surface = abstract_surface;
6536 cairo_pdf_smask_group_t *group;
6537 cairo_composite_rectangles_t extents;
6538 cairo_int_status_t status;
6539 cairo_rectangle_int_t r;
6542 status = _cairo_composite_rectangles_init_for_mask (&extents,
6544 op, source, mask, clip);
6545 if (unlikely (status))
6548 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
6549 cairo_status_t source_status, mask_status;
6551 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
6552 if (_cairo_int_status_is_error (status))
6554 source_status = status;
6556 if (mask->has_component_alpha) {
6557 status = CAIRO_INT_STATUS_UNSUPPORTED;
6559 status = _cairo_pdf_surface_analyze_operation (surface, op, mask, &extents.bounded);
6560 if (_cairo_int_status_is_error (status))
6563 mask_status = status;
6565 _cairo_composite_rectangles_fini (&extents);
6566 return _cairo_analysis_surface_merge_status (source_status,
6568 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
6569 status = _cairo_pdf_surface_start_fallback (surface);
6570 if (unlikely (status))
6574 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
6575 assert (_cairo_pdf_surface_operation_supported (surface, op, mask, &extents.bounded));
6577 /* get the accurate extents */
6578 status = _cairo_pattern_get_ink_extents (source, &r);
6579 if (unlikely (status))
6582 /* XXX slight impedance mismatch */
6583 _cairo_box_from_rectangle (&box, &r);
6584 status = _cairo_composite_rectangles_intersect_source_extents (&extents,
6586 if (unlikely (status))
6589 status = _cairo_pattern_get_ink_extents (mask, &r);
6590 if (unlikely (status))
6593 _cairo_box_from_rectangle (&box, &r);
6594 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
6596 if (unlikely (status))
6599 status = _cairo_pdf_surface_set_clip (surface, &extents);
6600 if (unlikely (status))
6603 status = _cairo_pdf_surface_select_operator (surface, op);
6604 if (unlikely (status))
6607 /* Check if we can use a stencil mask */
6608 status = _cairo_pdf_surface_emit_stencil_mask (surface, source, mask, &extents.bounded);
6609 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
6612 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
6613 if (unlikely (group == NULL)) {
6614 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
6618 group->operation = PDF_MASK;
6619 status = _cairo_pattern_create_copy (&group->source, source);
6620 if (unlikely (status)) {
6621 _cairo_pdf_smask_group_destroy (group);
6624 status = _cairo_pattern_create_copy (&group->mask, mask);
6625 if (unlikely (status)) {
6626 _cairo_pdf_smask_group_destroy (group);
6629 group->source_res = _cairo_pdf_surface_new_object (surface);
6630 if (group->source_res.id == 0) {
6631 _cairo_pdf_smask_group_destroy (group);
6632 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
6636 status = _cairo_pdf_surface_add_smask_group (surface, group);
6637 if (unlikely (status)) {
6638 _cairo_pdf_smask_group_destroy (group);
6642 status = _cairo_pdf_surface_add_smask (surface, group->group_res);
6643 if (unlikely (status))
6646 status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
6647 if (unlikely (status))
6650 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6651 if (unlikely (status))
6654 _cairo_output_stream_printf (surface->output,
6655 "q /s%d gs /x%d Do Q\n",
6656 group->group_res.id,
6657 group->source_res.id);
6659 _cairo_composite_rectangles_fini (&extents);
6660 return _cairo_output_stream_get_status (surface->output);
6663 _cairo_composite_rectangles_fini (&extents);
6667 static cairo_int_status_t
6668 _cairo_pdf_surface_stroke (void *abstract_surface,
6669 cairo_operator_t op,
6670 const cairo_pattern_t *source,
6671 const cairo_path_fixed_t *path,
6672 const cairo_stroke_style_t *style,
6673 const cairo_matrix_t *ctm,
6674 const cairo_matrix_t *ctm_inverse,
6676 cairo_antialias_t antialias,
6677 const cairo_clip_t *clip)
6679 cairo_pdf_surface_t *surface = abstract_surface;
6680 cairo_pdf_smask_group_t *group;
6681 cairo_pdf_resource_t pattern_res, gstate_res;
6682 cairo_composite_rectangles_t extents;
6683 cairo_int_status_t status;
6685 status = _cairo_composite_rectangles_init_for_stroke (&extents,
6690 if (unlikely (status))
6693 /* use the more accurate extents */
6694 if (extents.is_bounded) {
6695 cairo_rectangle_int_t mask;
6698 status = _cairo_path_fixed_stroke_extents (path, style,
6702 if (unlikely (status))
6705 _cairo_box_from_rectangle (&box, &mask);
6706 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
6708 if (unlikely (status))
6712 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
6713 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
6717 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
6719 status = _cairo_pdf_surface_set_clip (surface, &extents);
6720 if (unlikely (status))
6725 status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
6727 &pattern_res, &gstate_res);
6728 if (unlikely (status))
6731 status = _cairo_pdf_surface_select_operator (surface, op);
6732 if (unlikely (status))
6735 if (gstate_res.id != 0) {
6736 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
6737 if (unlikely (group == NULL)) {
6738 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
6742 group->operation = PDF_STROKE;
6743 status = _cairo_pattern_create_copy (&group->source, source);
6744 if (unlikely (status)) {
6745 _cairo_pdf_smask_group_destroy (group);
6748 group->source_res = pattern_res;
6749 status = _cairo_path_fixed_init_copy (&group->path, path);
6750 if (unlikely (status)) {
6751 _cairo_pdf_smask_group_destroy (group);
6755 group->style = *style;
6757 group->ctm_inverse = *ctm_inverse;
6758 status = _cairo_pdf_surface_add_smask_group (surface, group);
6759 if (unlikely (status)) {
6760 _cairo_pdf_smask_group_destroy (group);
6764 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
6765 if (unlikely (status))
6768 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
6769 if (unlikely (status))
6772 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6773 if (unlikely (status))
6776 _cairo_output_stream_printf (surface->output,
6777 "q /s%d gs /x%d Do Q\n",
6779 group->group_res.id);
6781 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
6782 if (unlikely (status))
6785 status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
6790 if (unlikely (status))
6793 status = _cairo_pdf_surface_unselect_pattern (surface);
6794 if (unlikely (status))
6798 _cairo_composite_rectangles_fini (&extents);
6799 return _cairo_output_stream_get_status (surface->output);
6802 _cairo_composite_rectangles_fini (&extents);
6806 static cairo_int_status_t
6807 _cairo_pdf_surface_fill (void *abstract_surface,
6808 cairo_operator_t op,
6809 const cairo_pattern_t *source,
6810 const cairo_path_fixed_t*path,
6811 cairo_fill_rule_t fill_rule,
6813 cairo_antialias_t antialias,
6814 const cairo_clip_t *clip)
6816 cairo_pdf_surface_t *surface = abstract_surface;
6817 cairo_int_status_t status;
6818 cairo_pdf_smask_group_t *group;
6819 cairo_pdf_resource_t pattern_res, gstate_res;
6820 cairo_composite_rectangles_t extents;
6822 status = _cairo_composite_rectangles_init_for_fill (&extents,
6826 if (unlikely (status))
6829 /* use the more accurate extents */
6830 if (extents.is_bounded) {
6831 cairo_rectangle_int_t mask;
6834 _cairo_path_fixed_fill_extents (path,
6839 _cairo_box_from_rectangle (&box, &mask);
6840 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
6842 if (unlikely (status))
6846 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
6847 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
6849 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
6850 status = _cairo_pdf_surface_start_fallback (surface);
6851 if (unlikely (status))
6855 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
6857 status = _cairo_pdf_surface_set_clip (surface, &extents);
6858 if (unlikely (status))
6861 status = _cairo_pdf_surface_select_operator (surface, op);
6862 if (unlikely (status))
6865 if (_can_paint_pattern (source)) {
6866 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6867 if (unlikely (status))
6870 _cairo_output_stream_printf (surface->output, "q\n");
6871 status = _cairo_pdf_operators_clip (&surface->pdf_operators,
6874 if (unlikely (status))
6877 status = _cairo_pdf_surface_paint_pattern (surface,
6881 if (unlikely (status))
6884 _cairo_output_stream_printf (surface->output, "Q\n");
6885 status = _cairo_output_stream_get_status (surface->output);
6891 status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
6893 &pattern_res, &gstate_res);
6894 if (unlikely (status))
6897 if (gstate_res.id != 0) {
6898 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
6899 if (unlikely (group == NULL)) {
6900 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
6904 group->operation = PDF_FILL;
6905 status = _cairo_pattern_create_copy (&group->source, source);
6906 if (unlikely (status)) {
6907 _cairo_pdf_smask_group_destroy (group);
6910 group->source_res = pattern_res;
6911 status = _cairo_path_fixed_init_copy (&group->path, path);
6912 if (unlikely (status)) {
6913 _cairo_pdf_smask_group_destroy (group);
6917 group->fill_rule = fill_rule;
6918 status = _cairo_pdf_surface_add_smask_group (surface, group);
6919 if (unlikely (status)) {
6920 _cairo_pdf_smask_group_destroy (group);
6924 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
6925 if (unlikely (status))
6928 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
6929 if (unlikely (status))
6932 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6933 if (unlikely (status))
6936 _cairo_output_stream_printf (surface->output,
6937 "q /s%d gs /x%d Do Q\n",
6939 group->group_res.id);
6941 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
6942 if (unlikely (status))
6945 status = _cairo_pdf_operators_fill (&surface->pdf_operators,
6948 if (unlikely (status))
6951 status = _cairo_pdf_surface_unselect_pattern (surface);
6952 if (unlikely (status))
6956 _cairo_composite_rectangles_fini (&extents);
6957 return _cairo_output_stream_get_status (surface->output);
6960 _cairo_composite_rectangles_fini (&extents);
6964 static cairo_int_status_t
6965 _cairo_pdf_surface_fill_stroke (void *abstract_surface,
6966 cairo_operator_t fill_op,
6967 const cairo_pattern_t *fill_source,
6968 cairo_fill_rule_t fill_rule,
6969 double fill_tolerance,
6970 cairo_antialias_t fill_antialias,
6971 const cairo_path_fixed_t*path,
6972 cairo_operator_t stroke_op,
6973 const cairo_pattern_t *stroke_source,
6974 const cairo_stroke_style_t *stroke_style,
6975 const cairo_matrix_t *stroke_ctm,
6976 const cairo_matrix_t *stroke_ctm_inverse,
6977 double stroke_tolerance,
6978 cairo_antialias_t stroke_antialias,
6979 const cairo_clip_t *clip)
6981 cairo_pdf_surface_t *surface = abstract_surface;
6982 cairo_int_status_t status;
6983 cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res;
6984 cairo_composite_rectangles_t extents;
6986 /* During analysis we return unsupported and let the _fill and
6987 * _stroke functions that are on the fallback path do the analysis
6988 * for us. During render we may still encounter unsupported
6989 * combinations of fill/stroke patterns. However we can return
6990 * unsupported anytime to let the _fill and _stroke functions take
6993 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
6994 return CAIRO_INT_STATUS_UNSUPPORTED;
6996 /* PDF rendering of fill-stroke is not the same as cairo when
6997 * either the fill or stroke is not opaque.
6999 if ( !_cairo_pattern_is_opaque (fill_source, NULL) ||
7000 !_cairo_pattern_is_opaque (stroke_source, NULL))
7002 return CAIRO_INT_STATUS_UNSUPPORTED;
7005 if (fill_op != stroke_op)
7006 return CAIRO_INT_STATUS_UNSUPPORTED;
7008 /* Compute the operation extents using the stroke which will naturally
7009 * be larger than the fill extents.
7011 status = _cairo_composite_rectangles_init_for_stroke (&extents,
7013 stroke_op, stroke_source,
7014 path, stroke_style, stroke_ctm,
7016 if (unlikely (status))
7019 /* use the more accurate extents */
7020 if (extents.is_bounded) {
7021 cairo_rectangle_int_t mask;
7024 status = _cairo_path_fixed_stroke_extents (path, stroke_style,
7025 stroke_ctm, stroke_ctm_inverse,
7028 if (unlikely (status))
7031 _cairo_box_from_rectangle (&box, &mask);
7032 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
7034 if (unlikely (status))
7038 status = _cairo_pdf_surface_set_clip (surface, &extents);
7039 if (unlikely (status))
7042 status = _cairo_pdf_surface_select_operator (surface, fill_op);
7043 if (unlikely (status))
7046 /* use the more accurate extents */
7047 if (extents.is_bounded) {
7048 cairo_rectangle_int_t mask;
7051 _cairo_path_fixed_fill_extents (path,
7056 _cairo_box_from_rectangle (&box, &mask);
7057 status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
7059 if (unlikely (status))
7063 fill_pattern_res.id = 0;
7065 status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
7069 if (unlikely (status))
7072 assert (gstate_res.id == 0);
7074 stroke_pattern_res.id = 0;
7076 status = _cairo_pdf_surface_add_pdf_pattern (surface,
7079 &stroke_pattern_res,
7081 if (unlikely (status))
7084 assert (gstate_res.id == 0);
7086 /* As PDF has separate graphics state for fill and stroke we can
7087 * select both at the same time */
7088 status = _cairo_pdf_surface_select_pattern (surface, fill_source,
7089 fill_pattern_res, FALSE);
7090 if (unlikely (status))
7093 status = _cairo_pdf_surface_select_pattern (surface, stroke_source,
7094 stroke_pattern_res, TRUE);
7095 if (unlikely (status))
7098 status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators,
7103 stroke_ctm_inverse);
7104 if (unlikely (status))
7107 status = _cairo_pdf_surface_unselect_pattern (surface);
7108 if (unlikely (status))
7111 _cairo_composite_rectangles_fini (&extents);
7112 return _cairo_output_stream_get_status (surface->output);
7115 _cairo_composite_rectangles_fini (&extents);
7120 _cairo_pdf_surface_has_show_text_glyphs (void *abstract_surface)
7125 static cairo_int_status_t
7126 _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
7127 cairo_operator_t op,
7128 const cairo_pattern_t *source,
7131 cairo_glyph_t *glyphs,
7133 const cairo_text_cluster_t *clusters,
7135 cairo_text_cluster_flags_t cluster_flags,
7136 cairo_scaled_font_t *scaled_font,
7137 const cairo_clip_t *clip)
7139 cairo_pdf_surface_t *surface = abstract_surface;
7140 cairo_pdf_smask_group_t *group;
7141 cairo_pdf_resource_t pattern_res, gstate_res;
7142 cairo_composite_rectangles_t extents;
7143 cairo_bool_t overlap;
7144 cairo_int_status_t status;
7146 status = _cairo_composite_rectangles_init_for_glyphs (&extents,
7153 if (unlikely (status))
7156 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
7157 status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
7161 assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
7163 status = _cairo_pdf_surface_set_clip (surface, &extents);
7164 if (unlikely (status))
7169 status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
7171 &pattern_res, &gstate_res);
7172 if (unlikely (status))
7175 status = _cairo_pdf_surface_select_operator (surface, op);
7176 if (unlikely (status))
7179 if (gstate_res.id != 0) {
7180 group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
7181 if (unlikely (group == NULL)) {
7182 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7186 group->operation = PDF_SHOW_GLYPHS;
7187 status = _cairo_pattern_create_copy (&group->source, source);
7188 if (unlikely (status)) {
7189 _cairo_pdf_smask_group_destroy (group);
7192 group->source_res = pattern_res;
7195 group->utf8 = malloc (utf8_len);
7196 if (unlikely (group->utf8 == NULL)) {
7197 _cairo_pdf_smask_group_destroy (group);
7198 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7201 memcpy (group->utf8, utf8, utf8_len);
7203 group->utf8_len = utf8_len;
7206 group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
7207 if (unlikely (group->glyphs == NULL)) {
7208 _cairo_pdf_smask_group_destroy (group);
7209 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7212 memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
7214 group->num_glyphs = num_glyphs;
7217 group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
7218 if (unlikely (group->clusters == NULL)) {
7219 _cairo_pdf_smask_group_destroy (group);
7220 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
7223 memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
7225 group->num_clusters = num_clusters;
7227 group->scaled_font = cairo_scaled_font_reference (scaled_font);
7228 status = _cairo_pdf_surface_add_smask_group (surface, group);
7229 if (unlikely (status)) {
7230 _cairo_pdf_smask_group_destroy (group);
7234 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
7235 if (unlikely (status))
7238 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
7239 if (unlikely (status))
7242 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7243 if (unlikely (status))
7246 _cairo_output_stream_printf (surface->output,
7247 "q /s%d gs /x%d Do Q\n",
7249 group->group_res.id);
7251 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
7252 if (unlikely (status))
7255 /* Each call to show_glyphs() with a transclucent pattern must
7256 * be in a separate text object otherwise overlapping text
7257 * from separate calls to show_glyphs will not composite with
7259 if (! _cairo_pattern_is_opaque (source, &extents.bounded)) {
7260 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7261 if (unlikely (status))
7265 status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
7268 clusters, num_clusters,
7271 if (unlikely (status))
7274 status = _cairo_pdf_surface_unselect_pattern (surface);
7275 if (unlikely (status))
7279 _cairo_composite_rectangles_fini (&extents);
7280 return _cairo_output_stream_get_status (surface->output);
7283 _cairo_composite_rectangles_fini (&extents);
7287 static const char **
7288 _cairo_pdf_surface_get_supported_mime_types (void *abstract_surface)
7290 return _cairo_pdf_supported_mime_types;
7294 _cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
7295 cairo_paginated_mode_t paginated_mode)
7297 cairo_pdf_surface_t *surface = abstract_surface;
7299 surface->paginated_mode = paginated_mode;
7302 static const cairo_surface_backend_t cairo_pdf_surface_backend = {
7303 CAIRO_SURFACE_TYPE_PDF,
7304 _cairo_pdf_surface_finish,
7306 _cairo_default_context_create,
7308 NULL, /* create similar: handled by wrapper */
7309 NULL, /* create similar image */
7310 NULL, /* map to image */
7311 NULL, /* unmap image */
7313 _cairo_surface_default_source,
7314 NULL, /* acquire_source_image */
7315 NULL, /* release_source_image */
7316 NULL, /* snapshot */
7318 NULL, /* _cairo_pdf_surface_copy_page */
7319 _cairo_pdf_surface_show_page,
7321 _cairo_pdf_surface_get_extents,
7322 _cairo_pdf_surface_get_font_options,
7325 NULL, /* mark_dirty_rectangle */
7327 /* Here are the drawing functions */
7328 _cairo_pdf_surface_paint,
7329 _cairo_pdf_surface_mask,
7330 _cairo_pdf_surface_stroke,
7331 _cairo_pdf_surface_fill,
7332 _cairo_pdf_surface_fill_stroke,
7333 NULL, /* show_glyphs */
7334 _cairo_pdf_surface_has_show_text_glyphs,
7335 _cairo_pdf_surface_show_text_glyphs,
7336 _cairo_pdf_surface_get_supported_mime_types,
7339 static const cairo_paginated_surface_backend_t
7340 cairo_pdf_surface_paginated_backend = {
7341 _cairo_pdf_surface_start_page,
7342 _cairo_pdf_surface_set_paginated_mode,
7343 NULL, /* set_bounding_box */
7344 _cairo_pdf_surface_has_fallback_images,
7345 _cairo_pdf_surface_supports_fine_grained_fallbacks,