Changes.
[cairo/gpu.git] / src / cairo-pdf-surface.c
blob88b17440e2ed51733196cd2a07d3af9ea433f265
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
34 * California.
36 * Contributor(s):
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() */
43 #include "cairoint.h"
44 #include "cairo-pdf.h"
45 #include "cairo-pdf-surface-private.h"
46 #include "cairo-pdf-operators-private.h"
47 #include "cairo-analysis-surface-private.h"
48 #include "cairo-image-info-private.h"
49 #include "cairo-meta-surface-private.h"
50 #include "cairo-output-stream-private.h"
51 #include "cairo-paginated-private.h"
52 #include "cairo-scaled-font-subsets-private.h"
53 #include "cairo-type3-glyph-surface-private.h"
55 #include <time.h>
56 #include <zlib.h>
58 /* Issues:
60 * - We embed an image in the stream each time it's composited. We
61 * could add generation counters to surfaces and remember the stream
62 * ID for a particular generation for a particular surface.
64 * - Backend specific meta data.
68 * Page Structure of the Generated PDF:
70 * Each page requiring fallbacks images contains a knockout group at
71 * the top level. The first operation of the knockout group paints a
72 * group containing all the supported drawing operations. Fallback
73 * images (if any) are painted in the knockout group. This ensures
74 * that fallback images do not composite with any content under the
75 * fallback images.
77 * Streams:
79 * This PDF surface has three types of streams:
80 * - PDF Stream
81 * - Content Stream
82 * - Group Stream
84 * Calling _cairo_output_stream_printf (surface->output, ...) will
85 * write to the currently open stream.
87 * PDF Stream:
88 * A PDF Stream may be opened and closed with the following functions:
89 * _cairo_pdf_surface_open stream ()
90 * _cairo_pdf_surface_close_stream ()
92 * PDF Streams are written directly to the PDF file. They are used for
93 * fonts, images and patterns.
95 * Content Stream:
96 * The Content Stream is opened and closed with the following functions:
97 * _cairo_pdf_surface_open_content_stream ()
98 * _cairo_pdf_surface_close_content_stream ()
100 * The Content Stream contains the text and graphics operators.
102 * Group Stream:
103 * A Group Stream may be opened and closed with the following functions:
104 * _cairo_pdf_surface_open_group ()
105 * _cairo_pdf_surface_close_group ()
107 * A Group Stream is a Form XObject. It is used for short sequences
108 * of operators. As the content is very short the group is stored in
109 * memory until it is closed. This allows some optimization such as
110 * including the Resource dictionary and stream length inside the
111 * XObject instead of using an indirect object.
114 static const cairo_pdf_version_t _cairo_pdf_versions[] =
116 CAIRO_PDF_VERSION_1_4,
117 CAIRO_PDF_VERSION_1_5
120 #define CAIRO_PDF_VERSION_LAST ARRAY_LENGTH (_cairo_pdf_versions)
122 static const char * _cairo_pdf_version_strings[CAIRO_PDF_VERSION_LAST] =
124 "PDF 1.4",
125 "PDF 1.5"
128 typedef struct _cairo_pdf_object {
129 long offset;
130 } cairo_pdf_object_t;
132 typedef struct _cairo_pdf_font {
133 unsigned int font_id;
134 unsigned int subset_id;
135 cairo_pdf_resource_t subset_resource;
136 } cairo_pdf_font_t;
138 typedef struct _cairo_pdf_rgb_linear_function {
139 cairo_pdf_resource_t resource;
140 double color1[3];
141 double color2[3];
142 } cairo_pdf_rgb_linear_function_t;
144 typedef struct _cairo_pdf_alpha_linear_function {
145 cairo_pdf_resource_t resource;
146 double alpha1;
147 double alpha2;
148 } cairo_pdf_alpha_linear_function_t;
150 static cairo_pdf_resource_t
151 _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
153 static void
154 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
156 static void
157 _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
159 static cairo_status_t
160 _cairo_pdf_surface_add_font (unsigned int font_id,
161 unsigned int subset_id,
162 void *closure);
164 static void
165 _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
167 static cairo_status_t
168 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
169 cairo_pdf_resource_t *resource,
170 cairo_bool_t compressed,
171 const char *fmt,
172 ...) CAIRO_PRINTF_FORMAT(4, 5);
173 static cairo_status_t
174 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface);
176 static cairo_status_t
177 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
179 static void
180 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
182 static cairo_pdf_resource_t
183 _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface);
185 static cairo_pdf_resource_t
186 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface);
188 static long
189 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
191 static cairo_status_t
192 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
194 static cairo_status_t
195 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
197 static cairo_bool_t
198 _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b);
200 static const cairo_surface_backend_t cairo_pdf_surface_backend;
201 static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
203 static cairo_pdf_resource_t
204 _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
206 cairo_pdf_resource_t resource;
207 cairo_status_t status;
208 cairo_pdf_object_t object;
210 object.offset = _cairo_output_stream_get_position (surface->output);
212 status = _cairo_array_append (&surface->objects, &object);
213 if (unlikely (status)) {
214 resource.id = 0;
215 return resource;
218 resource = surface->next_available_resource;
219 surface->next_available_resource.id++;
221 return resource;
224 static void
225 _cairo_pdf_surface_update_object (cairo_pdf_surface_t *surface,
226 cairo_pdf_resource_t resource)
228 cairo_pdf_object_t *object;
230 object = _cairo_array_index (&surface->objects, resource.id - 1);
231 object->offset = _cairo_output_stream_get_position (surface->output);
234 static void
235 _cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
236 double width,
237 double height)
239 surface->width = width;
240 surface->height = height;
241 cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
242 _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
243 &surface->cairo_to_pdf);
246 static cairo_surface_t *
247 _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
248 double width,
249 double height)
251 cairo_pdf_surface_t *surface;
252 cairo_status_t status, status_ignored;
254 surface = malloc (sizeof (cairo_pdf_surface_t));
255 if (unlikely (surface == NULL)) {
256 /* destroy stream on behalf of caller */
257 status = _cairo_output_stream_destroy (output);
258 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
261 _cairo_surface_init (&surface->base, &cairo_pdf_surface_backend,
262 CAIRO_CONTENT_COLOR_ALPHA);
264 surface->output = output;
265 surface->width = width;
266 surface->height = height;
267 cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
269 _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
270 _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
271 _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
272 _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
273 _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
274 _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
275 _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t));
277 _cairo_array_init (&surface->page_patterns, sizeof (cairo_pdf_pattern_t));
278 _cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t));
279 surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal);
280 if (unlikely (surface->all_surfaces == NULL)) {
281 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
282 goto BAIL0;
285 _cairo_pdf_group_resources_init (&surface->resources);
287 surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
288 if (! surface->font_subsets) {
289 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
290 goto BAIL1;
293 surface->next_available_resource.id = 1;
294 surface->pages_resource = _cairo_pdf_surface_new_object (surface);
295 if (surface->pages_resource.id == 0) {
296 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
297 goto BAIL2;
300 surface->pdf_version = CAIRO_PDF_VERSION_1_5;
301 surface->compress_content = TRUE;
302 surface->pdf_stream.active = FALSE;
303 surface->pdf_stream.old_output = NULL;
304 surface->group_stream.active = FALSE;
305 surface->group_stream.stream = NULL;
306 surface->group_stream.mem_stream = NULL;
308 surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
310 surface->force_fallbacks = FALSE;
311 surface->select_pattern_gstate_saved = FALSE;
312 surface->current_pattern_is_solid_color = FALSE;
313 surface->header_emitted = FALSE;
315 _cairo_pdf_operators_init (&surface->pdf_operators,
316 surface->output,
317 &surface->cairo_to_pdf,
318 surface->font_subsets);
319 _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
320 _cairo_pdf_surface_add_font,
321 surface);
322 _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators, TRUE);
324 surface->paginated_surface = _cairo_paginated_surface_create (
325 &surface->base,
326 CAIRO_CONTENT_COLOR_ALPHA,
327 width, height,
328 &cairo_pdf_surface_paginated_backend);
330 status = surface->paginated_surface->status;
331 if (status == CAIRO_STATUS_SUCCESS) {
332 /* paginated keeps the only reference to surface now, drop ours */
333 cairo_surface_destroy (&surface->base);
334 return surface->paginated_surface;
337 BAIL2:
338 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
339 BAIL1:
340 _cairo_hash_table_destroy (surface->all_surfaces);
341 BAIL0:
342 _cairo_array_fini (&surface->objects);
343 free (surface);
345 /* destroy stream on behalf of caller */
346 status_ignored = _cairo_output_stream_destroy (output);
348 return _cairo_surface_create_in_error (status);
352 * cairo_pdf_surface_create_for_stream:
353 * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
354 * to indicate a no-op @write_func. With a no-op @write_func,
355 * the surface may be queried or used as a source without
356 * generating any temporary files.
357 * @closure: the closure argument for @write_func
358 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
359 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
361 * Creates a PDF surface of the specified size in points to be written
362 * incrementally to the stream represented by @write_func and @closure.
364 * Return value: a pointer to the newly created surface. The caller
365 * owns the surface and should call cairo_surface_destroy() when done
366 * with it.
368 * This function always returns a valid pointer, but it will return a
369 * pointer to a "nil" surface if an error such as out of memory
370 * occurs. You can use cairo_surface_status() to check for this.
372 * Since: 1.2
374 cairo_surface_t *
375 cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func,
376 void *closure,
377 double width_in_points,
378 double height_in_points)
380 cairo_output_stream_t *output;
382 output = _cairo_output_stream_create (write_func, NULL, closure);
383 if (_cairo_output_stream_get_status (output))
384 return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
386 return _cairo_pdf_surface_create_for_stream_internal (output,
387 width_in_points,
388 height_in_points);
392 * cairo_pdf_surface_create:
393 * @filename: a filename for the PDF output (must be writable), %NULL may be
394 * used to specify no output. This will generate a PDF surface that
395 * may be queried and used as a source, without generating a
396 * temporary file.
397 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
398 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
400 * Creates a PDF surface of the specified size in points to be written
401 * to @filename.
403 * Return value: a pointer to the newly created surface. The caller
404 * owns the surface and should call cairo_surface_destroy() when done
405 * with it.
407 * This function always returns a valid pointer, but it will return a
408 * pointer to a "nil" surface if an error such as out of memory
409 * occurs. You can use cairo_surface_status() to check for this.
411 * Since: 1.2
413 cairo_surface_t *
414 cairo_pdf_surface_create (const char *filename,
415 double width_in_points,
416 double height_in_points)
418 cairo_output_stream_t *output;
420 output = _cairo_output_stream_create_for_filename (filename);
421 if (_cairo_output_stream_get_status (output))
422 return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
424 return _cairo_pdf_surface_create_for_stream_internal (output,
425 width_in_points,
426 height_in_points);
429 static cairo_bool_t
430 _cairo_surface_is_pdf (cairo_surface_t *surface)
432 return surface->backend == &cairo_pdf_surface_backend;
435 /* If the abstract_surface is a paginated surface, and that paginated
436 * surface's target is a pdf_surface, then set pdf_surface to that
437 * target. Otherwise return %CAIRO_STATUS_SURFACE_TYPE_MISMATCH.
439 static cairo_status_t
440 _extract_pdf_surface (cairo_surface_t *surface,
441 cairo_pdf_surface_t **pdf_surface)
443 cairo_surface_t *target;
445 if (surface->status)
446 return surface->status;
448 if (! _cairo_surface_is_paginated (surface))
449 return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
451 target = _cairo_paginated_surface_get_target (surface);
452 if (target->status)
453 return target->status;
455 if (! _cairo_surface_is_pdf (target))
456 return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
458 *pdf_surface = (cairo_pdf_surface_t *) target;
460 return CAIRO_STATUS_SUCCESS;
464 * cairo_pdf_surface_restrict_to_version:
465 * @surface: a PDF #cairo_surface_t
466 * @version: PDF version
468 * Restricts the generated PDF file to @version. See cairo_pdf_get_versions()
469 * for a list of available version values that can be used here.
471 * This function should only be called before any drawing operations
472 * have been performed on the given surface. The simplest way to do
473 * this is to call this function immediately after creating the
474 * surface.
476 * Since: 1.10
478 void
479 cairo_pdf_surface_restrict_to_version (cairo_surface_t *abstract_surface,
480 cairo_pdf_version_t version)
482 cairo_pdf_surface_t *surface = NULL; /* hide compiler warning */
483 cairo_status_t status;
485 status = _extract_pdf_surface (abstract_surface, &surface);
486 if (status) {
487 status = _cairo_surface_set_error (abstract_surface, status);
488 return;
491 if (version < CAIRO_PDF_VERSION_LAST)
492 surface->pdf_version = version;
494 _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators,
495 version >= CAIRO_PDF_VERSION_1_5);
499 * cairo_pdf_get_versions:
500 * @versions: supported version list
501 * @num_versions: list length
503 * Used to retrieve the list of supported versions. See
504 * cairo_pdf_surface_restrict_to_version().
506 * Since: 1.10
508 void
509 cairo_pdf_get_versions (cairo_pdf_version_t const **versions,
510 int *num_versions)
512 if (versions != NULL)
513 *versions = _cairo_pdf_versions;
515 if (num_versions != NULL)
516 *num_versions = CAIRO_PDF_VERSION_LAST;
520 * cairo_pdf_version_to_string:
521 * @version: a version id
523 * Get the string representation of the given @version id. This function
524 * will return %NULL if @version isn't valid. See cairo_pdf_get_versions()
525 * for a way to get the list of valid version ids.
527 * Return value: the string associated to given version.
529 * Since: 1.10
531 const char *
532 cairo_pdf_version_to_string (cairo_pdf_version_t version)
534 if (version >= CAIRO_PDF_VERSION_LAST)
535 return NULL;
537 return _cairo_pdf_version_strings[version];
541 * cairo_pdf_surface_set_size:
542 * @surface: a PDF #cairo_surface_t
543 * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
544 * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
546 * Changes the size of a PDF surface for the current (and
547 * subsequent) pages.
549 * This function should only be called before any drawing operations
550 * have been performed on the current page. The simplest way to do
551 * this is to call this function immediately after creating the
552 * surface or immediately after completing a page with either
553 * cairo_show_page() or cairo_copy_page().
555 * Since: 1.2
557 void
558 cairo_pdf_surface_set_size (cairo_surface_t *surface,
559 double width_in_points,
560 double height_in_points)
562 cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
563 cairo_status_t status;
565 status = _extract_pdf_surface (surface, &pdf_surface);
566 if (unlikely (status)) {
567 status = _cairo_surface_set_error (surface, status);
568 return;
571 _cairo_pdf_surface_set_size_internal (pdf_surface,
572 width_in_points,
573 height_in_points);
574 status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
575 width_in_points,
576 height_in_points);
577 if (unlikely (status))
578 status = _cairo_surface_set_error (surface, status);
581 static void
582 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
584 int i, size;
585 cairo_pdf_pattern_t *pattern;
586 cairo_pdf_source_surface_t *src_surface;
587 cairo_pdf_smask_group_t *group;
589 size = _cairo_array_num_elements (&surface->page_patterns);
590 for (i = 0; i < size; i++) {
591 pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->page_patterns, i);
592 cairo_pattern_destroy (pattern->pattern);
594 _cairo_array_truncate (&surface->page_patterns, 0);
596 size = _cairo_array_num_elements (&surface->page_surfaces);
597 for (i = 0; i < size; i++) {
598 src_surface = (cairo_pdf_source_surface_t *) _cairo_array_index (&surface->page_surfaces, i);
599 cairo_surface_destroy (src_surface->surface);
601 _cairo_array_truncate (&surface->page_surfaces, 0);
603 size = _cairo_array_num_elements (&surface->smask_groups);
604 for (i = 0; i < size; i++) {
605 _cairo_array_copy_element (&surface->smask_groups, i, &group);
606 _cairo_pdf_smask_group_destroy (group);
608 _cairo_array_truncate (&surface->smask_groups, 0);
609 _cairo_array_truncate (&surface->knockout_group, 0);
612 static void
613 _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
615 _cairo_array_init (&res->alphas, sizeof (double));
616 _cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t));
617 _cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t));
618 _cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t));
619 _cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t));
622 static void
623 _cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
625 _cairo_array_fini (&res->alphas);
626 _cairo_array_fini (&res->smasks);
627 _cairo_array_fini (&res->patterns);
628 _cairo_array_fini (&res->xobjects);
629 _cairo_array_fini (&res->fonts);
632 static void
633 _cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
635 _cairo_array_truncate (&res->alphas, 0);
636 _cairo_array_truncate (&res->smasks, 0);
637 _cairo_array_truncate (&res->patterns, 0);
638 _cairo_array_truncate (&res->xobjects, 0);
639 _cairo_array_truncate (&res->fonts, 0);
642 static cairo_status_t
643 _cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
644 double alpha,
645 int *index)
647 int num_alphas, i;
648 double other;
649 cairo_status_t status;
650 cairo_pdf_group_resources_t *res = &surface->resources;
652 num_alphas = _cairo_array_num_elements (&res->alphas);
653 for (i = 0; i < num_alphas; i++) {
654 _cairo_array_copy_element (&res->alphas, i, &other);
655 if (alpha == other) {
656 *index = i;
657 return CAIRO_STATUS_SUCCESS;
661 status = _cairo_array_append (&res->alphas, &alpha);
662 if (unlikely (status))
663 return status;
665 *index = _cairo_array_num_elements (&res->alphas) - 1;
667 return CAIRO_STATUS_SUCCESS;
670 static cairo_status_t
671 _cairo_pdf_surface_add_smask (cairo_pdf_surface_t *surface,
672 cairo_pdf_resource_t smask)
674 return _cairo_array_append (&(surface->resources.smasks), &smask);
677 static cairo_status_t
678 _cairo_pdf_surface_add_pattern (cairo_pdf_surface_t *surface,
679 cairo_pdf_resource_t pattern)
681 return _cairo_array_append (&(surface->resources.patterns), &pattern);
684 static cairo_status_t
685 _cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface,
686 cairo_pdf_resource_t xobject)
688 return _cairo_array_append (&(surface->resources.xobjects), &xobject);
691 static cairo_status_t
692 _cairo_pdf_surface_add_font (unsigned int font_id,
693 unsigned int subset_id,
694 void *closure)
696 cairo_pdf_surface_t *surface = closure;
697 cairo_pdf_font_t font;
698 int num_fonts, i;
699 cairo_status_t status;
700 cairo_pdf_group_resources_t *res = &surface->resources;
702 num_fonts = _cairo_array_num_elements (&res->fonts);
703 for (i = 0; i < num_fonts; i++) {
704 _cairo_array_copy_element (&res->fonts, i, &font);
705 if (font.font_id == font_id &&
706 font.subset_id == subset_id)
707 return CAIRO_STATUS_SUCCESS;
710 num_fonts = _cairo_array_num_elements (&surface->fonts);
711 for (i = 0; i < num_fonts; i++) {
712 _cairo_array_copy_element (&surface->fonts, i, &font);
713 if (font.font_id == font_id &&
714 font.subset_id == subset_id)
715 return _cairo_array_append (&res->fonts, &font);
718 font.font_id = font_id;
719 font.subset_id = subset_id;
720 font.subset_resource = _cairo_pdf_surface_new_object (surface);
721 if (font.subset_resource.id == 0)
722 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
724 status = _cairo_array_append (&surface->fonts, &font);
725 if (unlikely (status))
726 return status;
728 return _cairo_array_append (&res->fonts, &font);
731 static cairo_pdf_resource_t
732 _cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface,
733 unsigned int font_id,
734 unsigned int subset_id)
736 cairo_pdf_font_t font;
737 int num_fonts, i;
739 num_fonts = _cairo_array_num_elements (&surface->fonts);
740 for (i = 0; i < num_fonts; i++) {
741 _cairo_array_copy_element (&surface->fonts, i, &font);
742 if (font.font_id == font_id && font.subset_id == subset_id)
743 return font.subset_resource;
746 font.subset_resource.id = 0;
747 return font.subset_resource;
750 static void
751 _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface,
752 cairo_pdf_group_resources_t *res)
754 int num_alphas, num_smasks, num_resources, i;
755 double alpha;
756 cairo_pdf_resource_t *smask, *pattern, *xobject;
757 cairo_pdf_font_t *font;
759 _cairo_output_stream_printf (surface->output, "<<\n");
761 num_alphas = _cairo_array_num_elements (&res->alphas);
762 num_smasks = _cairo_array_num_elements (&res->smasks);
763 if (num_alphas > 0 || num_smasks > 0) {
764 _cairo_output_stream_printf (surface->output,
765 " /ExtGState <<\n");
767 for (i = 0; i < num_alphas; i++) {
768 _cairo_array_copy_element (&res->alphas, i, &alpha);
769 _cairo_output_stream_printf (surface->output,
770 " /a%d << /CA %f /ca %f >>\n",
771 i, alpha, alpha);
774 for (i = 0; i < num_smasks; i++) {
775 smask = _cairo_array_index (&res->smasks, i);
776 _cairo_output_stream_printf (surface->output,
777 " /s%d %d 0 R\n",
778 smask->id, smask->id);
781 _cairo_output_stream_printf (surface->output,
782 " >>\n");
785 num_resources = _cairo_array_num_elements (&res->patterns);
786 if (num_resources > 0) {
787 _cairo_output_stream_printf (surface->output,
788 " /Pattern <<");
789 for (i = 0; i < num_resources; i++) {
790 pattern = _cairo_array_index (&res->patterns, i);
791 _cairo_output_stream_printf (surface->output,
792 " /p%d %d 0 R",
793 pattern->id, pattern->id);
796 _cairo_output_stream_printf (surface->output,
797 " >>\n");
800 num_resources = _cairo_array_num_elements (&res->xobjects);
801 if (num_resources > 0) {
802 _cairo_output_stream_printf (surface->output,
803 " /XObject <<");
805 for (i = 0; i < num_resources; i++) {
806 xobject = _cairo_array_index (&res->xobjects, i);
807 _cairo_output_stream_printf (surface->output,
808 " /x%d %d 0 R",
809 xobject->id, xobject->id);
812 _cairo_output_stream_printf (surface->output,
813 " >>\n");
816 num_resources = _cairo_array_num_elements (&res->fonts);
817 if (num_resources > 0) {
818 _cairo_output_stream_printf (surface->output," /Font <<\n");
819 for (i = 0; i < num_resources; i++) {
820 font = _cairo_array_index (&res->fonts, i);
821 _cairo_output_stream_printf (surface->output,
822 " /f-%d-%d %d 0 R\n",
823 font->font_id,
824 font->subset_id,
825 font->subset_resource.id);
827 _cairo_output_stream_printf (surface->output, " >>\n");
830 _cairo_output_stream_printf (surface->output,
831 ">>\n");
834 static cairo_pdf_smask_group_t *
835 _cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t *surface)
837 cairo_pdf_smask_group_t *group;
839 group = calloc (1, sizeof (cairo_pdf_smask_group_t));
840 if (unlikely (group == NULL)) {
841 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
842 return NULL;
845 group->group_res = _cairo_pdf_surface_new_object (surface);
846 if (group->group_res.id == 0) {
847 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
848 free (group);
849 return NULL;
851 group->width = surface->width;
852 group->height = surface->height;
854 return group;
857 static void
858 _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
860 if (group->operation == PDF_FILL || group->operation == PDF_STROKE)
861 _cairo_path_fixed_fini (&group->path);
862 if (group->source)
863 cairo_pattern_destroy (group->source);
864 if (group->mask)
865 cairo_pattern_destroy (group->mask);
866 if (group->utf8)
867 free (group->utf8);
868 if (group->glyphs)
869 free (group->glyphs);
870 if (group->clusters)
871 free (group->clusters);
872 if (group->scaled_font)
873 cairo_scaled_font_destroy (group->scaled_font);
874 free (group);
877 static cairo_status_t
878 _cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t *surface,
879 cairo_pdf_smask_group_t *group)
881 return _cairo_array_append (&surface->smask_groups, &group);
884 static cairo_bool_t
885 _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b)
887 const cairo_pdf_source_surface_entry_t *a = key_a;
888 const cairo_pdf_source_surface_entry_t *b = key_b;
890 return (a->id == b->id) && (a->interpolate == b->interpolate);
893 static void
894 _cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key)
896 key->base.hash = key->id;
899 static cairo_int_status_t
900 _get_jpx_image_info (cairo_surface_t *source,
901 cairo_image_info_t *info,
902 const unsigned char **mime_data,
903 unsigned int *mime_data_length)
905 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
906 mime_data, mime_data_length);
907 if (*mime_data == NULL)
908 return CAIRO_INT_STATUS_UNSUPPORTED;
910 return _cairo_image_info_get_jpx_info (info, *mime_data, *mime_data_length);
913 static cairo_int_status_t
914 _get_jpeg_image_info (cairo_surface_t *source,
915 cairo_image_info_t *info,
916 const unsigned char **mime_data,
917 unsigned int *mime_data_length)
919 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
920 mime_data, mime_data_length);
921 if (*mime_data == NULL)
922 return CAIRO_INT_STATUS_UNSUPPORTED;
924 return _cairo_image_info_get_jpeg_info (info, *mime_data, *mime_data_length);
927 static cairo_status_t
928 _get_source_surface_size (cairo_surface_t *source,
929 int *width,
930 int *height)
932 cairo_image_surface_t *image;
933 void *image_extra;
934 cairo_status_t status;
935 cairo_image_info_t info;
936 const unsigned char *mime_data;
937 unsigned int mime_data_length;
939 if (_cairo_surface_is_meta (source)) {
940 cairo_rectangle_int_t extents;
942 status = _cairo_surface_get_extents (source, &extents);
943 if (unlikely (status))
944 return status;
946 *width = extents.width;
947 *height = extents.height;
949 return status;
952 status = _get_jpx_image_info (source, &info, &mime_data, &mime_data_length);
953 if (status == CAIRO_STATUS_SUCCESS) {
954 *width = info.width;
955 *height = info.height;
956 } else if (_cairo_status_is_error (status)) {
957 return status;
960 status = _get_jpeg_image_info (source, &info, &mime_data, &mime_data_length);
961 if (status == CAIRO_STATUS_SUCCESS) {
962 *width = info.width;
963 *height = info.height;
964 } else if (_cairo_status_is_error (status)) {
965 return status;
968 status = _cairo_surface_acquire_source_image (source, &image, &image_extra);
969 if (unlikely (status))
970 return status;
972 *width = image->width;
973 *height = image->height;
975 _cairo_surface_release_source_image (source, image, image_extra);
977 return status;
980 static cairo_status_t
981 _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
982 cairo_surface_t *source,
983 cairo_filter_t filter,
984 cairo_pdf_resource_t *surface_res,
985 int *width,
986 int *height)
988 cairo_pdf_source_surface_t src_surface;
989 cairo_pdf_source_surface_entry_t surface_key;
990 cairo_pdf_source_surface_entry_t *surface_entry;
991 cairo_status_t status;
992 cairo_bool_t interpolate;
994 switch (filter) {
995 case CAIRO_FILTER_GOOD:
996 case CAIRO_FILTER_BEST:
997 case CAIRO_FILTER_BILINEAR:
998 interpolate = TRUE;
999 break;
1000 case CAIRO_FILTER_FAST:
1001 case CAIRO_FILTER_NEAREST:
1002 case CAIRO_FILTER_GAUSSIAN:
1003 interpolate = FALSE;
1004 break;
1007 surface_key.id = source->unique_id;
1008 surface_key.interpolate = interpolate;
1009 _cairo_pdf_source_surface_init_key (&surface_key);
1010 surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base);
1011 if (surface_entry) {
1012 *surface_res = surface_entry->surface_res;
1013 *width = surface_entry->width;
1014 *height = surface_entry->height;
1016 return CAIRO_STATUS_SUCCESS;
1019 surface_entry = malloc (sizeof (cairo_pdf_source_surface_entry_t));
1020 if (surface_entry == NULL)
1021 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1023 surface_entry->id = surface_key.id;
1024 surface_entry->interpolate = interpolate;
1025 _cairo_pdf_source_surface_init_key (surface_entry);
1027 src_surface.hash_entry = surface_entry;
1028 src_surface.surface = cairo_surface_reference (source);
1029 surface_entry->surface_res = _cairo_pdf_surface_new_object (surface);
1030 if (surface_entry->surface_res.id == 0) {
1031 free (surface_entry);
1032 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1035 status = _get_source_surface_size (source, &surface_entry->width,
1036 &surface_entry->height);
1038 status = _cairo_array_append (&surface->page_surfaces, &src_surface);
1039 if (unlikely (status)) {
1040 free (surface_entry);
1041 return status;
1044 status = _cairo_hash_table_insert (surface->all_surfaces,
1045 &surface_entry->base);
1047 *surface_res = surface_entry->surface_res;
1048 *width = surface_entry->width;
1049 *height = surface_entry->height;
1051 return status;
1054 static cairo_status_t
1055 _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
1056 const cairo_pattern_t *pattern,
1057 cairo_rectangle_int_t *extents,
1058 cairo_pdf_resource_t *pattern_res,
1059 cairo_pdf_resource_t *gstate_res)
1061 cairo_pdf_pattern_t pdf_pattern;
1062 cairo_status_t status;
1064 /* Solid colors are emitted into the content stream */
1065 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
1066 pattern_res->id = 0;
1067 gstate_res->id = 0;
1068 return CAIRO_STATUS_SUCCESS;
1071 if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
1072 pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
1074 cairo_gradient_pattern_t *gradient;
1076 gradient = (cairo_gradient_pattern_t *) pattern;
1078 /* Gradients with zero stops do not produce any output */
1079 if (gradient->n_stops == 0)
1080 return CAIRO_INT_STATUS_NOTHING_TO_DO;
1082 /* Gradients with one stop are the same as solid colors */
1083 if (gradient->n_stops == 1) {
1084 pattern_res->id = 0;
1085 gstate_res->id = 0;
1086 return CAIRO_STATUS_SUCCESS;
1090 status = _cairo_pattern_create_copy (&pdf_pattern.pattern, pattern);
1091 if (unlikely (status))
1092 return status;
1094 pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface);
1095 if (pdf_pattern.pattern_res.id == 0) {
1096 cairo_pattern_destroy (pdf_pattern.pattern);
1097 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1100 pdf_pattern.gstate_res.id = 0;
1102 /* gradient patterns require an smask object to implement transparency */
1103 if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
1104 pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
1105 if (_cairo_pattern_is_opaque (pattern) == FALSE) {
1106 pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
1107 if (pdf_pattern.gstate_res.id == 0) {
1108 cairo_pattern_destroy (pdf_pattern.pattern);
1109 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1114 pdf_pattern.width = surface->width;
1115 pdf_pattern.height = surface->height;
1116 if (extents) {
1117 pdf_pattern.extents = *extents;
1118 } else {
1119 pdf_pattern.extents.x = 0;
1120 pdf_pattern.extents.y = 0;
1121 pdf_pattern.extents.width = surface->width;
1122 pdf_pattern.extents.height = surface->height;
1125 *pattern_res = pdf_pattern.pattern_res;
1126 *gstate_res = pdf_pattern.gstate_res;
1128 status = _cairo_array_append (&surface->page_patterns, &pdf_pattern);
1129 if (unlikely (status)) {
1130 cairo_pattern_destroy (pdf_pattern.pattern);
1131 return status;
1134 return CAIRO_STATUS_SUCCESS;
1137 static cairo_status_t
1138 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
1139 cairo_pdf_resource_t *resource,
1140 cairo_bool_t compressed,
1141 const char *fmt,
1142 ...)
1144 va_list ap;
1145 cairo_pdf_resource_t self, length;
1146 cairo_output_stream_t *output = NULL;
1148 if (resource) {
1149 self = *resource;
1150 _cairo_pdf_surface_update_object (surface, self);
1151 } else {
1152 self = _cairo_pdf_surface_new_object (surface);
1153 if (self.id == 0)
1154 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1157 length = _cairo_pdf_surface_new_object (surface);
1158 if (length.id == 0)
1159 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1161 if (compressed) {
1162 output = _cairo_deflate_stream_create (surface->output);
1163 if (_cairo_output_stream_get_status (output))
1164 return _cairo_output_stream_destroy (output);
1167 surface->pdf_stream.active = TRUE;
1168 surface->pdf_stream.self = self;
1169 surface->pdf_stream.length = length;
1170 surface->pdf_stream.compressed = compressed;
1171 surface->current_pattern_is_solid_color = FALSE;
1172 _cairo_pdf_operators_reset (&surface->pdf_operators);
1174 _cairo_output_stream_printf (surface->output,
1175 "%d 0 obj\n"
1176 "<< /Length %d 0 R\n",
1177 surface->pdf_stream.self.id,
1178 surface->pdf_stream.length.id);
1179 if (compressed)
1180 _cairo_output_stream_printf (surface->output,
1181 " /Filter /FlateDecode\n");
1183 if (fmt != NULL) {
1184 va_start (ap, fmt);
1185 _cairo_output_stream_vprintf (surface->output, fmt, ap);
1186 va_end (ap);
1189 _cairo_output_stream_printf (surface->output,
1190 ">>\n"
1191 "stream\n");
1193 surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
1195 if (compressed) {
1196 assert (surface->pdf_stream.old_output == NULL);
1197 surface->pdf_stream.old_output = surface->output;
1198 surface->output = output;
1199 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1202 return _cairo_output_stream_get_status (surface->output);
1205 static cairo_status_t
1206 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
1208 cairo_status_t status;
1209 long length;
1211 if (! surface->pdf_stream.active)
1212 return CAIRO_STATUS_SUCCESS;
1214 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1216 if (surface->pdf_stream.compressed) {
1217 cairo_status_t status2;
1219 status2 = _cairo_output_stream_destroy (surface->output);
1220 if (likely (status == CAIRO_STATUS_SUCCESS))
1221 status = status2;
1223 surface->output = surface->pdf_stream.old_output;
1224 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1225 surface->pdf_stream.old_output = NULL;
1226 _cairo_output_stream_printf (surface->output,
1227 "\n");
1230 length = _cairo_output_stream_get_position (surface->output) -
1231 surface->pdf_stream.start_offset;
1232 _cairo_output_stream_printf (surface->output,
1233 "endstream\n"
1234 "endobj\n");
1236 _cairo_pdf_surface_update_object (surface,
1237 surface->pdf_stream.length);
1238 _cairo_output_stream_printf (surface->output,
1239 "%d 0 obj\n"
1240 " %ld\n"
1241 "endobj\n",
1242 surface->pdf_stream.length.id,
1243 length);
1245 surface->pdf_stream.active = FALSE;
1247 if (likely (status == CAIRO_STATUS_SUCCESS))
1248 status = _cairo_output_stream_get_status (surface->output);
1250 return status;
1253 static void
1254 _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface,
1255 cairo_output_stream_t *mem_stream,
1256 cairo_pdf_resource_t resource,
1257 cairo_pdf_group_resources_t *resources,
1258 cairo_bool_t is_knockout_group)
1260 _cairo_pdf_surface_update_object (surface, resource);
1262 _cairo_output_stream_printf (surface->output,
1263 "%d 0 obj\n"
1264 "<< /Type /XObject\n"
1265 " /Length %d\n",
1266 resource.id,
1267 _cairo_memory_stream_length (mem_stream));
1269 if (surface->compress_content) {
1270 _cairo_output_stream_printf (surface->output,
1271 " /Filter /FlateDecode\n");
1274 _cairo_output_stream_printf (surface->output,
1275 " /Subtype /Form\n"
1276 " /BBox [ 0 0 %f %f ]\n"
1277 " /Group <<\n"
1278 " /Type /Group\n"
1279 " /S /Transparency\n"
1280 " /CS /DeviceRGB\n",
1281 surface->width,
1282 surface->height);
1284 if (is_knockout_group)
1285 _cairo_output_stream_printf (surface->output,
1286 " /K true\n");
1288 _cairo_output_stream_printf (surface->output,
1289 " >>\n"
1290 " /Resources\n");
1291 _cairo_pdf_surface_emit_group_resources (surface, resources);
1292 _cairo_output_stream_printf (surface->output,
1293 ">>\n"
1294 "stream\n");
1295 _cairo_memory_stream_copy (mem_stream, surface->output);
1296 _cairo_output_stream_printf (surface->output,
1297 "endstream\n"
1298 "endobj\n");
1301 static cairo_status_t
1302 _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
1303 cairo_pdf_resource_t *resource)
1305 cairo_status_t status;
1307 assert (surface->pdf_stream.active == FALSE);
1308 assert (surface->group_stream.active == FALSE);
1310 surface->group_stream.active = TRUE;
1311 surface->current_pattern_is_solid_color = FALSE;
1312 _cairo_pdf_operators_reset (&surface->pdf_operators);
1314 surface->group_stream.mem_stream = _cairo_memory_stream_create ();
1316 if (surface->compress_content) {
1317 surface->group_stream.stream =
1318 _cairo_deflate_stream_create (surface->group_stream.mem_stream);
1319 } else {
1320 surface->group_stream.stream = surface->group_stream.mem_stream;
1322 status = _cairo_output_stream_get_status (surface->group_stream.stream);
1324 surface->group_stream.old_output = surface->output;
1325 surface->output = surface->group_stream.stream;
1326 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1327 _cairo_pdf_group_resources_clear (&surface->resources);
1329 if (resource) {
1330 surface->group_stream.resource = *resource;
1331 } else {
1332 surface->group_stream.resource = _cairo_pdf_surface_new_object (surface);
1333 if (surface->group_stream.resource.id == 0)
1334 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1336 surface->group_stream.is_knockout = FALSE;
1338 return status;
1341 static cairo_status_t
1342 _cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface)
1344 cairo_status_t status;
1346 status = _cairo_pdf_surface_open_group (surface, NULL);
1347 if (unlikely (status))
1348 return status;
1350 surface->group_stream.is_knockout = TRUE;
1352 return CAIRO_STATUS_SUCCESS;
1355 static cairo_status_t
1356 _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
1357 cairo_pdf_resource_t *group)
1359 cairo_status_t status = CAIRO_STATUS_SUCCESS, status2;
1361 assert (surface->pdf_stream.active == FALSE);
1362 assert (surface->group_stream.active == TRUE);
1364 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1365 if (unlikely (status))
1366 return status;
1368 if (surface->compress_content) {
1369 status = _cairo_output_stream_destroy (surface->group_stream.stream);
1370 surface->group_stream.stream = NULL;
1372 _cairo_output_stream_printf (surface->group_stream.mem_stream,
1373 "\n");
1375 surface->output = surface->group_stream.old_output;
1376 _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1377 surface->group_stream.active = FALSE;
1378 _cairo_pdf_surface_write_memory_stream (surface,
1379 surface->group_stream.mem_stream,
1380 surface->group_stream.resource,
1381 &surface->resources,
1382 surface->group_stream.is_knockout);
1383 if (group)
1384 *group = surface->group_stream.resource;
1386 status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
1387 if (status == CAIRO_STATUS_SUCCESS)
1388 status = status2;
1390 surface->group_stream.mem_stream = NULL;
1391 surface->group_stream.stream = NULL;
1393 return status;
1396 static cairo_status_t
1397 _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
1398 cairo_pdf_resource_t *resource,
1399 cairo_bool_t is_form)
1401 cairo_status_t status;
1403 assert (surface->pdf_stream.active == FALSE);
1404 assert (surface->group_stream.active == FALSE);
1406 surface->content_resources = _cairo_pdf_surface_new_object (surface);
1407 if (surface->content_resources.id == 0)
1408 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1410 if (is_form) {
1411 status =
1412 _cairo_pdf_surface_open_stream (surface,
1413 resource,
1414 surface->compress_content,
1415 " /Type /XObject\n"
1416 " /Subtype /Form\n"
1417 " /BBox [ 0 0 %f %f ]\n"
1418 " /Group <<\n"
1419 " /Type /Group\n"
1420 " /S /Transparency\n"
1421 " /CS /DeviceRGB\n"
1422 " >>\n"
1423 " /Resources %d 0 R\n",
1424 surface->width,
1425 surface->height,
1426 surface->content_resources.id);
1427 } else {
1428 status =
1429 _cairo_pdf_surface_open_stream (surface,
1430 resource,
1431 surface->compress_content,
1432 NULL);
1434 if (unlikely (status))
1435 return status;
1437 surface->content = surface->pdf_stream.self;
1439 _cairo_output_stream_printf (surface->output, "q\n");
1441 return _cairo_output_stream_get_status (surface->output);
1444 static cairo_status_t
1445 _cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
1447 cairo_status_t status;
1449 assert (surface->pdf_stream.active == TRUE);
1450 assert (surface->group_stream.active == FALSE);
1452 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1453 if (unlikely (status))
1454 return status;
1456 _cairo_output_stream_printf (surface->output, "Q\n");
1457 status = _cairo_pdf_surface_close_stream (surface);
1458 if (unlikely (status))
1459 return status;
1461 _cairo_pdf_surface_update_object (surface, surface->content_resources);
1462 _cairo_output_stream_printf (surface->output,
1463 "%d 0 obj\n",
1464 surface->content_resources.id);
1465 _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
1466 _cairo_output_stream_printf (surface->output,
1467 "endobj\n");
1469 return _cairo_output_stream_get_status (surface->output);
1472 static cairo_surface_t *
1473 _cairo_pdf_surface_create_similar (void *abstract_surface,
1474 cairo_content_t content,
1475 int width,
1476 int height)
1478 return _cairo_meta_surface_create (content, width, height);
1481 static void
1482 _cairo_pdf_source_surface_entry_pluck (void *entry, void *closure)
1484 cairo_pdf_source_surface_entry_t *surface_entry = entry;
1485 cairo_hash_table_t *patterns = closure;
1487 _cairo_hash_table_remove (patterns, &surface_entry->base);
1488 free (surface_entry);
1491 static cairo_status_t
1492 _cairo_pdf_surface_finish (void *abstract_surface)
1494 cairo_pdf_surface_t *surface = abstract_surface;
1495 long offset;
1496 cairo_pdf_resource_t info, catalog;
1497 cairo_status_t status, status2;
1499 status = surface->base.status;
1500 if (status == CAIRO_STATUS_SUCCESS)
1501 status = _cairo_pdf_surface_emit_font_subsets (surface);
1503 _cairo_pdf_surface_write_pages (surface);
1505 info = _cairo_pdf_surface_write_info (surface);
1506 if (info.id == 0 && status == CAIRO_STATUS_SUCCESS)
1507 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1509 catalog = _cairo_pdf_surface_write_catalog (surface);
1510 if (catalog.id == 0 && status == CAIRO_STATUS_SUCCESS)
1511 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1513 offset = _cairo_pdf_surface_write_xref (surface);
1515 _cairo_output_stream_printf (surface->output,
1516 "trailer\n"
1517 "<< /Size %d\n"
1518 " /Root %d 0 R\n"
1519 " /Info %d 0 R\n"
1520 ">>\n",
1521 surface->next_available_resource.id,
1522 catalog.id,
1523 info.id);
1525 _cairo_output_stream_printf (surface->output,
1526 "startxref\n"
1527 "%ld\n"
1528 "%%%%EOF\n",
1529 offset);
1531 /* pdf_operators has already been flushed when the last stream was
1532 * closed so we should never be writing anything here - however,
1533 * the stream may itself be in an error state. */
1534 status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
1535 if (status == CAIRO_STATUS_SUCCESS)
1536 status = status2;
1538 /* close any active streams still open due to fatal errors */
1539 status2 = _cairo_pdf_surface_close_stream (surface);
1540 if (status == CAIRO_STATUS_SUCCESS)
1541 status = status2;
1543 if (surface->group_stream.stream != NULL) {
1544 status2 = _cairo_output_stream_destroy (surface->group_stream.stream);
1545 if (status == CAIRO_STATUS_SUCCESS)
1546 status = status2;
1548 if (surface->group_stream.mem_stream != NULL) {
1549 status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
1550 if (status == CAIRO_STATUS_SUCCESS)
1551 status = status2;
1553 if (surface->pdf_stream.active)
1554 surface->output = surface->pdf_stream.old_output;
1555 if (surface->group_stream.active)
1556 surface->output = surface->group_stream.old_output;
1558 /* and finish the pdf surface */
1559 status2 = _cairo_output_stream_destroy (surface->output);
1560 if (status == CAIRO_STATUS_SUCCESS)
1561 status = status2;
1563 _cairo_pdf_surface_clear (surface);
1564 _cairo_pdf_group_resources_fini (&surface->resources);
1566 _cairo_array_fini (&surface->objects);
1567 _cairo_array_fini (&surface->pages);
1568 _cairo_array_fini (&surface->rgb_linear_functions);
1569 _cairo_array_fini (&surface->alpha_linear_functions);
1570 _cairo_array_fini (&surface->page_patterns);
1571 _cairo_array_fini (&surface->page_surfaces);
1572 _cairo_hash_table_foreach (surface->all_surfaces,
1573 _cairo_pdf_source_surface_entry_pluck,
1574 surface->all_surfaces);
1575 _cairo_hash_table_destroy (surface->all_surfaces);
1576 _cairo_array_fini (&surface->smask_groups);
1577 _cairo_array_fini (&surface->fonts);
1578 _cairo_array_fini (&surface->knockout_group);
1580 if (surface->font_subsets) {
1581 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
1582 surface->font_subsets = NULL;
1585 return status;
1588 static cairo_int_status_t
1589 _cairo_pdf_surface_start_page (void *abstract_surface)
1591 cairo_pdf_surface_t *surface = abstract_surface;
1593 /* Document header */
1594 if (! surface->header_emitted) {
1595 const char *version;
1597 switch (surface->pdf_version) {
1598 case CAIRO_PDF_VERSION_1_4:
1599 version = "1.4";
1600 break;
1601 default:
1602 case CAIRO_PDF_VERSION_1_5:
1603 version = "1.5";
1604 break;
1607 _cairo_output_stream_printf (surface->output,
1608 "%%PDF-%s\n", version);
1609 _cairo_output_stream_printf (surface->output,
1610 "%%%c%c%c%c\n", 181, 237, 174, 251);
1611 surface->header_emitted = TRUE;
1614 _cairo_pdf_group_resources_clear (&surface->resources);
1616 return CAIRO_STATUS_SUCCESS;
1619 static cairo_int_status_t
1620 _cairo_pdf_surface_has_fallback_images (void *abstract_surface,
1621 cairo_bool_t has_fallbacks)
1623 cairo_status_t status;
1624 cairo_pdf_surface_t *surface = abstract_surface;
1626 surface->has_fallback_images = has_fallbacks;
1627 status = _cairo_pdf_surface_open_content_stream (surface, NULL, has_fallbacks);
1628 if (unlikely (status))
1629 return status;
1631 return CAIRO_STATUS_SUCCESS;
1634 static cairo_bool_t
1635 _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
1637 return TRUE;
1640 /* Emit alpha channel from the image into the given data, providing
1641 * an id that can be used to reference the resulting SMask object.
1643 * In the case that the alpha channel happens to be all opaque, then
1644 * no SMask object will be emitted and *id_ret will be set to 0.
1646 static cairo_status_t
1647 _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
1648 cairo_image_surface_t *image,
1649 cairo_pdf_resource_t *stream_ret)
1651 cairo_status_t status = CAIRO_STATUS_SUCCESS;
1652 char *alpha;
1653 unsigned long alpha_size;
1654 uint32_t *pixel32;
1655 uint8_t *pixel8;
1656 int i, x, y;
1657 cairo_bool_t opaque;
1658 uint8_t a;
1660 /* This is the only image format we support, which simplifies things. */
1661 assert (image->format == CAIRO_FORMAT_ARGB32 ||
1662 image->format == CAIRO_FORMAT_A8 ||
1663 image->format == CAIRO_FORMAT_A1 );
1665 stream_ret->id = 0;
1667 if (image->format == CAIRO_FORMAT_A1) {
1668 alpha_size = (image->width + 7) / 8 * image->height;
1669 alpha = _cairo_malloc_ab ((image->width+7) / 8, image->height);
1670 } else {
1671 alpha_size = image->height * image->width;
1672 alpha = _cairo_malloc_ab (image->height, image->width);
1675 if (unlikely (alpha == NULL)) {
1676 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1677 goto CLEANUP;
1680 opaque = TRUE;
1681 i = 0;
1682 for (y = 0; y < image->height; y++) {
1683 if (image->format == CAIRO_FORMAT_ARGB32) {
1684 pixel32 = (uint32_t *) (image->data + y * image->stride);
1686 for (x = 0; x < image->width; x++, pixel32++) {
1687 a = (*pixel32 & 0xff000000) >> 24;
1688 alpha[i++] = a;
1689 if (a != 0xff)
1690 opaque = FALSE;
1692 } else if (image->format == CAIRO_FORMAT_A8){
1693 pixel8 = (uint8_t *) (image->data + y * image->stride);
1695 for (x = 0; x < image->width; x++, pixel8++) {
1696 a = *pixel8;
1697 alpha[i++] = a;
1698 if (a != 0xff)
1699 opaque = FALSE;
1701 } else { /* image->format == CAIRO_FORMAT_A1 */
1702 pixel8 = (uint8_t *) (image->data + y * image->stride);
1704 for (x = 0; x < (image->width + 7) / 8; x++, pixel8++) {
1705 a = *pixel8;
1706 a = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a);
1707 alpha[i++] = a;
1708 if (a != 0xff)
1709 opaque = FALSE;
1714 /* Bail out without emitting smask if it's all opaque. */
1715 if (opaque)
1716 goto CLEANUP_ALPHA;
1718 status = _cairo_pdf_surface_open_stream (surface,
1719 NULL,
1720 TRUE,
1721 " /Type /XObject\n"
1722 " /Subtype /Image\n"
1723 " /Width %d\n"
1724 " /Height %d\n"
1725 " /ColorSpace /DeviceGray\n"
1726 " /BitsPerComponent %d\n",
1727 image->width, image->height,
1728 image->format == CAIRO_FORMAT_A1 ? 1 : 8);
1729 if (unlikely (status))
1730 goto CLEANUP_ALPHA;
1732 *stream_ret = surface->pdf_stream.self;
1733 _cairo_output_stream_write (surface->output, alpha, alpha_size);
1734 status = _cairo_pdf_surface_close_stream (surface);
1736 CLEANUP_ALPHA:
1737 free (alpha);
1738 CLEANUP:
1739 return status;
1742 /* Emit image data into the given surface, providing a resource that
1743 * can be used to reference the data in image_ret. */
1744 static cairo_status_t
1745 _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
1746 cairo_image_surface_t *image,
1747 cairo_pdf_resource_t *image_res,
1748 cairo_filter_t filter)
1750 cairo_status_t status = CAIRO_STATUS_SUCCESS;
1751 char *rgb;
1752 unsigned long rgb_size;
1753 uint32_t *pixel;
1754 int i, x, y;
1755 cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
1756 cairo_bool_t need_smask;
1757 const char *interpolate = "true";
1759 /* These are the only image formats we currently support, (which
1760 * makes things a lot simpler here). This is enforced through
1761 * _cairo_pdf_surface_analyze_operation which only accept source surfaces of
1762 * CONTENT_COLOR or CONTENT_COLOR_ALPHA.
1764 assert (image->format == CAIRO_FORMAT_RGB24 ||
1765 image->format == CAIRO_FORMAT_ARGB32 ||
1766 image->format == CAIRO_FORMAT_A8 ||
1767 image->format == CAIRO_FORMAT_A1);
1769 rgb_size = image->height * image->width * 3;
1770 rgb = _cairo_malloc_abc (image->width, image->height, 3);
1771 if (unlikely (rgb == NULL)) {
1772 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1773 goto CLEANUP;
1776 i = 0;
1777 for (y = 0; y < image->height; y++) {
1778 pixel = (uint32_t *) (image->data + y * image->stride);
1780 for (x = 0; x < image->width; x++, pixel++) {
1781 /* XXX: We're un-premultiplying alpha here. My reading of the PDF
1782 * specification suggests that we should be able to avoid having
1783 * to do this by filling in the SMask's Matte dictionary
1784 * appropriately, but my attempts to do that so far have
1785 * failed. */
1786 if (image->format == CAIRO_FORMAT_ARGB32) {
1787 uint8_t a;
1788 a = (*pixel & 0xff000000) >> 24;
1789 if (a == 0) {
1790 rgb[i++] = 0;
1791 rgb[i++] = 0;
1792 rgb[i++] = 0;
1793 } else {
1794 rgb[i++] = (((*pixel & 0xff0000) >> 16) * 255 + a / 2) / a;
1795 rgb[i++] = (((*pixel & 0x00ff00) >> 8) * 255 + a / 2) / a;
1796 rgb[i++] = (((*pixel & 0x0000ff) >> 0) * 255 + a / 2) / a;
1798 } else if (image->format == CAIRO_FORMAT_RGB24) {
1799 rgb[i++] = (*pixel & 0x00ff0000) >> 16;
1800 rgb[i++] = (*pixel & 0x0000ff00) >> 8;
1801 rgb[i++] = (*pixel & 0x000000ff) >> 0;
1802 } else {
1803 rgb[i++] = 0;
1804 rgb[i++] = 0;
1805 rgb[i++] = 0;
1810 need_smask = FALSE;
1811 if (image->format == CAIRO_FORMAT_ARGB32 ||
1812 image->format == CAIRO_FORMAT_A8 ||
1813 image->format == CAIRO_FORMAT_A1) {
1814 status = _cairo_pdf_surface_emit_smask (surface, image, &smask);
1815 if (unlikely (status))
1816 goto CLEANUP_RGB;
1818 if (smask.id)
1819 need_smask = TRUE;
1822 switch (filter) {
1823 case CAIRO_FILTER_GOOD:
1824 case CAIRO_FILTER_BEST:
1825 case CAIRO_FILTER_BILINEAR:
1826 interpolate = "true";
1827 break;
1828 case CAIRO_FILTER_FAST:
1829 case CAIRO_FILTER_NEAREST:
1830 case CAIRO_FILTER_GAUSSIAN:
1831 interpolate = "false";
1832 break;
1835 #define IMAGE_DICTIONARY " /Type /XObject\n" \
1836 " /Subtype /Image\n" \
1837 " /Width %d\n" \
1838 " /Height %d\n" \
1839 " /ColorSpace /DeviceRGB\n" \
1840 " /Interpolate %s\n" \
1841 " /BitsPerComponent 8\n"
1843 if (need_smask)
1844 status = _cairo_pdf_surface_open_stream (surface,
1845 image_res,
1846 TRUE,
1847 IMAGE_DICTIONARY
1848 " /SMask %d 0 R\n",
1849 image->width, image->height,
1850 interpolate,
1851 smask.id);
1852 else
1853 status = _cairo_pdf_surface_open_stream (surface,
1854 image_res,
1855 TRUE,
1856 IMAGE_DICTIONARY,
1857 image->width, image->height,
1858 interpolate);
1859 if (unlikely (status))
1860 goto CLEANUP_RGB;
1862 #undef IMAGE_DICTIONARY
1864 if (image_res == NULL)
1865 *image_res = surface->pdf_stream.self;
1866 _cairo_output_stream_write (surface->output, rgb, rgb_size);
1867 status = _cairo_pdf_surface_close_stream (surface);
1869 CLEANUP_RGB:
1870 free (rgb);
1871 CLEANUP:
1872 return status;
1875 static cairo_int_status_t
1876 _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface,
1877 cairo_surface_t *source,
1878 cairo_pdf_resource_t res)
1880 cairo_status_t status;
1881 const unsigned char *mime_data;
1882 unsigned int mime_data_length;
1883 cairo_image_info_t info;
1885 if (surface->pdf_version < CAIRO_PDF_VERSION_1_5)
1886 return CAIRO_INT_STATUS_UNSUPPORTED;
1888 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
1889 &mime_data, &mime_data_length);
1890 if (mime_data == NULL)
1891 return CAIRO_INT_STATUS_UNSUPPORTED;
1893 status = _cairo_image_info_get_jpx_info (&info, mime_data, mime_data_length);
1894 if (status)
1895 return status;
1897 status = _cairo_pdf_surface_open_stream (surface,
1898 &res,
1899 FALSE,
1900 " /Type /XObject\n"
1901 " /Subtype /Image\n"
1902 " /Width %d\n"
1903 " /Height %d\n"
1904 " /ColorSpace /DeviceRGB\n"
1905 " /Filter /JPXDecode\n",
1906 info.width,
1907 info.height);
1908 if (status)
1909 return status;
1911 _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
1912 _cairo_output_stream_printf (surface->output, "\n");
1913 status = _cairo_pdf_surface_close_stream (surface);
1915 return status;
1918 static cairo_int_status_t
1919 _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
1920 cairo_surface_t *source,
1921 cairo_pdf_resource_t res)
1923 cairo_status_t status;
1924 const unsigned char *mime_data;
1925 unsigned int mime_data_length;
1926 cairo_image_info_t info;
1928 cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
1929 &mime_data, &mime_data_length);
1930 if (unlikely (source->status))
1931 return source->status;
1932 if (mime_data == NULL)
1933 return CAIRO_INT_STATUS_UNSUPPORTED;
1935 status = _cairo_image_info_get_jpeg_info (&info, mime_data, mime_data_length);
1936 if (unlikely (status))
1937 return status;
1939 if (info.num_components != 1 && info.num_components != 3)
1940 return CAIRO_INT_STATUS_UNSUPPORTED;
1942 status = _cairo_pdf_surface_open_stream (surface,
1943 &res,
1944 FALSE,
1945 " /Type /XObject\n"
1946 " /Subtype /Image\n"
1947 " /Width %d\n"
1948 " /Height %d\n"
1949 " /ColorSpace %s\n"
1950 " /BitsPerComponent %d\n"
1951 " /Filter /DCTDecode\n",
1952 info.width,
1953 info.height,
1954 info.num_components == 1 ? "/DeviceGray" : "/DeviceRGB",
1955 info.bits_per_component);
1956 if (unlikely (status))
1957 return status;
1959 _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
1960 _cairo_output_stream_printf (surface->output, "\n");
1961 status = _cairo_pdf_surface_close_stream (surface);
1963 return status;
1966 static cairo_status_t
1967 _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
1968 cairo_surface_t *source,
1969 cairo_pdf_resource_t resource,
1970 cairo_bool_t interpolate)
1972 cairo_image_surface_t *image;
1973 void *image_extra;
1974 cairo_status_t status;
1976 status = _cairo_pdf_surface_emit_jpx_image (surface, source, resource);
1977 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1978 return status;
1980 status = _cairo_pdf_surface_emit_jpeg_image (surface, source, resource);
1981 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1982 return status;
1984 status = _cairo_surface_acquire_source_image (source, &image, &image_extra);
1985 if (unlikely (status))
1986 return status;
1988 status = _cairo_pdf_surface_emit_image (surface, image,
1989 &resource, interpolate);
1990 if (unlikely (status))
1991 goto BAIL;
1993 BAIL:
1994 _cairo_surface_release_source_image (source, image, image_extra);
1996 return status;
1999 static cairo_status_t
2000 _cairo_pdf_surface_emit_padded_image_surface (cairo_pdf_surface_t *surface,
2001 cairo_pdf_pattern_t *pdf_pattern,
2002 cairo_pdf_resource_t *resource,
2003 int *width,
2004 int *height,
2005 int *origin_x,
2006 int *origin_y)
2008 cairo_image_surface_t *image;
2009 cairo_surface_t *pad_image;
2010 void *image_extra;
2011 cairo_status_t status;
2012 cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
2013 int x = 0;
2014 int y = 0;
2015 cairo_bool_t interpolate;
2017 status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
2018 if (unlikely (status))
2019 return status;
2021 pad_image = &image->base;
2022 if (cairo_pattern_get_extend (&pattern->base) == CAIRO_EXTEND_PAD) {
2023 cairo_box_t box;
2024 cairo_rectangle_int_t rect;
2025 cairo_surface_pattern_t pad_pattern;
2027 /* get the operation extents in pattern space */
2028 _cairo_box_from_rectangle (&box, &pdf_pattern->extents);
2029 _cairo_matrix_transform_bounding_box_fixed (&pattern->base.matrix, &box, NULL);
2030 _cairo_box_round_to_rectangle (&box, &rect);
2031 x = -rect.x;
2032 y = -rect.y;
2034 pad_image = _cairo_image_surface_create_with_content (pattern->surface->content,
2035 rect.width,
2036 rect.height);
2037 if (pad_image->status) {
2038 status = pad_image->status;
2039 goto BAIL;
2042 _cairo_pattern_init_for_surface (&pad_pattern, &image->base);
2043 cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
2044 pad_pattern.base.extend = CAIRO_EXTEND_PAD;
2045 status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
2046 &pad_pattern.base,
2047 NULL,
2048 pad_image,
2049 0, 0,
2050 0, 0,
2051 0, 0,
2052 rect.width,
2053 rect.height);
2054 _cairo_pattern_fini (&pad_pattern.base);
2055 if (unlikely (status))
2056 goto BAIL;
2059 switch (pdf_pattern->pattern->filter) {
2060 case CAIRO_FILTER_GOOD:
2061 case CAIRO_FILTER_BEST:
2062 case CAIRO_FILTER_BILINEAR:
2063 interpolate = TRUE;
2064 break;
2065 case CAIRO_FILTER_FAST:
2066 case CAIRO_FILTER_NEAREST:
2067 case CAIRO_FILTER_GAUSSIAN:
2068 interpolate = FALSE;
2069 break;
2072 *resource = _cairo_pdf_surface_new_object (surface);
2073 if (resource->id == 0) {
2074 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2075 goto BAIL;
2078 status = _cairo_pdf_surface_emit_image (surface, (cairo_image_surface_t *)pad_image,
2079 resource, interpolate);
2080 if (unlikely (status))
2081 goto BAIL;
2083 *width = ((cairo_image_surface_t *)pad_image)->width;
2084 *height = ((cairo_image_surface_t *)pad_image)->height;
2085 *origin_x = x;
2086 *origin_y = y;
2088 BAIL:
2089 if (pad_image != &image->base)
2090 cairo_surface_destroy (pad_image);
2092 _cairo_surface_release_source_image (pattern->surface, image, image_extra);
2094 return status;
2098 static cairo_status_t
2099 _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
2100 cairo_surface_t *meta_surface,
2101 cairo_pdf_resource_t resource)
2103 double old_width, old_height;
2104 cairo_paginated_mode_t old_paginated_mode;
2105 cairo_clip_t *old_clip;
2106 cairo_rectangle_int_t meta_extents;
2107 cairo_status_t status;
2108 int alpha = 0;
2110 status = _cairo_surface_get_extents (meta_surface, &meta_extents);
2111 if (unlikely (status))
2112 return status;
2114 old_width = surface->width;
2115 old_height = surface->height;
2116 old_paginated_mode = surface->paginated_mode;
2117 old_clip = _cairo_surface_get_clip (&surface->base);
2118 _cairo_pdf_surface_set_size_internal (surface,
2119 meta_extents.width,
2120 meta_extents.height);
2121 /* Patterns are emitted after fallback images. The paginated mode
2122 * needs to be set to _RENDER while the meta surface is replayed
2123 * back to this surface.
2125 surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
2126 _cairo_pdf_group_resources_clear (&surface->resources);
2127 status = _cairo_pdf_surface_open_content_stream (surface, &resource, TRUE);
2128 if (unlikely (status))
2129 return status;
2131 if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
2132 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
2133 if (unlikely (status))
2134 return status;
2136 _cairo_output_stream_printf (surface->output,
2137 "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
2138 alpha,
2139 surface->width,
2140 surface->height);
2143 status = _cairo_meta_surface_replay_region (meta_surface, &surface->base,
2144 CAIRO_META_REGION_NATIVE);
2145 assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
2146 if (unlikely (status))
2147 return status;
2149 status = _cairo_surface_set_clip (&surface->base, old_clip);
2150 if (unlikely (status))
2151 return status;
2153 status = _cairo_pdf_surface_close_content_stream (surface);
2155 _cairo_pdf_surface_set_size_internal (surface,
2156 old_width,
2157 old_height);
2158 surface->paginated_mode = old_paginated_mode;
2160 return status;
2163 static cairo_status_t
2164 _cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface,
2165 cairo_pdf_source_surface_t *src_surface)
2167 if (_cairo_surface_is_meta (src_surface->surface)) {
2168 return _cairo_pdf_surface_emit_meta_surface (surface,
2169 src_surface->surface,
2170 src_surface->hash_entry->surface_res);
2171 } else {
2172 return _cairo_pdf_surface_emit_image_surface (surface,
2173 src_surface->surface,
2174 src_surface->hash_entry->surface_res,
2175 src_surface->hash_entry->interpolate);
2179 static cairo_status_t
2180 _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
2181 cairo_pdf_pattern_t *pdf_pattern)
2183 cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
2184 cairo_status_t status;
2185 cairo_pdf_resource_t pattern_resource = {0};
2186 cairo_matrix_t cairo_p2d, pdf_p2d;
2187 cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
2188 double xstep, ystep;
2189 cairo_rectangle_int_t surface_extents;
2190 int pattern_width = 0; /* squelch bogus compiler warning */
2191 int pattern_height = 0; /* squelch bogus compiler warning */
2192 int origin_x = 0; /* squelch bogus compiler warning */
2193 int origin_y = 0; /* squelch bogus compiler warning */
2194 int bbox_x, bbox_y;
2195 char draw_surface[200];
2197 if (cairo_pattern_get_extend (&pattern->base) == CAIRO_EXTEND_PAD &&
2198 ! _cairo_surface_is_meta (pattern->surface))
2200 status = _cairo_pdf_surface_emit_padded_image_surface (surface,
2201 pdf_pattern,
2202 &pattern_resource,
2203 &pattern_width,
2204 &pattern_height,
2205 &origin_x,
2206 &origin_y);
2208 else
2210 status = _cairo_pdf_surface_add_source_surface (surface,
2211 pattern->surface,
2212 pdf_pattern->pattern->filter,
2213 &pattern_resource,
2214 &pattern_width,
2215 &pattern_height);
2217 if (unlikely (status))
2218 return status;
2220 status = _cairo_surface_get_extents (&surface->base, &surface_extents);
2221 if (unlikely (status))
2222 return status;
2224 bbox_x = pattern_width;
2225 bbox_y = pattern_height;
2226 switch (extend) {
2227 case CAIRO_EXTEND_PAD:
2228 case CAIRO_EXTEND_NONE:
2230 /* In PS/PDF, (as far as I can tell), all patterns are
2231 * repeating. So we support cairo's EXTEND_NONE semantics
2232 * by setting the repeat step size to a size large enough
2233 * to guarantee that no more than a single occurrence will
2234 * be visible.
2236 * First, map the surface extents into pattern space (since
2237 * xstep and ystep are in pattern space). Then use an upper
2238 * bound on the length of the diagonal of the pattern image
2239 * and the surface as repeat size. This guarantees to never
2240 * repeat visibly.
2242 double x1 = 0.0, y1 = 0.0;
2243 double x2 = surface->width, y2 = surface->height;
2244 _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
2245 &x1, &y1, &x2, &y2,
2246 NULL);
2248 /* Rather than computing precise bounds of the union, just
2249 * add the surface extents unconditionally. We only
2250 * required an answer that's large enough, we don't really
2251 * care if it's not as tight as possible.*/
2252 xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
2253 pattern_width + pattern_height);
2255 break;
2256 case CAIRO_EXTEND_REPEAT:
2257 xstep = pattern_width;
2258 ystep = pattern_height;
2259 break;
2260 case CAIRO_EXTEND_REFLECT:
2261 bbox_x = pattern_width*2;
2262 bbox_y = pattern_height*2;
2263 xstep = bbox_x;
2264 ystep = bbox_y;
2265 break;
2266 /* All the rest (if any) should have been analyzed away, so this
2267 * case should be unreachable. */
2268 default:
2269 ASSERT_NOT_REACHED;
2270 xstep = 0;
2271 ystep = 0;
2274 /* At this point, (that is, within the surface backend interface),
2275 * the pattern's matrix maps from cairo's device space to cairo's
2276 * pattern space, (both with their origin at the upper-left, and
2277 * cairo's pattern space of size width,height).
2279 * Then, we must emit a PDF pattern object that maps from its own
2280 * pattern space, (which has a size that we establish in the BBox
2281 * dictionary entry), to the PDF page's *initial* space, (which
2282 * does not benefit from the Y-axis flipping matrix that we emit
2283 * on each page). So the PDF patterns matrix maps from a
2284 * (width,height) pattern space to a device space with the origin
2285 * in the lower-left corner.
2287 * So to handle all of that, we start with an identity matrix for
2288 * the PDF pattern to device matrix. We translate it up by the
2289 * image height then flip it in the Y direction, (moving us from
2290 * the PDF origin to cairo's origin). We then multiply in the
2291 * inverse of the cairo pattern matrix, (since it maps from device
2292 * to pattern, while we're setting up pattern to device). Finally,
2293 * we translate back down by the image height and flip again to
2294 * end up at the lower-left origin that PDF expects.
2296 * Additionally, within the stream that paints the pattern itself,
2297 * we are using a PDF image object that has a size of (1,1) so we
2298 * have to scale it up by the image width and height to fill our
2299 * pattern cell.
2301 cairo_p2d = pattern->base.matrix;
2302 status = cairo_matrix_invert (&cairo_p2d);
2303 /* cairo_pattern_set_matrix ensures the matrix is invertible */
2304 assert (status == CAIRO_STATUS_SUCCESS);
2306 cairo_matrix_init_identity (&pdf_p2d);
2307 cairo_matrix_translate (&pdf_p2d, 0.0, surface_extents.height);
2308 cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
2309 cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
2310 cairo_matrix_translate (&pdf_p2d, -origin_x, -origin_y);
2311 cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
2312 cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
2314 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
2315 status = _cairo_pdf_surface_open_stream (surface,
2316 &pdf_pattern->pattern_res,
2317 FALSE,
2318 " /PatternType 1\n"
2319 " /BBox [0 0 %d %d]\n"
2320 " /XStep %f\n"
2321 " /YStep %f\n"
2322 " /TilingType 1\n"
2323 " /PaintType 1\n"
2324 " /Matrix [ %f %f %f %f %f %f ]\n"
2325 " /Resources << /XObject << /x%d %d 0 R >> >>\n",
2326 bbox_x, bbox_y,
2327 xstep, ystep,
2328 pdf_p2d.xx, pdf_p2d.yx,
2329 pdf_p2d.xy, pdf_p2d.yy,
2330 pdf_p2d.x0, pdf_p2d.y0,
2331 pattern_resource.id,
2332 pattern_resource.id);
2333 if (unlikely (status))
2334 return status;
2336 if (_cairo_surface_is_meta (pattern->surface)) {
2337 snprintf(draw_surface,
2338 sizeof (draw_surface),
2339 "/x%d Do\n",
2340 pattern_resource.id);
2341 } else {
2342 snprintf(draw_surface,
2343 sizeof (draw_surface),
2344 "q %d 0 0 %d 0 0 cm /x%d Do Q",
2345 pattern_width,
2346 pattern_height,
2347 pattern_resource.id);
2350 if (extend == CAIRO_EXTEND_REFLECT) {
2351 _cairo_output_stream_printf (surface->output,
2352 "q 0 0 %d %d re W n %s Q\n"
2353 "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n %s Q\n"
2354 "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n %s Q\n"
2355 "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n %s Q\n",
2356 pattern_width, pattern_height,
2357 draw_surface,
2358 pattern_width*2, pattern_width, pattern_height,
2359 draw_surface,
2360 pattern_height*2, pattern_width, pattern_height,
2361 draw_surface,
2362 pattern_width*2, pattern_height*2, pattern_width, pattern_height,
2363 draw_surface);
2364 } else {
2365 _cairo_output_stream_printf (surface->output,
2366 " %s \n",
2367 draw_surface);
2370 status = _cairo_pdf_surface_close_stream (surface);
2371 if (unlikely (status))
2372 return status;
2374 return _cairo_output_stream_get_status (surface->output);
2377 typedef struct _cairo_pdf_color_stop {
2378 double offset;
2379 double color[4];
2380 cairo_pdf_resource_t resource;
2381 } cairo_pdf_color_stop_t;
2383 static cairo_status_t
2384 cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t *surface,
2385 cairo_pdf_color_stop_t *stop1,
2386 cairo_pdf_color_stop_t *stop2,
2387 cairo_pdf_resource_t *function)
2389 int num_elems, i;
2390 cairo_pdf_rgb_linear_function_t elem;
2391 cairo_pdf_resource_t res;
2392 cairo_status_t status;
2394 num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions);
2395 for (i = 0; i < num_elems; i++) {
2396 _cairo_array_copy_element (&surface->rgb_linear_functions, i, &elem);
2397 if (memcmp (&elem.color1[0], &stop1->color[0], sizeof (double)*3) != 0)
2398 continue;
2399 if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0)
2400 continue;
2401 *function = elem.resource;
2402 return CAIRO_STATUS_SUCCESS;
2405 res = _cairo_pdf_surface_new_object (surface);
2406 if (res.id == 0)
2407 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2409 _cairo_output_stream_printf (surface->output,
2410 "%d 0 obj\n"
2411 "<< /FunctionType 2\n"
2412 " /Domain [ 0 1 ]\n"
2413 " /C0 [ %f %f %f ]\n"
2414 " /C1 [ %f %f %f ]\n"
2415 " /N 1\n"
2416 ">>\n"
2417 "endobj\n",
2418 res.id,
2419 stop1->color[0],
2420 stop1->color[1],
2421 stop1->color[2],
2422 stop2->color[0],
2423 stop2->color[1],
2424 stop2->color[2]);
2426 elem.resource = res;
2427 memcpy (&elem.color1[0], &stop1->color[0], sizeof (double)*3);
2428 memcpy (&elem.color2[0], &stop2->color[0], sizeof (double)*3);
2430 status = _cairo_array_append (&surface->rgb_linear_functions, &elem);
2431 *function = res;
2433 return status;
2436 static cairo_status_t
2437 cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t *surface,
2438 cairo_pdf_color_stop_t *stop1,
2439 cairo_pdf_color_stop_t *stop2,
2440 cairo_pdf_resource_t *function)
2442 int num_elems, i;
2443 cairo_pdf_alpha_linear_function_t elem;
2444 cairo_pdf_resource_t res;
2445 cairo_status_t status;
2447 num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions);
2448 for (i = 0; i < num_elems; i++) {
2449 _cairo_array_copy_element (&surface->alpha_linear_functions, i, &elem);
2450 if (elem.alpha1 != stop1->color[3])
2451 continue;
2452 if (elem.alpha2 != stop2->color[3])
2453 continue;
2454 *function = elem.resource;
2455 return CAIRO_STATUS_SUCCESS;
2458 res = _cairo_pdf_surface_new_object (surface);
2459 if (res.id == 0)
2460 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2462 _cairo_output_stream_printf (surface->output,
2463 "%d 0 obj\n"
2464 "<< /FunctionType 2\n"
2465 " /Domain [ 0 1 ]\n"
2466 " /C0 [ %f ]\n"
2467 " /C1 [ %f ]\n"
2468 " /N 1\n"
2469 ">>\n"
2470 "endobj\n",
2471 res.id,
2472 stop1->color[3],
2473 stop2->color[3]);
2475 elem.resource = res;
2476 elem.alpha1 = stop1->color[3];
2477 elem.alpha2 = stop2->color[3];
2479 status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
2480 *function = res;
2482 return status;
2485 static cairo_status_t
2486 _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
2487 unsigned int n_stops,
2488 cairo_pdf_color_stop_t *stops,
2489 cairo_bool_t is_alpha,
2490 cairo_pdf_resource_t *function)
2492 cairo_pdf_resource_t res;
2493 unsigned int i;
2494 cairo_status_t status;
2496 /* emit linear gradients between pairs of subsequent stops... */
2497 for (i = 0; i < n_stops-1; i++) {
2498 if (is_alpha) {
2499 status = cairo_pdf_surface_emit_alpha_linear_function (surface,
2500 &stops[i],
2501 &stops[i+1],
2502 &stops[i].resource);
2503 if (unlikely (status))
2504 return status;
2505 } else {
2506 status = cairo_pdf_surface_emit_rgb_linear_function (surface,
2507 &stops[i],
2508 &stops[i+1],
2509 &stops[i].resource);
2510 if (unlikely (status))
2511 return status;
2515 /* ... and stitch them together */
2516 res = _cairo_pdf_surface_new_object (surface);
2517 if (res.id == 0)
2518 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2520 _cairo_output_stream_printf (surface->output,
2521 "%d 0 obj\n"
2522 "<< /FunctionType 3\n"
2523 " /Domain [ %f %f ]\n",
2524 res.id,
2525 stops[0].offset,
2526 stops[n_stops - 1].offset);
2528 _cairo_output_stream_printf (surface->output,
2529 " /Functions [ ");
2530 for (i = 0; i < n_stops-1; i++)
2531 _cairo_output_stream_printf (surface->output,
2532 "%d 0 R ", stops[i].resource.id);
2533 _cairo_output_stream_printf (surface->output,
2534 "]\n");
2536 _cairo_output_stream_printf (surface->output,
2537 " /Bounds [ ");
2538 for (i = 1; i < n_stops-1; i++)
2539 _cairo_output_stream_printf (surface->output,
2540 "%f ", stops[i].offset);
2541 _cairo_output_stream_printf (surface->output,
2542 "]\n");
2544 _cairo_output_stream_printf (surface->output,
2545 " /Encode [ ");
2546 for (i = 1; i < n_stops; i++)
2547 _cairo_output_stream_printf (surface->output,
2548 "0 1 ");
2549 _cairo_output_stream_printf (surface->output,
2550 "]\n");
2552 _cairo_output_stream_printf (surface->output,
2553 ">>\n"
2554 "endobj\n");
2556 *function = res;
2558 return _cairo_output_stream_get_status (surface->output);
2562 static void
2563 calc_gradient_color (cairo_pdf_color_stop_t *new_stop,
2564 cairo_pdf_color_stop_t *stop1,
2565 cairo_pdf_color_stop_t *stop2)
2567 int i;
2568 double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
2570 for (i = 0; i < 4; i++)
2571 new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
2574 #define COLOR_STOP_EPSILON 1e-6
2576 static cairo_status_t
2577 _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
2578 cairo_gradient_pattern_t *pattern,
2579 cairo_pdf_resource_t *color_function,
2580 cairo_pdf_resource_t *alpha_function)
2582 cairo_pdf_color_stop_t *allstops, *stops;
2583 unsigned int n_stops;
2584 unsigned int i;
2585 cairo_bool_t emit_alpha = FALSE;
2586 cairo_status_t status;
2588 color_function->id = 0;
2589 alpha_function->id = 0;
2591 allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t));
2592 if (unlikely (allstops == NULL))
2593 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2595 stops = &allstops[1];
2596 n_stops = pattern->n_stops;
2598 for (i = 0; i < n_stops; i++) {
2599 stops[i].color[0] = pattern->stops[i].color.red;
2600 stops[i].color[1] = pattern->stops[i].color.green;
2601 stops[i].color[2] = pattern->stops[i].color.blue;
2602 stops[i].color[3] = pattern->stops[i].color.alpha;
2603 if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
2604 emit_alpha = TRUE;
2605 stops[i].offset = pattern->stops[i].offset;
2608 if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
2609 pattern->base.extend == CAIRO_EXTEND_REFLECT) {
2610 if (stops[0].offset > COLOR_STOP_EPSILON) {
2611 if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
2612 memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
2613 else
2614 calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
2615 stops = allstops;
2616 n_stops++;
2618 stops[0].offset = 0.0;
2620 if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
2621 if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
2622 memcpy (&stops[n_stops],
2623 &stops[n_stops - 1],
2624 sizeof (cairo_pdf_color_stop_t));
2625 } else {
2626 calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
2628 n_stops++;
2630 stops[n_stops-1].offset = 1.0;
2633 if (n_stops == 2) {
2634 /* no need for stitched function */
2635 status = cairo_pdf_surface_emit_rgb_linear_function (surface,
2636 &stops[0],
2637 &stops[1],
2638 color_function);
2639 if (unlikely (status))
2640 goto BAIL;
2642 if (emit_alpha) {
2643 status = cairo_pdf_surface_emit_alpha_linear_function (surface,
2644 &stops[0],
2645 &stops[1],
2646 alpha_function);
2647 if (unlikely (status))
2648 goto BAIL;
2650 } else {
2651 /* multiple stops: stitch. XXX possible optimization: regularly spaced
2652 * stops do not require stitching. XXX */
2653 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
2654 n_stops,
2655 stops,
2656 FALSE,
2657 color_function);
2658 if (unlikely (status))
2659 goto BAIL;
2661 if (emit_alpha) {
2662 status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
2663 n_stops,
2664 stops,
2665 TRUE,
2666 alpha_function);
2667 if (unlikely (status))
2668 goto BAIL;
2672 BAIL:
2673 free (allstops);
2674 return status;
2677 static cairo_status_t
2678 _cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface,
2679 cairo_gradient_pattern_t *pattern,
2680 cairo_pdf_resource_t *function,
2681 int begin,
2682 int end)
2684 cairo_pdf_resource_t res;
2685 int i;
2687 res = _cairo_pdf_surface_new_object (surface);
2688 if (res.id == 0)
2689 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2691 _cairo_output_stream_printf (surface->output,
2692 "%d 0 obj\n"
2693 "<< /FunctionType 3\n"
2694 " /Domain [ %d %d ]\n",
2695 res.id,
2696 begin,
2697 end);
2699 _cairo_output_stream_printf (surface->output,
2700 " /Functions [ ");
2701 for (i = begin; i < end; i++)
2702 _cairo_output_stream_printf (surface->output,
2703 "%d 0 R ", function->id);
2704 _cairo_output_stream_printf (surface->output,
2705 "]\n");
2707 _cairo_output_stream_printf (surface->output,
2708 " /Bounds [ ");
2709 for (i = begin + 1; i < end; i++)
2710 _cairo_output_stream_printf (surface->output,
2711 "%d ", i);
2712 _cairo_output_stream_printf (surface->output,
2713 "]\n");
2715 _cairo_output_stream_printf (surface->output,
2716 " /Encode [ ");
2717 for (i = begin; i < end; i++) {
2718 if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) {
2719 _cairo_output_stream_printf (surface->output,
2720 "1 0 ");
2721 } else {
2722 _cairo_output_stream_printf (surface->output,
2723 "0 1 ");
2726 _cairo_output_stream_printf (surface->output,
2727 "]\n");
2729 _cairo_output_stream_printf (surface->output,
2730 ">>\n"
2731 "endobj\n");
2733 *function = res;
2735 return _cairo_output_stream_get_status (surface->output);
2738 static cairo_status_t
2739 cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
2740 cairo_pdf_resource_t gstate_resource,
2741 cairo_pdf_resource_t gradient_mask)
2743 cairo_pdf_resource_t smask_resource;
2744 cairo_status_t status;
2746 status = _cairo_pdf_surface_open_stream (surface,
2747 NULL,
2748 surface->compress_content,
2749 " /Type /XObject\n"
2750 " /Subtype /Form\n"
2751 " /FormType 1\n"
2752 " /BBox [ 0 0 %f %f ]\n"
2753 " /Resources\n"
2754 " << /ExtGState\n"
2755 " << /a0 << /ca 1 /CA 1 >>"
2756 " >>\n"
2757 " /Pattern\n"
2758 " << /p%d %d 0 R >>\n"
2759 " >>\n"
2760 " /Group\n"
2761 " << /Type /Group\n"
2762 " /S /Transparency\n"
2763 " /CS /DeviceGray\n"
2764 " >>\n",
2765 surface->width,
2766 surface->height,
2767 gradient_mask.id,
2768 gradient_mask.id);
2769 if (unlikely (status))
2770 return status;
2772 _cairo_output_stream_printf (surface->output,
2773 "q\n"
2774 "/a0 gs\n"
2775 "/Pattern cs /p%d scn\n"
2776 "0 0 %f %f re\n"
2777 "f\n"
2778 "Q\n",
2779 gradient_mask.id,
2780 surface->width,
2781 surface->height);
2783 status = _cairo_pdf_surface_close_stream (surface);
2784 if (unlikely (status))
2785 return status;
2787 smask_resource = _cairo_pdf_surface_new_object (surface);
2788 if (smask_resource.id == 0)
2789 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2791 _cairo_output_stream_printf (surface->output,
2792 "%d 0 obj\n"
2793 "<< /Type /Mask\n"
2794 " /S /Luminosity\n"
2795 " /G %d 0 R\n"
2796 ">>\n"
2797 "endobj\n",
2798 smask_resource.id,
2799 surface->pdf_stream.self.id);
2801 /* Create GState which uses the transparency group as an SMask. */
2802 _cairo_pdf_surface_update_object (surface, gstate_resource);
2804 _cairo_output_stream_printf (surface->output,
2805 "%d 0 obj\n"
2806 "<< /Type /ExtGState\n"
2807 " /SMask %d 0 R\n"
2808 " /ca 1\n"
2809 " /CA 1\n"
2810 " /AIS false\n"
2811 ">>\n"
2812 "endobj\n",
2813 gstate_resource.id,
2814 smask_resource.id);
2816 return _cairo_output_stream_get_status (surface->output);
2819 static cairo_status_t
2820 _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
2821 cairo_pdf_pattern_t *pdf_pattern)
2823 cairo_linear_pattern_t *pattern = (cairo_linear_pattern_t *) pdf_pattern->pattern;
2824 cairo_pdf_resource_t color_function, alpha_function;
2825 double x1, y1, x2, y2;
2826 double _x1, _y1, _x2, _y2;
2827 cairo_matrix_t pat_to_pdf;
2828 cairo_extend_t extend;
2829 cairo_status_t status;
2830 cairo_gradient_pattern_t *gradient = &pattern->base;
2831 double first_stop, last_stop;
2832 int repeat_begin = 0, repeat_end = 1;
2834 assert (pattern->base.n_stops != 0);
2836 extend = cairo_pattern_get_extend (pdf_pattern->pattern);
2838 pat_to_pdf = pattern->base.base.matrix;
2839 status = cairo_matrix_invert (&pat_to_pdf);
2840 /* cairo_pattern_set_matrix ensures the matrix is invertible */
2841 assert (status == CAIRO_STATUS_SUCCESS);
2843 cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
2844 first_stop = gradient->stops[0].offset;
2845 last_stop = gradient->stops[gradient->n_stops - 1].offset;
2847 if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
2848 pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
2849 double dx, dy;
2850 int x_rep = 0, y_rep = 0;
2852 x1 = _cairo_fixed_to_double (pattern->p1.x);
2853 y1 = _cairo_fixed_to_double (pattern->p1.y);
2854 cairo_matrix_transform_point (&pat_to_pdf, &x1, &y1);
2856 x2 = _cairo_fixed_to_double (pattern->p2.x);
2857 y2 = _cairo_fixed_to_double (pattern->p2.y);
2858 cairo_matrix_transform_point (&pat_to_pdf, &x2, &y2);
2860 dx = fabs (x2 - x1);
2861 dy = fabs (y2 - y1);
2862 if (dx > 1e-6)
2863 x_rep = (int) ceil (surface->width/dx);
2864 if (dy > 1e-6)
2865 y_rep = (int) ceil (surface->height/dy);
2867 repeat_end = MAX (x_rep, y_rep);
2868 repeat_begin = -repeat_end;
2869 first_stop = repeat_begin;
2870 last_stop = repeat_end;
2873 /* PDF requires the first and last stop to be the same as the line
2874 * coordinates. For repeating patterns this moves the line
2875 * coordinates out to the begin/end of the repeating function. For
2876 * non repeating patterns this may move the line coordinates in if
2877 * there are not stops at offset 0 and 1. */
2878 x1 = _cairo_fixed_to_double (pattern->p1.x);
2879 y1 = _cairo_fixed_to_double (pattern->p1.y);
2880 x2 = _cairo_fixed_to_double (pattern->p2.x);
2881 y2 = _cairo_fixed_to_double (pattern->p2.y);
2883 _x1 = x1 + (x2 - x1)*first_stop;
2884 _y1 = y1 + (y2 - y1)*first_stop;
2885 _x2 = x1 + (x2 - x1)*last_stop;
2886 _y2 = y1 + (y2 - y1)*last_stop;
2888 x1 = _x1;
2889 x2 = _x2;
2890 y1 = _y1;
2891 y2 = _y2;
2893 /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
2894 * Type 2 function is used by itself without a stitching
2895 * function. Type 2 functions always have the domain [0 1] */
2896 if ((pattern->base.base.extend == CAIRO_EXTEND_NONE ||
2897 pattern->base.base.extend == CAIRO_EXTEND_PAD) &&
2898 gradient->n_stops == 2) {
2899 first_stop = 0.0;
2900 last_stop = 1.0;
2903 status = _cairo_pdf_surface_emit_pattern_stops (surface,
2904 &pattern->base,
2905 &color_function,
2906 &alpha_function);
2907 if (unlikely (status))
2908 return status;
2910 if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
2911 pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
2912 status = _cairo_pdf_surface_emit_repeating_function (surface,
2913 &pattern->base,
2914 &color_function,
2915 repeat_begin,
2916 repeat_end);
2917 if (unlikely (status))
2918 return status;
2920 if (alpha_function.id != 0) {
2921 status = _cairo_pdf_surface_emit_repeating_function (surface,
2922 &pattern->base,
2923 &alpha_function,
2924 repeat_begin,
2925 repeat_end);
2926 if (unlikely (status))
2927 return status;
2931 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
2932 _cairo_output_stream_printf (surface->output,
2933 "%d 0 obj\n"
2934 "<< /Type /Pattern\n"
2935 " /PatternType 2\n"
2936 " /Matrix [ %f %f %f %f %f %f ]\n"
2937 " /Shading\n"
2938 " << /ShadingType 2\n"
2939 " /ColorSpace /DeviceRGB\n"
2940 " /Coords [ %f %f %f %f ]\n"
2941 " /Domain [ %f %f ]\n"
2942 " /Function %d 0 R\n",
2943 pdf_pattern->pattern_res.id,
2944 pat_to_pdf.xx, pat_to_pdf.yx,
2945 pat_to_pdf.xy, pat_to_pdf.yy,
2946 pat_to_pdf.x0, pat_to_pdf.y0,
2947 x1, y1, x2, y2,
2948 first_stop, last_stop,
2949 color_function.id);
2951 if (extend == CAIRO_EXTEND_PAD) {
2952 _cairo_output_stream_printf (surface->output,
2953 " /Extend [ true true ]\n");
2954 } else {
2955 _cairo_output_stream_printf (surface->output,
2956 " /Extend [ false false ]\n");
2959 _cairo_output_stream_printf (surface->output,
2960 " >>\n"
2961 ">>\n"
2962 "endobj\n");
2964 if (alpha_function.id != 0) {
2965 cairo_pdf_resource_t mask_resource;
2967 assert (pdf_pattern->gstate_res.id != 0);
2969 /* Create pattern for SMask. */
2970 mask_resource = _cairo_pdf_surface_new_object (surface);
2971 if (mask_resource.id == 0)
2972 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2974 _cairo_output_stream_printf (surface->output,
2975 "%d 0 obj\n"
2976 "<< /Type /Pattern\n"
2977 " /PatternType 2\n"
2978 " /Matrix [ %f %f %f %f %f %f ]\n"
2979 " /Shading\n"
2980 " << /ShadingType 2\n"
2981 " /ColorSpace /DeviceGray\n"
2982 " /Coords [ %f %f %f %f ]\n"
2983 " /Domain [ %f %f ]\n"
2984 " /Function %d 0 R\n",
2985 mask_resource.id,
2986 pat_to_pdf.xx, pat_to_pdf.yx,
2987 pat_to_pdf.xy, pat_to_pdf.yy,
2988 pat_to_pdf.x0, pat_to_pdf.y0,
2989 x1, y1, x2, y2,
2990 first_stop, last_stop,
2991 alpha_function.id);
2993 if (extend == CAIRO_EXTEND_PAD) {
2994 _cairo_output_stream_printf (surface->output,
2995 " /Extend [ true true ]\n");
2996 } else {
2997 _cairo_output_stream_printf (surface->output,
2998 " /Extend [ false false ]\n");
3001 _cairo_output_stream_printf (surface->output,
3002 " >>\n"
3003 ">>\n"
3004 "endobj\n");
3005 status = _cairo_pdf_surface_add_pattern (surface, mask_resource);
3006 if (unlikely (status))
3007 return status;
3009 status = cairo_pdf_surface_emit_transparency_group (surface,
3010 pdf_pattern->gstate_res,
3011 mask_resource);
3012 if (unlikely (status))
3013 return status;
3016 return _cairo_output_stream_get_status (surface->output);
3019 static cairo_status_t
3020 _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface,
3021 cairo_pdf_pattern_t *pdf_pattern)
3023 cairo_pdf_resource_t color_function, alpha_function;
3024 double x1, y1, x2, y2, r1, r2;
3025 cairo_matrix_t pat_to_pdf;
3026 cairo_extend_t extend;
3027 cairo_status_t status;
3028 cairo_radial_pattern_t *pattern = (cairo_radial_pattern_t *) pdf_pattern->pattern;
3030 assert (pattern->base.n_stops != 0);
3032 extend = cairo_pattern_get_extend (pdf_pattern->pattern);
3034 status = _cairo_pdf_surface_emit_pattern_stops (surface,
3035 &pattern->base,
3036 &color_function,
3037 &alpha_function);
3038 if (unlikely (status))
3039 return status;
3041 pat_to_pdf = pattern->base.base.matrix;
3042 status = cairo_matrix_invert (&pat_to_pdf);
3043 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3044 assert (status == CAIRO_STATUS_SUCCESS);
3046 cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
3047 x1 = _cairo_fixed_to_double (pattern->c1.x);
3048 y1 = _cairo_fixed_to_double (pattern->c1.y);
3049 r1 = _cairo_fixed_to_double (pattern->r1);
3050 x2 = _cairo_fixed_to_double (pattern->c2.x);
3051 y2 = _cairo_fixed_to_double (pattern->c2.y);
3052 r2 = _cairo_fixed_to_double (pattern->r2);
3054 _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
3056 _cairo_output_stream_printf (surface->output,
3057 "%d 0 obj\n"
3058 "<< /Type /Pattern\n"
3059 " /PatternType 2\n"
3060 " /Matrix [ %f %f %f %f %f %f ]\n"
3061 " /Shading\n"
3062 " << /ShadingType 3\n"
3063 " /ColorSpace /DeviceRGB\n"
3064 " /Coords [ %f %f %f %f %f %f ]\n"
3065 " /Function %d 0 R\n",
3066 pdf_pattern->pattern_res.id,
3067 pat_to_pdf.xx, pat_to_pdf.yx,
3068 pat_to_pdf.xy, pat_to_pdf.yy,
3069 pat_to_pdf.x0, pat_to_pdf.y0,
3070 x1, y1, r1, x2, y2, r2,
3071 color_function.id);
3073 if (extend == CAIRO_EXTEND_PAD) {
3074 _cairo_output_stream_printf (surface->output,
3075 " /Extend [ true true ]\n");
3076 } else {
3077 _cairo_output_stream_printf (surface->output,
3078 " /Extend [ false false ]\n");
3081 _cairo_output_stream_printf (surface->output,
3082 " >>\n"
3083 ">>\n"
3084 "endobj\n");
3086 if (alpha_function.id != 0) {
3087 cairo_pdf_resource_t mask_resource;
3089 assert (pdf_pattern->gstate_res.id != 0);
3091 /* Create pattern for SMask. */
3092 mask_resource = _cairo_pdf_surface_new_object (surface);
3093 if (mask_resource.id == 0)
3094 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3096 _cairo_output_stream_printf (surface->output,
3097 "%d 0 obj\n"
3098 "<< /Type /Pattern\n"
3099 " /PatternType 2\n"
3100 " /Matrix [ %f %f %f %f %f %f ]\n"
3101 " /Shading\n"
3102 " << /ShadingType 3\n"
3103 " /ColorSpace /DeviceGray\n"
3104 " /Coords [ %f %f %f %f %f %f ]\n"
3105 " /Function %d 0 R\n",
3106 mask_resource.id,
3107 pat_to_pdf.xx, pat_to_pdf.yx,
3108 pat_to_pdf.xy, pat_to_pdf.yy,
3109 pat_to_pdf.x0, pat_to_pdf.y0,
3110 x1, y1, r1, x2, y2, r2,
3111 alpha_function.id);
3113 if (extend == CAIRO_EXTEND_PAD) {
3114 _cairo_output_stream_printf (surface->output,
3115 " /Extend [ true true ]\n");
3116 } else {
3117 _cairo_output_stream_printf (surface->output,
3118 " /Extend [ false false ]\n");
3121 _cairo_output_stream_printf (surface->output,
3122 " >>\n"
3123 ">>\n"
3124 "endobj\n");
3126 status = cairo_pdf_surface_emit_transparency_group (surface,
3127 pdf_pattern->gstate_res,
3128 mask_resource);
3129 if (unlikely (status))
3130 return status;
3133 return _cairo_output_stream_get_status (surface->output);
3136 static cairo_status_t
3137 _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
3139 double old_width, old_height;
3140 cairo_status_t status;
3142 old_width = surface->width;
3143 old_height = surface->height;
3144 _cairo_pdf_surface_set_size_internal (surface,
3145 pdf_pattern->width,
3146 pdf_pattern->height);
3148 switch (pdf_pattern->pattern->type) {
3149 case CAIRO_PATTERN_TYPE_SOLID:
3150 ASSERT_NOT_REACHED;
3151 status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3152 break;
3154 case CAIRO_PATTERN_TYPE_SURFACE:
3155 status = _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
3156 break;
3158 case CAIRO_PATTERN_TYPE_LINEAR:
3159 status = _cairo_pdf_surface_emit_linear_pattern (surface, pdf_pattern);
3160 break;
3162 case CAIRO_PATTERN_TYPE_RADIAL:
3163 status = _cairo_pdf_surface_emit_radial_pattern (surface, pdf_pattern);
3164 break;
3166 default:
3167 ASSERT_NOT_REACHED;
3168 status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3169 break;
3172 _cairo_pdf_surface_set_size_internal (surface,
3173 old_width,
3174 old_height);
3176 return status;
3179 static cairo_status_t
3180 _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
3181 const cairo_pattern_t *pattern,
3182 cairo_pdf_resource_t pattern_res,
3183 cairo_bool_t is_stroke)
3185 cairo_status_t status;
3186 int alpha;
3187 const cairo_color_t *solid_color = NULL;
3189 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
3190 const cairo_solid_pattern_t *solid = (const cairo_solid_pattern_t *) pattern;
3192 solid_color = &solid->color;
3195 if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
3196 pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
3198 cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
3200 if (gradient->n_stops == 1)
3201 solid_color = &gradient->stops[0].color;
3204 if (solid_color != NULL) {
3205 if (surface->current_pattern_is_solid_color == FALSE ||
3206 surface->current_color_red != solid_color->red ||
3207 surface->current_color_green != solid_color->green ||
3208 surface->current_color_blue != solid_color->blue ||
3209 surface->current_color_is_stroke != is_stroke)
3211 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3212 if (unlikely (status))
3213 return status;
3215 _cairo_output_stream_printf (surface->output,
3216 "%f %f %f ",
3217 solid_color->red,
3218 solid_color->green,
3219 solid_color->blue);
3221 if (is_stroke)
3222 _cairo_output_stream_printf (surface->output, "RG ");
3223 else
3224 _cairo_output_stream_printf (surface->output, "rg ");
3226 surface->current_color_red = solid_color->red;
3227 surface->current_color_green = solid_color->green;
3228 surface->current_color_blue = solid_color->blue;
3229 surface->current_color_is_stroke = is_stroke;
3232 if (surface->current_pattern_is_solid_color == FALSE ||
3233 surface->current_color_alpha != solid_color->alpha)
3235 status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha);
3236 if (unlikely (status))
3237 return status;
3239 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3240 if (unlikely (status))
3241 return status;
3243 _cairo_output_stream_printf (surface->output,
3244 "/a%d gs\n",
3245 alpha);
3246 surface->current_color_alpha = solid_color->alpha;
3249 surface->current_pattern_is_solid_color = TRUE;
3250 } else {
3251 status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
3252 if (unlikely (status))
3253 return status;
3255 status = _cairo_pdf_surface_add_pattern (surface, pattern_res);
3256 if (unlikely (status))
3257 return status;
3259 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3260 if (unlikely (status))
3261 return status;
3263 /* fill-stroke calls select_pattern twice. Don't save if the
3264 * gstate is already saved. */
3265 if (!surface->select_pattern_gstate_saved)
3266 _cairo_output_stream_printf (surface->output, "q ");
3268 if (is_stroke) {
3269 _cairo_output_stream_printf (surface->output,
3270 "/Pattern CS /p%d SCN ",
3271 pattern_res.id);
3272 } else {
3273 _cairo_output_stream_printf (surface->output,
3274 "/Pattern cs /p%d scn ",
3275 pattern_res.id);
3277 _cairo_output_stream_printf (surface->output,
3278 "/a%d gs\n",
3279 alpha);
3280 surface->select_pattern_gstate_saved = TRUE;
3281 surface->current_pattern_is_solid_color = FALSE;
3284 return _cairo_output_stream_get_status (surface->output);
3287 static cairo_int_status_t
3288 _cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
3290 cairo_int_status_t status;
3292 if (surface->select_pattern_gstate_saved) {
3293 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3294 if (unlikely (status))
3295 return status;
3297 _cairo_output_stream_printf (surface->output, "Q\n");
3298 _cairo_pdf_operators_reset (&surface->pdf_operators);
3300 surface->select_pattern_gstate_saved = FALSE;
3302 return CAIRO_STATUS_SUCCESS;
3305 static cairo_int_status_t
3306 _cairo_pdf_surface_show_page (void *abstract_surface)
3308 cairo_pdf_surface_t *surface = abstract_surface;
3309 cairo_int_status_t status;
3311 status = _cairo_pdf_surface_close_content_stream (surface);
3312 if (unlikely (status))
3313 return status;
3315 status = _cairo_pdf_surface_write_page (surface);
3316 if (unlikely (status))
3317 return status;
3319 _cairo_pdf_surface_clear (surface);
3321 return CAIRO_STATUS_SUCCESS;
3324 static cairo_int_status_t
3325 _cairo_pdf_surface_get_extents (void *abstract_surface,
3326 cairo_rectangle_int_t *rectangle)
3328 cairo_pdf_surface_t *surface = abstract_surface;
3330 rectangle->x = 0;
3331 rectangle->y = 0;
3333 /* XXX: The conversion to integers here is pretty bogus, (not to
3334 * mention the arbitrary limitation of width to a short(!). We
3335 * may need to come up with a better interface for get_size.
3337 rectangle->width = (int) ceil (surface->width);
3338 rectangle->height = (int) ceil (surface->height);
3340 return CAIRO_STATUS_SUCCESS;
3343 static cairo_int_status_t
3344 _cairo_pdf_surface_intersect_clip_path (void *abstract_surface,
3345 cairo_path_fixed_t *path,
3346 cairo_fill_rule_t fill_rule,
3347 double tolerance,
3348 cairo_antialias_t antialias)
3350 cairo_pdf_surface_t *surface = abstract_surface;
3351 cairo_int_status_t status;
3353 if (path == NULL) {
3354 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3355 if (unlikely (status))
3356 return status;
3358 _cairo_output_stream_printf (surface->output, "Q q\n");
3359 surface->current_pattern_is_solid_color = FALSE;
3360 _cairo_pdf_operators_reset (&surface->pdf_operators);
3362 return CAIRO_STATUS_SUCCESS;
3365 return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
3368 static void
3369 _cairo_pdf_surface_get_font_options (void *abstract_surface,
3370 cairo_font_options_t *options)
3372 _cairo_font_options_init_default (options);
3374 cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
3375 cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
3376 cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
3379 static cairo_pdf_resource_t
3380 _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface)
3382 cairo_pdf_resource_t info;
3384 info = _cairo_pdf_surface_new_object (surface);
3385 if (info.id == 0)
3386 return info;
3388 _cairo_output_stream_printf (surface->output,
3389 "%d 0 obj\n"
3390 "<< /Creator (cairo %s (http://cairographics.org))\n"
3391 " /Producer (cairo %s (http://cairographics.org))\n"
3392 ">>\n"
3393 "endobj\n",
3394 info.id,
3395 cairo_version_string (),
3396 cairo_version_string ());
3398 return info;
3401 static void
3402 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
3404 cairo_pdf_resource_t page;
3405 int num_pages, i;
3407 _cairo_pdf_surface_update_object (surface, surface->pages_resource);
3408 _cairo_output_stream_printf (surface->output,
3409 "%d 0 obj\n"
3410 "<< /Type /Pages\n"
3411 " /Kids [ ",
3412 surface->pages_resource.id);
3414 num_pages = _cairo_array_num_elements (&surface->pages);
3415 for (i = 0; i < num_pages; i++) {
3416 _cairo_array_copy_element (&surface->pages, i, &page);
3417 _cairo_output_stream_printf (surface->output, "%d 0 R ", page.id);
3420 _cairo_output_stream_printf (surface->output, "]\n");
3421 _cairo_output_stream_printf (surface->output, " /Count %d\n", num_pages);
3424 /* TODO: Figure out which other defaults to be inherited by /Page
3425 * objects. */
3426 _cairo_output_stream_printf (surface->output,
3427 ">>\n"
3428 "endobj\n");
3431 static cairo_status_t
3432 _cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t *surface,
3433 const char *utf8)
3435 uint16_t *utf16 = NULL;
3436 int utf16_len = 0;
3437 cairo_status_t status;
3438 int i;
3440 if (utf8 && *utf8) {
3441 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
3442 if (unlikely (status))
3443 return status;
3446 _cairo_output_stream_printf (surface->output, "<");
3447 if (utf16 == NULL || utf16_len == 0) {
3448 /* According to the "ToUnicode Mapping File Tutorial"
3449 * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
3451 * Glyphs that do not map to a Unicode code point must be
3452 * mapped to 0xfffd "REPLACEMENT CHARACTER".
3454 _cairo_output_stream_printf (surface->output,
3455 "fffd");
3456 } else {
3457 for (i = 0; i < utf16_len; i++)
3458 _cairo_output_stream_printf (surface->output,
3459 "%04x", (int) (utf16[i]));
3461 _cairo_output_stream_printf (surface->output, ">");
3463 if (utf16)
3464 free (utf16);
3466 return CAIRO_STATUS_SUCCESS;
3469 /* Bob Jenkins hash
3471 * Public domain code from:
3472 * http://burtleburtle.net/bob/hash/doobs.html
3475 #define HASH_MIX(a,b,c) \
3477 a -= b; a -= c; a ^= (c>>13); \
3478 b -= c; b -= a; b ^= (a<<8); \
3479 c -= a; c -= b; c ^= (b>>13); \
3480 a -= b; a -= c; a ^= (c>>12); \
3481 b -= c; b -= a; b ^= (a<<16); \
3482 c -= a; c -= b; c ^= (b>>5); \
3483 a -= b; a -= c; a ^= (c>>3); \
3484 b -= c; b -= a; b ^= (a<<10); \
3485 c -= a; c -= b; c ^= (b>>15); \
3488 static uint32_t
3489 _hash_data (const unsigned char *data, int length, uint32_t initval)
3491 uint32_t a, b, c, len;
3493 len = length;
3494 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
3495 c = initval; /* the previous hash value */
3497 while (len >= 12) {
3498 a += (data[0] + ((uint32_t)data[1]<<8) + ((uint32_t)data[2]<<16) + ((uint32_t)data[3]<<24));
3499 b += (data[4] + ((uint32_t)data[5]<<8) + ((uint32_t)data[6]<<16) + ((uint32_t)data[7]<<24));
3500 c += (data[8] + ((uint32_t)data[9]<<8) + ((uint32_t)data[10]<<16)+ ((uint32_t)data[11]<<24));
3501 HASH_MIX (a,b,c);
3502 data += 12;
3503 len -= 12;
3506 c += length;
3507 switch(len) {
3508 case 11: c+= ((uint32_t) data[10] << 24);
3509 case 10: c+= ((uint32_t) data[9] << 16);
3510 case 9 : c+= ((uint32_t) data[8] << 8);
3511 case 8 : b+= ((uint32_t) data[7] << 24);
3512 case 7 : b+= ((uint32_t) data[6] << 16);
3513 case 6 : b+= ((uint32_t) data[5] << 8);
3514 case 5 : b+= data[4];
3515 case 4 : a+= ((uint32_t) data[3] << 24);
3516 case 3 : a+= ((uint32_t) data[2] << 16);
3517 case 2 : a+= ((uint32_t) data[1] << 8);
3518 case 1 : a+= data[0];
3520 HASH_MIX (a,b,c);
3522 return c;
3525 static void
3526 _create_font_subset_tag (cairo_scaled_font_subset_t *font_subset,
3527 const char *font_name,
3528 char *tag)
3530 uint32_t hash;
3531 int i;
3532 long numerator;
3533 ldiv_t d;
3535 hash = _hash_data ((unsigned char *) font_name, strlen(font_name), 0);
3536 hash = _hash_data ((unsigned char *) (font_subset->glyphs),
3537 font_subset->num_glyphs * sizeof(unsigned long), hash);
3539 numerator = abs (hash);
3540 for (i = 0; i < 6; i++) {
3541 d = ldiv (numerator, 26);
3542 numerator = d.quot;
3543 tag[i] = 'A' + d.rem;
3545 tag[i] = 0;
3548 static cairo_int_status_t
3549 _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
3550 cairo_scaled_font_subset_t *font_subset,
3551 cairo_bool_t is_composite,
3552 cairo_pdf_resource_t *stream)
3554 unsigned int i, num_bfchar;
3555 cairo_int_status_t status;
3557 stream->id = 0;
3559 status = _cairo_pdf_surface_open_stream (surface,
3560 NULL,
3561 surface->compress_content,
3562 NULL);
3563 if (unlikely (status))
3564 return status;
3566 _cairo_output_stream_printf (surface->output,
3567 "/CIDInit /ProcSet findresource begin\n"
3568 "12 dict begin\n"
3569 "begincmap\n"
3570 "/CIDSystemInfo\n"
3571 "<< /Registry (Adobe)\n"
3572 " /Ordering (UCS)\n"
3573 " /Supplement 0\n"
3574 ">> def\n"
3575 "/CMapName /Adobe-Identity-UCS def\n"
3576 "/CMapType 2 def\n"
3577 "1 begincodespacerange\n");
3579 if (is_composite) {
3580 _cairo_output_stream_printf (surface->output,
3581 "<0000> <ffff>\n");
3582 } else {
3583 _cairo_output_stream_printf (surface->output,
3584 "<00> <ff>\n");
3587 _cairo_output_stream_printf (surface->output,
3588 "endcodespacerange\n");
3590 num_bfchar = font_subset->num_glyphs - 1;
3592 /* The CMap specification has a limit of 100 characters per beginbfchar operator */
3593 _cairo_output_stream_printf (surface->output,
3594 "%d beginbfchar\n",
3595 num_bfchar > 100 ? 100 : num_bfchar);
3597 for (i = 0; i < num_bfchar; i++) {
3598 if (i != 0 && i % 100 == 0) {
3599 _cairo_output_stream_printf (surface->output,
3600 "endbfchar\n"
3601 "%d beginbfchar\n",
3602 num_bfchar - i > 100 ? 100 : num_bfchar - i);
3604 if (is_composite) {
3605 _cairo_output_stream_printf (surface->output,
3606 "<%04x> ",
3607 i + 1);
3608 } else {
3609 _cairo_output_stream_printf (surface->output,
3610 "<%02x> ",
3611 i + 1);
3613 status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
3614 font_subset->utf8[i + 1]);
3615 if (unlikely (status))
3616 return status;
3618 _cairo_output_stream_printf (surface->output,
3619 "\n");
3621 _cairo_output_stream_printf (surface->output,
3622 "endbfchar\n");
3624 _cairo_output_stream_printf (surface->output,
3625 "endcmap\n"
3626 "CMapName currentdict /CMap defineresource pop\n"
3627 "end\n"
3628 "end\n");
3630 *stream = surface->pdf_stream.self;
3631 return _cairo_pdf_surface_close_stream (surface);
3634 static cairo_status_t
3635 _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
3636 cairo_scaled_font_subset_t *font_subset,
3637 cairo_cff_subset_t *subset)
3639 cairo_pdf_resource_t stream, descriptor, cidfont_dict;
3640 cairo_pdf_resource_t subset_resource, to_unicode_stream;
3641 cairo_pdf_font_t font;
3642 unsigned int i;
3643 cairo_status_t status;
3644 char tag[10];
3646 _create_font_subset_tag (font_subset, subset->ps_name, tag);
3648 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
3649 font_subset->font_id,
3650 font_subset->subset_id);
3651 if (subset_resource.id == 0)
3652 return CAIRO_STATUS_SUCCESS;
3654 status = _cairo_pdf_surface_open_stream (surface,
3655 NULL,
3656 TRUE,
3657 " /Subtype /CIDFontType0C\n");
3658 if (unlikely (status))
3659 return status;
3661 stream = surface->pdf_stream.self;
3662 _cairo_output_stream_write (surface->output,
3663 subset->data, subset->data_length);
3664 status = _cairo_pdf_surface_close_stream (surface);
3665 if (unlikely (status))
3666 return status;
3668 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
3669 font_subset, TRUE,
3670 &to_unicode_stream);
3671 if (_cairo_status_is_error (status))
3672 return status;
3674 descriptor = _cairo_pdf_surface_new_object (surface);
3675 if (descriptor.id == 0)
3676 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3678 _cairo_output_stream_printf (surface->output,
3679 "%d 0 obj\n"
3680 "<< /Type /FontDescriptor\n"
3681 " /FontName /%s+%s\n",
3682 descriptor.id,
3683 tag,
3684 subset->ps_name);
3686 if (subset->font_name) {
3687 _cairo_output_stream_printf (surface->output,
3688 " /FontFamily (%s)\n",
3689 subset->font_name);
3692 _cairo_output_stream_printf (surface->output,
3693 " /Flags 4\n"
3694 " /FontBBox [ %ld %ld %ld %ld ]\n"
3695 " /ItalicAngle 0\n"
3696 " /Ascent %ld\n"
3697 " /Descent %ld\n"
3698 " /CapHeight 500\n"
3699 " /StemV 80\n"
3700 " /StemH 80\n"
3701 " /FontFile3 %u 0 R\n"
3702 ">>\n"
3703 "endobj\n",
3704 subset->x_min,
3705 subset->y_min,
3706 subset->x_max,
3707 subset->y_max,
3708 subset->ascent,
3709 subset->descent,
3710 stream.id);
3712 cidfont_dict = _cairo_pdf_surface_new_object (surface);
3713 if (cidfont_dict.id == 0)
3714 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3716 _cairo_output_stream_printf (surface->output,
3717 "%d 0 obj\n"
3718 "<< /Type /Font\n"
3719 " /Subtype /CIDFontType0\n"
3720 " /BaseFont /%s+%s\n"
3721 " /CIDSystemInfo\n"
3722 " << /Registry (Adobe)\n"
3723 " /Ordering (Identity)\n"
3724 " /Supplement 0\n"
3725 " >>\n"
3726 " /FontDescriptor %d 0 R\n"
3727 " /W [0 [",
3728 cidfont_dict.id,
3729 tag,
3730 subset->ps_name,
3731 descriptor.id);
3733 for (i = 0; i < font_subset->num_glyphs; i++)
3734 _cairo_output_stream_printf (surface->output,
3735 " %d",
3736 subset->widths[i]);
3738 _cairo_output_stream_printf (surface->output,
3739 " ]]\n"
3740 ">>\n"
3741 "endobj\n");
3743 _cairo_pdf_surface_update_object (surface, subset_resource);
3744 _cairo_output_stream_printf (surface->output,
3745 "%d 0 obj\n"
3746 "<< /Type /Font\n"
3747 " /Subtype /Type0\n"
3748 " /BaseFont /%s+%s\n"
3749 " /Encoding /Identity-H\n"
3750 " /DescendantFonts [ %d 0 R]\n",
3751 subset_resource.id,
3752 tag,
3753 subset->ps_name,
3754 cidfont_dict.id);
3756 if (to_unicode_stream.id != 0)
3757 _cairo_output_stream_printf (surface->output,
3758 " /ToUnicode %d 0 R\n",
3759 to_unicode_stream.id);
3761 _cairo_output_stream_printf (surface->output,
3762 ">>\n"
3763 "endobj\n");
3765 font.font_id = font_subset->font_id;
3766 font.subset_id = font_subset->subset_id;
3767 font.subset_resource = subset_resource;
3768 status = _cairo_array_append (&surface->fonts, &font);
3770 return status;
3773 static cairo_status_t
3774 _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
3775 cairo_scaled_font_subset_t *font_subset)
3777 cairo_status_t status;
3778 cairo_cff_subset_t subset;
3779 char name[64];
3781 snprintf (name, sizeof name, "CairoFont-%d-%d",
3782 font_subset->font_id, font_subset->subset_id);
3783 status = _cairo_cff_subset_init (&subset, name, font_subset);
3784 if (unlikely (status))
3785 return status;
3787 status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
3789 _cairo_cff_subset_fini (&subset);
3791 return status;
3794 static cairo_status_t
3795 _cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t *surface,
3796 cairo_scaled_font_subset_t *font_subset)
3798 cairo_status_t status;
3799 cairo_cff_subset_t subset;
3800 char name[64];
3802 snprintf (name, sizeof name, "CairoFont-%d-%d",
3803 font_subset->font_id, font_subset->subset_id);
3804 status = _cairo_cff_fallback_init (&subset, name, font_subset);
3805 if (unlikely (status))
3806 return status;
3808 status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
3810 _cairo_cff_fallback_fini (&subset);
3812 return status;
3815 static cairo_status_t
3816 _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
3817 cairo_scaled_font_subset_t *font_subset,
3818 cairo_type1_subset_t *subset)
3820 cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
3821 cairo_pdf_font_t font;
3822 cairo_status_t status;
3823 unsigned long length;
3824 unsigned int i;
3825 char tag[10];
3827 _create_font_subset_tag (font_subset, subset->base_font, tag);
3829 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
3830 font_subset->font_id,
3831 font_subset->subset_id);
3832 if (subset_resource.id == 0)
3833 return CAIRO_STATUS_SUCCESS;
3835 /* We ignore the zero-trailer and set Length3 to 0. */
3836 length = subset->header_length + subset->data_length;
3837 status = _cairo_pdf_surface_open_stream (surface,
3838 NULL,
3839 TRUE,
3840 " /Length1 %lu\n"
3841 " /Length2 %lu\n"
3842 " /Length3 0\n",
3843 subset->header_length,
3844 subset->data_length);
3845 if (unlikely (status))
3846 return status;
3848 stream = surface->pdf_stream.self;
3849 _cairo_output_stream_write (surface->output, subset->data, length);
3850 status = _cairo_pdf_surface_close_stream (surface);
3851 if (unlikely (status))
3852 return status;
3854 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
3855 font_subset, FALSE,
3856 &to_unicode_stream);
3857 if (_cairo_status_is_error (status))
3858 return status;
3860 descriptor = _cairo_pdf_surface_new_object (surface);
3861 if (descriptor.id == 0)
3862 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3864 _cairo_output_stream_printf (surface->output,
3865 "%d 0 obj\n"
3866 "<< /Type /FontDescriptor\n"
3867 " /FontName /%s+%s\n"
3868 " /Flags 4\n"
3869 " /FontBBox [ %ld %ld %ld %ld ]\n"
3870 " /ItalicAngle 0\n"
3871 " /Ascent %ld\n"
3872 " /Descent %ld\n"
3873 " /CapHeight 500\n"
3874 " /StemV 80\n"
3875 " /StemH 80\n"
3876 " /FontFile %u 0 R\n"
3877 ">>\n"
3878 "endobj\n",
3879 descriptor.id,
3880 tag,
3881 subset->base_font,
3882 subset->x_min,
3883 subset->y_min,
3884 subset->x_max,
3885 subset->y_max,
3886 subset->ascent,
3887 subset->descent,
3888 stream.id);
3890 _cairo_pdf_surface_update_object (surface, subset_resource);
3891 _cairo_output_stream_printf (surface->output,
3892 "%d 0 obj\n"
3893 "<< /Type /Font\n"
3894 " /Subtype /Type1\n"
3895 " /BaseFont /%s+%s\n"
3896 " /FirstChar 0\n"
3897 " /LastChar %d\n"
3898 " /FontDescriptor %d 0 R\n"
3899 " /Widths [",
3900 subset_resource.id,
3901 tag,
3902 subset->base_font,
3903 font_subset->num_glyphs - 1,
3904 descriptor.id);
3906 for (i = 0; i < font_subset->num_glyphs; i++)
3907 _cairo_output_stream_printf (surface->output,
3908 " %d",
3909 subset->widths[i]);
3911 _cairo_output_stream_printf (surface->output,
3912 " ]\n");
3914 if (to_unicode_stream.id != 0)
3915 _cairo_output_stream_printf (surface->output,
3916 " /ToUnicode %d 0 R\n",
3917 to_unicode_stream.id);
3919 _cairo_output_stream_printf (surface->output,
3920 ">>\n"
3921 "endobj\n");
3923 font.font_id = font_subset->font_id;
3924 font.subset_id = font_subset->subset_id;
3925 font.subset_resource = subset_resource;
3926 return _cairo_array_append (&surface->fonts, &font);
3929 #if CAIRO_HAS_FT_FONT
3930 static cairo_status_t
3931 _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
3932 cairo_scaled_font_subset_t *font_subset)
3934 cairo_status_t status;
3935 cairo_type1_subset_t subset;
3936 char name[64];
3938 snprintf (name, sizeof name, "CairoFont-%d-%d",
3939 font_subset->font_id, font_subset->subset_id);
3940 status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE);
3941 if (unlikely (status))
3942 return status;
3944 status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
3946 _cairo_type1_subset_fini (&subset);
3947 return status;
3949 #endif
3951 static cairo_status_t
3952 _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
3953 cairo_scaled_font_subset_t *font_subset)
3955 cairo_status_t status;
3956 cairo_type1_subset_t subset;
3957 char name[64];
3959 snprintf (name, sizeof name, "CairoFont-%d-%d",
3960 font_subset->font_id, font_subset->subset_id);
3961 status = _cairo_type1_fallback_init_binary (&subset, name, font_subset);
3962 if (unlikely (status))
3963 return status;
3965 status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
3967 _cairo_type1_fallback_fini (&subset);
3968 return status;
3971 #define PDF_UNITS_PER_EM 1000
3973 static cairo_status_t
3974 _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
3975 cairo_scaled_font_subset_t *font_subset)
3977 cairo_pdf_resource_t stream, descriptor, cidfont_dict;
3978 cairo_pdf_resource_t subset_resource, to_unicode_stream;
3979 cairo_status_t status;
3980 cairo_pdf_font_t font;
3981 cairo_truetype_subset_t subset;
3982 unsigned int i;
3983 char tag[10];
3985 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
3986 font_subset->font_id,
3987 font_subset->subset_id);
3988 if (subset_resource.id == 0)
3989 return CAIRO_STATUS_SUCCESS;
3991 status = _cairo_truetype_subset_init (&subset, font_subset);
3992 if (unlikely (status))
3993 return status;
3995 _create_font_subset_tag (font_subset, subset.ps_name, tag);
3997 status = _cairo_pdf_surface_open_stream (surface,
3998 NULL,
3999 TRUE,
4000 " /Length1 %lu\n",
4001 subset.data_length);
4002 if (unlikely (status)) {
4003 _cairo_truetype_subset_fini (&subset);
4004 return status;
4007 stream = surface->pdf_stream.self;
4008 _cairo_output_stream_write (surface->output,
4009 subset.data, subset.data_length);
4010 status = _cairo_pdf_surface_close_stream (surface);
4011 if (unlikely (status)) {
4012 _cairo_truetype_subset_fini (&subset);
4013 return status;
4016 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
4017 font_subset, TRUE,
4018 &to_unicode_stream);
4019 if (_cairo_status_is_error (status)) {
4020 _cairo_truetype_subset_fini (&subset);
4021 return status;
4024 descriptor = _cairo_pdf_surface_new_object (surface);
4025 if (descriptor.id == 0) {
4026 _cairo_truetype_subset_fini (&subset);
4027 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4030 _cairo_output_stream_printf (surface->output,
4031 "%d 0 obj\n"
4032 "<< /Type /FontDescriptor\n"
4033 " /FontName /%s+%s\n",
4034 descriptor.id,
4035 tag,
4036 subset.ps_name);
4038 if (subset.font_name) {
4039 _cairo_output_stream_printf (surface->output,
4040 " /FontFamily (%s)\n",
4041 subset.font_name);
4044 _cairo_output_stream_printf (surface->output,
4045 " /Flags 4\n"
4046 " /FontBBox [ %ld %ld %ld %ld ]\n"
4047 " /ItalicAngle 0\n"
4048 " /Ascent %ld\n"
4049 " /Descent %ld\n"
4050 " /CapHeight %ld\n"
4051 " /StemV 80\n"
4052 " /StemH 80\n"
4053 " /FontFile2 %u 0 R\n"
4054 ">>\n"
4055 "endobj\n",
4056 (long)(subset.x_min*PDF_UNITS_PER_EM),
4057 (long)(subset.y_min*PDF_UNITS_PER_EM),
4058 (long)(subset.x_max*PDF_UNITS_PER_EM),
4059 (long)(subset.y_max*PDF_UNITS_PER_EM),
4060 (long)(subset.ascent*PDF_UNITS_PER_EM),
4061 (long)(subset.descent*PDF_UNITS_PER_EM),
4062 (long)(subset.y_max*PDF_UNITS_PER_EM),
4063 stream.id);
4065 cidfont_dict = _cairo_pdf_surface_new_object (surface);
4066 if (cidfont_dict.id == 0) {
4067 _cairo_truetype_subset_fini (&subset);
4068 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4071 _cairo_output_stream_printf (surface->output,
4072 "%d 0 obj\n"
4073 "<< /Type /Font\n"
4074 " /Subtype /CIDFontType2\n"
4075 " /BaseFont /%s+%s\n"
4076 " /CIDSystemInfo\n"
4077 " << /Registry (Adobe)\n"
4078 " /Ordering (Identity)\n"
4079 " /Supplement 0\n"
4080 " >>\n"
4081 " /FontDescriptor %d 0 R\n"
4082 " /W [0 [",
4083 cidfont_dict.id,
4084 tag,
4085 subset.ps_name,
4086 descriptor.id);
4088 for (i = 0; i < font_subset->num_glyphs; i++)
4089 _cairo_output_stream_printf (surface->output,
4090 " %ld",
4091 (long)(subset.widths[i]*PDF_UNITS_PER_EM));
4093 _cairo_output_stream_printf (surface->output,
4094 " ]]\n"
4095 ">>\n"
4096 "endobj\n");
4098 _cairo_pdf_surface_update_object (surface, subset_resource);
4099 _cairo_output_stream_printf (surface->output,
4100 "%d 0 obj\n"
4101 "<< /Type /Font\n"
4102 " /Subtype /Type0\n"
4103 " /BaseFont /%s+%s\n"
4104 " /Encoding /Identity-H\n"
4105 " /DescendantFonts [ %d 0 R]\n",
4106 subset_resource.id,
4107 tag,
4108 subset.ps_name,
4109 cidfont_dict.id);
4111 if (to_unicode_stream.id != 0)
4112 _cairo_output_stream_printf (surface->output,
4113 " /ToUnicode %d 0 R\n",
4114 to_unicode_stream.id);
4116 _cairo_output_stream_printf (surface->output,
4117 ">>\n"
4118 "endobj\n");
4120 font.font_id = font_subset->font_id;
4121 font.subset_id = font_subset->subset_id;
4122 font.subset_resource = subset_resource;
4123 status = _cairo_array_append (&surface->fonts, &font);
4125 _cairo_truetype_subset_fini (&subset);
4127 return status;
4130 static cairo_status_t
4131 _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
4132 cairo_output_stream_t *stream)
4134 uint8_t *byte, output_byte;
4135 int row, col, num_cols;
4137 /* The only image type supported by Type 3 fonts are 1-bit image
4138 * masks */
4139 assert (image->format == CAIRO_FORMAT_A1);
4141 _cairo_output_stream_printf (stream,
4142 "BI\n"
4143 "/IM true\n"
4144 "/W %d\n"
4145 "/H %d\n"
4146 "/BPC 1\n"
4147 "/D [1 0]\n",
4148 image->width,
4149 image->height);
4151 _cairo_output_stream_printf (stream,
4152 "ID ");
4154 num_cols = (image->width + 7) / 8;
4155 for (row = 0; row < image->height; row++) {
4156 byte = image->data + row * image->stride;
4157 for (col = 0; col < num_cols; col++) {
4158 output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
4159 _cairo_output_stream_write (stream, &output_byte, 1);
4160 byte++;
4164 _cairo_output_stream_printf (stream,
4165 "\nEI\n");
4167 return _cairo_output_stream_get_status (stream);
4170 static cairo_status_t
4171 _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
4172 void *closure)
4174 cairo_pdf_surface_t *surface = closure;
4175 cairo_status_t status = CAIRO_STATUS_SUCCESS;
4176 cairo_status_t status2;
4177 unsigned int i;
4178 cairo_surface_t *type3_surface;
4179 cairo_output_stream_t *null_stream;
4181 null_stream = _cairo_null_stream_create ();
4182 type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
4183 null_stream,
4184 _cairo_pdf_emit_imagemask,
4185 surface->font_subsets);
4186 if (unlikely (type3_surface->status)) {
4187 status2 = _cairo_output_stream_destroy (null_stream);
4188 return type3_surface->status;
4191 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
4192 _cairo_pdf_surface_add_font,
4193 surface);
4195 for (i = 0; i < font_subset->num_glyphs; i++) {
4196 status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
4197 font_subset->glyphs[i]);
4198 if (unlikely (status))
4199 break;
4202 cairo_surface_destroy (type3_surface);
4203 status2 = _cairo_output_stream_destroy (null_stream);
4204 if (status == CAIRO_STATUS_SUCCESS)
4205 status = status2;
4207 return status;
4210 static cairo_status_t
4211 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
4212 cairo_scaled_font_subset_t *font_subset)
4214 cairo_status_t status = CAIRO_STATUS_SUCCESS;
4215 cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
4216 cairo_pdf_font_t font;
4217 double *widths;
4218 unsigned int i;
4219 cairo_box_t font_bbox = {{0,0},{0,0}};
4220 cairo_box_t bbox = {{0,0},{0,0}};
4221 cairo_surface_t *type3_surface;
4223 if (font_subset->num_glyphs == 0)
4224 return CAIRO_STATUS_SUCCESS;
4226 subset_resource = _cairo_pdf_surface_get_font_resource (surface,
4227 font_subset->font_id,
4228 font_subset->subset_id);
4229 if (subset_resource.id == 0)
4230 return CAIRO_STATUS_SUCCESS;
4232 glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
4233 if (unlikely (glyphs == NULL))
4234 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4236 widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
4237 if (unlikely (widths == NULL)) {
4238 free (glyphs);
4239 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4242 _cairo_pdf_group_resources_clear (&surface->resources);
4243 type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
4244 NULL,
4245 _cairo_pdf_emit_imagemask,
4246 surface->font_subsets);
4247 if (unlikely (type3_surface->status)) {
4248 free (glyphs);
4249 free (widths);
4250 return type3_surface->status;
4253 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
4254 _cairo_pdf_surface_add_font,
4255 surface);
4257 for (i = 0; i < font_subset->num_glyphs; i++) {
4258 status = _cairo_pdf_surface_open_stream (surface,
4259 NULL,
4260 surface->compress_content,
4261 NULL);
4262 if (unlikely (status))
4263 break;
4265 glyphs[i] = surface->pdf_stream.self;
4266 status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
4267 surface->output,
4268 font_subset->glyphs[i],
4269 &bbox,
4270 &widths[i]);
4271 if (unlikely (status))
4272 break;
4274 status = _cairo_pdf_surface_close_stream (surface);
4275 if (unlikely (status))
4276 break;
4278 if (i == 0) {
4279 font_bbox.p1.x = bbox.p1.x;
4280 font_bbox.p1.y = bbox.p1.y;
4281 font_bbox.p2.x = bbox.p2.x;
4282 font_bbox.p2.y = bbox.p2.y;
4283 } else {
4284 if (bbox.p1.x < font_bbox.p1.x)
4285 font_bbox.p1.x = bbox.p1.x;
4286 if (bbox.p1.y < font_bbox.p1.y)
4287 font_bbox.p1.y = bbox.p1.y;
4288 if (bbox.p2.x > font_bbox.p2.x)
4289 font_bbox.p2.x = bbox.p2.x;
4290 if (bbox.p2.y > font_bbox.p2.y)
4291 font_bbox.p2.y = bbox.p2.y;
4294 cairo_surface_destroy (type3_surface);
4295 if (unlikely (status)) {
4296 free (glyphs);
4297 free (widths);
4298 return status;
4301 encoding = _cairo_pdf_surface_new_object (surface);
4302 if (encoding.id == 0) {
4303 free (glyphs);
4304 free (widths);
4305 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4308 _cairo_output_stream_printf (surface->output,
4309 "%d 0 obj\n"
4310 "<< /Type /Encoding\n"
4311 " /Differences [0", encoding.id);
4312 for (i = 0; i < font_subset->num_glyphs; i++)
4313 _cairo_output_stream_printf (surface->output,
4314 " /%d", i);
4315 _cairo_output_stream_printf (surface->output,
4316 "]\n"
4317 ">>\n"
4318 "endobj\n");
4320 char_procs = _cairo_pdf_surface_new_object (surface);
4321 if (char_procs.id == 0) {
4322 free (glyphs);
4323 free (widths);
4324 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4327 _cairo_output_stream_printf (surface->output,
4328 "%d 0 obj\n"
4329 "<<\n", char_procs.id);
4330 for (i = 0; i < font_subset->num_glyphs; i++)
4331 _cairo_output_stream_printf (surface->output,
4332 " /%d %d 0 R\n",
4333 i, glyphs[i].id);
4334 _cairo_output_stream_printf (surface->output,
4335 ">>\n"
4336 "endobj\n");
4338 free (glyphs);
4340 status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
4341 font_subset, FALSE,
4342 &to_unicode_stream);
4343 if (_cairo_status_is_error (status)) {
4344 free (widths);
4345 return status;
4348 _cairo_pdf_surface_update_object (surface, subset_resource);
4349 _cairo_output_stream_printf (surface->output,
4350 "%d 0 obj\n"
4351 "<< /Type /Font\n"
4352 " /Subtype /Type3\n"
4353 " /FontBBox [%f %f %f %f]\n"
4354 " /FontMatrix [ 1 0 0 1 0 0 ]\n"
4355 " /Encoding %d 0 R\n"
4356 " /CharProcs %d 0 R\n"
4357 " /FirstChar 0\n"
4358 " /LastChar %d\n",
4359 subset_resource.id,
4360 _cairo_fixed_to_double (font_bbox.p1.x),
4361 - _cairo_fixed_to_double (font_bbox.p2.y),
4362 _cairo_fixed_to_double (font_bbox.p2.x),
4363 - _cairo_fixed_to_double (font_bbox.p1.y),
4364 encoding.id,
4365 char_procs.id,
4366 font_subset->num_glyphs - 1);
4368 _cairo_output_stream_printf (surface->output,
4369 " /Widths [");
4370 for (i = 0; i < font_subset->num_glyphs; i++)
4371 _cairo_output_stream_printf (surface->output, " %f", widths[i]);
4372 _cairo_output_stream_printf (surface->output,
4373 "]\n");
4374 free (widths);
4376 _cairo_output_stream_printf (surface->output,
4377 " /Resources\n");
4378 _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
4380 if (to_unicode_stream.id != 0)
4381 _cairo_output_stream_printf (surface->output,
4382 " /ToUnicode %d 0 R\n",
4383 to_unicode_stream.id);
4385 _cairo_output_stream_printf (surface->output,
4386 ">>\n"
4387 "endobj\n");
4389 font.font_id = font_subset->font_id;
4390 font.subset_id = font_subset->subset_id;
4391 font.subset_resource = subset_resource;
4392 return _cairo_array_append (&surface->fonts, &font);
4395 static cairo_status_t
4396 _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
4397 void *closure)
4399 cairo_pdf_surface_t *surface = closure;
4400 cairo_status_t status;
4402 if (font_subset->is_composite) {
4403 status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
4404 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4405 return status;
4407 status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
4408 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4409 return status;
4411 status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
4412 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4413 return status;
4414 } else {
4415 #if CAIRO_HAS_FT_FONT
4416 status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
4417 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4418 return status;
4419 #endif
4421 status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
4422 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4423 return status;
4427 ASSERT_NOT_REACHED;
4428 return CAIRO_STATUS_SUCCESS;
4431 static cairo_status_t
4432 _cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
4433 void *closure)
4435 cairo_pdf_surface_t *surface = closure;
4436 cairo_status_t status;
4438 status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
4439 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4440 return status;
4442 ASSERT_NOT_REACHED;
4443 return CAIRO_STATUS_SUCCESS;
4446 static cairo_status_t
4447 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
4449 cairo_status_t status;
4451 status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
4452 _cairo_pdf_surface_analyze_user_font_subset,
4453 surface);
4454 if (unlikely (status))
4455 goto BAIL;
4457 status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
4458 _cairo_pdf_surface_emit_unscaled_font_subset,
4459 surface);
4460 if (unlikely (status))
4461 goto BAIL;
4463 status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
4464 _cairo_pdf_surface_emit_scaled_font_subset,
4465 surface);
4466 if (unlikely (status))
4467 goto BAIL;
4469 status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
4470 _cairo_pdf_surface_emit_scaled_font_subset,
4471 surface);
4473 BAIL:
4474 _cairo_scaled_font_subsets_destroy (surface->font_subsets);
4475 surface->font_subsets = NULL;
4477 return status;
4480 static cairo_pdf_resource_t
4481 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface)
4483 cairo_pdf_resource_t catalog;
4485 catalog = _cairo_pdf_surface_new_object (surface);
4486 if (catalog.id == 0)
4487 return catalog;
4489 _cairo_output_stream_printf (surface->output,
4490 "%d 0 obj\n"
4491 "<< /Type /Catalog\n"
4492 " /Pages %d 0 R\n"
4493 ">>\n"
4494 "endobj\n",
4495 catalog.id,
4496 surface->pages_resource.id);
4498 return catalog;
4501 static long
4502 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
4504 cairo_pdf_object_t *object;
4505 int num_objects, i;
4506 long offset;
4507 char buffer[11];
4509 num_objects = _cairo_array_num_elements (&surface->objects);
4511 offset = _cairo_output_stream_get_position (surface->output);
4512 _cairo_output_stream_printf (surface->output,
4513 "xref\n"
4514 "%d %d\n",
4515 0, num_objects + 1);
4517 _cairo_output_stream_printf (surface->output,
4518 "0000000000 65535 f \n");
4519 for (i = 0; i < num_objects; i++) {
4520 object = _cairo_array_index (&surface->objects, i);
4521 snprintf (buffer, sizeof buffer, "%010ld", object->offset);
4522 _cairo_output_stream_printf (surface->output,
4523 "%s 00000 n \n", buffer);
4526 return offset;
4529 static cairo_status_t
4530 _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
4531 cairo_pdf_smask_group_t *group)
4533 cairo_pdf_resource_t mask_group;
4534 cairo_pdf_resource_t smask;
4535 cairo_pdf_smask_group_t *smask_group;
4536 cairo_pdf_resource_t pattern_res, gstate_res;
4537 cairo_status_t status;
4539 /* Create mask group */
4540 status = _cairo_pdf_surface_open_group (surface, NULL);
4541 if (unlikely (status))
4542 return status;
4544 pattern_res.id = 0;
4545 gstate_res.id = 0;
4546 status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, NULL,
4547 &pattern_res, &gstate_res);
4548 if (unlikely (status))
4549 return status;
4551 if (gstate_res.id != 0) {
4552 smask_group = _cairo_pdf_surface_create_smask_group (surface);
4553 if (unlikely (smask_group == NULL))
4554 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4556 smask_group->operation = PDF_PAINT;
4557 smask_group->source = cairo_pattern_reference (group->mask);
4558 smask_group->source_res = pattern_res;
4559 status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
4560 if (unlikely (status)) {
4561 _cairo_pdf_smask_group_destroy (smask_group);
4562 return status;
4565 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
4566 if (unlikely (status))
4567 return status;
4569 status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
4570 if (unlikely (status))
4571 return status;
4573 _cairo_output_stream_printf (surface->output,
4574 "q /s%d gs /x%d Do Q\n",
4575 gstate_res.id,
4576 smask_group->group_res.id);
4577 } else {
4578 status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE);
4579 if (unlikely (status))
4580 return status;
4582 _cairo_output_stream_printf (surface->output,
4583 "0 0 %f %f re f\n",
4584 surface->width, surface->height);
4586 status = _cairo_pdf_surface_unselect_pattern (surface);
4587 if (unlikely (status))
4588 return status;
4591 status = _cairo_pdf_surface_close_group (surface, &mask_group);
4592 if (unlikely (status))
4593 return status;
4595 /* Create source group */
4596 status = _cairo_pdf_surface_open_group (surface, &group->source_res);
4597 if (unlikely (status))
4598 return status;
4600 pattern_res.id = 0;
4601 gstate_res.id = 0;
4602 status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, NULL,
4603 &pattern_res, &gstate_res);
4604 if (unlikely (status))
4605 return status;
4607 if (gstate_res.id != 0) {
4608 smask_group = _cairo_pdf_surface_create_smask_group (surface);
4609 if (unlikely (smask_group == NULL))
4610 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4612 smask_group->operation = PDF_PAINT;
4613 smask_group->source = cairo_pattern_reference (group->source);
4614 smask_group->source_res = pattern_res;
4615 status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
4616 if (unlikely (status)) {
4617 _cairo_pdf_smask_group_destroy (smask_group);
4618 return status;
4621 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
4622 if (unlikely (status))
4623 return status;
4625 status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
4626 if (unlikely (status))
4627 return status;
4629 _cairo_output_stream_printf (surface->output,
4630 "q /s%d gs /x%d Do Q\n",
4631 gstate_res.id,
4632 smask_group->group_res.id);
4633 } else {
4634 status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE);
4635 if (unlikely (status))
4636 return status;
4638 _cairo_output_stream_printf (surface->output,
4639 "0 0 %f %f re f\n",
4640 surface->width, surface->height);
4642 status = _cairo_pdf_surface_unselect_pattern (surface);
4643 if (unlikely (status))
4644 return status;
4647 status = _cairo_pdf_surface_close_group (surface, NULL);
4648 if (unlikely (status))
4649 return status;
4651 /* Create an smask based on the alpha component of mask_group */
4652 smask = _cairo_pdf_surface_new_object (surface);
4653 if (smask.id == 0)
4654 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4656 _cairo_output_stream_printf (surface->output,
4657 "%d 0 obj\n"
4658 "<< /Type /Mask\n"
4659 " /S /Alpha\n"
4660 " /G %d 0 R\n"
4661 ">>\n"
4662 "endobj\n",
4663 smask.id,
4664 mask_group.id);
4666 /* Create a GState that uses the smask */
4667 _cairo_pdf_surface_update_object (surface, group->group_res);
4668 _cairo_output_stream_printf (surface->output,
4669 "%d 0 obj\n"
4670 "<< /Type /ExtGState\n"
4671 " /SMask %d 0 R\n"
4672 " /ca 1\n"
4673 " /CA 1\n"
4674 " /AIS false\n"
4675 ">>\n"
4676 "endobj\n",
4677 group->group_res.id,
4678 smask.id);
4680 return _cairo_output_stream_get_status (surface->output);
4683 static cairo_status_t
4684 _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
4685 cairo_pdf_smask_group_t *group)
4687 double old_width, old_height;
4688 cairo_status_t status;
4690 old_width = surface->width;
4691 old_height = surface->height;
4692 _cairo_pdf_surface_set_size_internal (surface,
4693 group->width,
4694 group->height);
4695 /* _mask is a special case that requires two groups - source
4696 * and mask as well as a smask and gstate dictionary */
4697 if (group->operation == PDF_MASK) {
4698 status = _cairo_pdf_surface_write_mask_group (surface, group);
4699 goto RESTORE_SIZE;
4702 status = _cairo_pdf_surface_open_group (surface, &group->group_res);
4703 if (unlikely (status))
4704 return status;
4706 status = _cairo_pdf_surface_select_pattern (surface,
4707 group->source,
4708 group->source_res,
4709 group->operation == PDF_STROKE);
4710 if (unlikely (status))
4711 return status;
4713 switch (group->operation) {
4714 case PDF_PAINT:
4715 _cairo_output_stream_printf (surface->output,
4716 "0 0 %f %f re f\n",
4717 surface->width, surface->height);
4718 break;
4719 case PDF_MASK:
4720 ASSERT_NOT_REACHED;
4721 break;
4722 case PDF_FILL:
4723 status = _cairo_pdf_operators_fill (&surface->pdf_operators,
4724 &group->path,
4725 group->fill_rule);
4726 break;
4727 case PDF_STROKE:
4728 status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
4729 &group->path,
4730 group->style,
4731 &group->ctm,
4732 &group->ctm_inverse);
4733 break;
4734 case PDF_SHOW_GLYPHS:
4735 status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
4736 group->utf8, group->utf8_len,
4737 group->glyphs, group->num_glyphs,
4738 group->clusters, group->num_clusters,
4739 group->cluster_flags,
4740 group->scaled_font);
4741 break;
4743 if (unlikely (status))
4744 return status;
4746 status = _cairo_pdf_surface_unselect_pattern (surface);
4747 if (unlikely (status))
4748 return status;
4750 status = _cairo_pdf_surface_close_group (surface, NULL);
4752 RESTORE_SIZE:
4753 _cairo_pdf_surface_set_size_internal (surface,
4754 old_width,
4755 old_height);
4757 return status;
4760 static cairo_status_t
4761 _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface)
4763 cairo_pdf_pattern_t pattern;
4764 cairo_pdf_smask_group_t *group;
4765 cairo_pdf_source_surface_t src_surface;
4766 int pattern_index, group_index, surface_index;
4767 cairo_status_t status;
4769 /* Writing out PDF_MASK groups will cause additional smask groups
4770 * to be appended to surface->smask_groups. Additional patterns
4771 * may also be appended to surface->patterns.
4773 * Writing meta surface patterns will cause additional patterns
4774 * and groups to be appended.
4776 pattern_index = 0;
4777 group_index = 0;
4778 surface_index = 0;
4779 while ((pattern_index < _cairo_array_num_elements (&surface->page_patterns)) ||
4780 (group_index < _cairo_array_num_elements (&surface->smask_groups)))
4782 for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) {
4783 _cairo_array_copy_element (&surface->smask_groups, group_index, &group);
4784 status = _cairo_pdf_surface_write_smask_group (surface, group);
4785 if (unlikely (status))
4786 return status;
4789 for (; pattern_index < _cairo_array_num_elements (&surface->page_patterns); pattern_index++) {
4790 _cairo_array_copy_element (&surface->page_patterns, pattern_index, &pattern);
4791 status = _cairo_pdf_surface_emit_pattern (surface, &pattern);
4792 if (unlikely (status))
4793 return status;
4796 for (; surface_index < _cairo_array_num_elements (&surface->page_surfaces); surface_index++) {
4797 _cairo_array_copy_element (&surface->page_surfaces, surface_index, &src_surface);
4798 status = _cairo_pdf_surface_emit_surface (surface, &src_surface);
4799 if (unlikely (status))
4800 return status;
4804 return CAIRO_STATUS_SUCCESS;
4807 static cairo_status_t
4808 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
4810 cairo_pdf_resource_t page, knockout, res;
4811 cairo_status_t status;
4812 int i, len;
4814 _cairo_pdf_group_resources_clear (&surface->resources);
4815 if (surface->has_fallback_images) {
4816 status = _cairo_pdf_surface_open_knockout_group (surface);
4817 if (unlikely (status))
4818 return status;
4820 len = _cairo_array_num_elements (&surface->knockout_group);
4821 for (i = 0; i < len; i++) {
4822 _cairo_array_copy_element (&surface->knockout_group, i, &res);
4823 _cairo_output_stream_printf (surface->output,
4824 "/x%d Do\n",
4825 res.id);
4826 status = _cairo_pdf_surface_add_xobject (surface, res);
4827 if (unlikely (status))
4828 return status;
4830 _cairo_output_stream_printf (surface->output,
4831 "/x%d Do\n",
4832 surface->content.id);
4833 status = _cairo_pdf_surface_add_xobject (surface, surface->content);
4834 if (unlikely (status))
4835 return status;
4837 status = _cairo_pdf_surface_close_group (surface, &knockout);
4838 if (unlikely (status))
4839 return status;
4841 _cairo_pdf_group_resources_clear (&surface->resources);
4842 status = _cairo_pdf_surface_open_content_stream (surface, NULL, FALSE);
4843 if (unlikely (status))
4844 return status;
4846 _cairo_output_stream_printf (surface->output,
4847 "/x%d Do\n",
4848 knockout.id);
4849 status = _cairo_pdf_surface_add_xobject (surface, knockout);
4850 if (unlikely (status))
4851 return status;
4853 status = _cairo_pdf_surface_close_content_stream (surface);
4854 if (unlikely (status))
4855 return status;
4858 page = _cairo_pdf_surface_new_object (surface);
4859 if (page.id == 0)
4860 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4862 _cairo_output_stream_printf (surface->output,
4863 "%d 0 obj\n"
4864 "<< /Type /Page\n"
4865 " /Parent %d 0 R\n"
4866 " /MediaBox [ 0 0 %f %f ]\n"
4867 " /Contents %d 0 R\n"
4868 " /Group <<\n"
4869 " /Type /Group\n"
4870 " /S /Transparency\n"
4871 " /CS /DeviceRGB\n"
4872 " >>\n"
4873 " /Resources %d 0 R\n"
4874 ">>\n"
4875 "endobj\n",
4876 page.id,
4877 surface->pages_resource.id,
4878 surface->width,
4879 surface->height,
4880 surface->content.id,
4881 surface->content_resources.id);
4883 status = _cairo_array_append (&surface->pages, &page);
4884 if (unlikely (status))
4885 return status;
4887 status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface);
4888 if (unlikely (status))
4889 return status;
4891 return CAIRO_STATUS_SUCCESS;
4894 static cairo_int_status_t
4895 _cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t *surface,
4896 cairo_surface_pattern_t *pattern)
4898 cairo_image_surface_t *image;
4899 void *image_extra;
4900 cairo_int_status_t status;
4901 cairo_image_transparency_t transparency;
4903 status = _cairo_surface_acquire_source_image (pattern->surface,
4904 &image,
4905 &image_extra);
4906 if (unlikely (status))
4907 return status;
4909 if (image->base.status)
4910 return image->base.status;
4912 transparency = _cairo_image_analyze_transparency (image);
4913 if (transparency == CAIRO_IMAGE_IS_OPAQUE)
4914 status = CAIRO_STATUS_SUCCESS;
4915 else
4916 status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
4918 _cairo_surface_release_source_image (pattern->surface, image, image_extra);
4920 return status;
4923 static cairo_bool_t
4924 _surface_pattern_supported (cairo_surface_pattern_t *pattern)
4926 cairo_extend_t extend;
4928 if (_cairo_surface_is_meta (pattern->surface))
4929 return TRUE;
4931 if (pattern->surface->backend->acquire_source_image == NULL)
4932 return FALSE;
4934 /* Does an ALPHA-only source surface even make sense? Maybe, but I
4935 * don't think it's worth the extra code to support it. */
4937 /* XXX: Need to write this function here...
4938 content = cairo_surface_get_content (pattern->surface);
4939 if (content == CAIRO_CONTENT_ALPHA)
4940 return FALSE;
4943 extend = cairo_pattern_get_extend (&pattern->base);
4944 switch (extend) {
4945 case CAIRO_EXTEND_NONE:
4946 case CAIRO_EXTEND_REPEAT:
4947 case CAIRO_EXTEND_REFLECT:
4948 /* There's no point returning FALSE for EXTEND_PAD, as the image
4949 * surface does not currently implement it either */
4950 case CAIRO_EXTEND_PAD:
4951 return TRUE;
4954 ASSERT_NOT_REACHED;
4955 return FALSE;
4958 static cairo_bool_t
4959 _gradient_pattern_supported (const cairo_pattern_t *pattern)
4961 cairo_extend_t extend;
4963 extend = cairo_pattern_get_extend ((cairo_pattern_t *) pattern);
4966 /* Radial gradients are currently only supported with EXTEND_NONE
4967 * and EXTEND_PAD and when one circle is inside the other. */
4968 if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
4969 double x1, y1, x2, y2, r1, r2, d;
4970 cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
4972 if (extend == CAIRO_EXTEND_REPEAT ||
4973 extend == CAIRO_EXTEND_REFLECT) {
4974 return FALSE;
4977 x1 = _cairo_fixed_to_double (radial->c1.x);
4978 y1 = _cairo_fixed_to_double (radial->c1.y);
4979 r1 = _cairo_fixed_to_double (radial->r1);
4980 x2 = _cairo_fixed_to_double (radial->c2.x);
4981 y2 = _cairo_fixed_to_double (radial->c2.y);
4982 r2 = _cairo_fixed_to_double (radial->r2);
4984 d = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
4985 if (d > fabs(r2 - r1)) {
4986 return FALSE;
4990 return TRUE;
4993 static cairo_bool_t
4994 _pattern_supported (const cairo_pattern_t *pattern)
4996 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
4997 return TRUE;
4999 if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
5000 pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
5001 return _gradient_pattern_supported (pattern);
5003 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
5004 return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
5006 return FALSE;
5009 static cairo_int_status_t
5010 _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
5011 cairo_operator_t op,
5012 const cairo_pattern_t *pattern)
5014 if (surface->force_fallbacks &&
5015 surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
5017 return CAIRO_INT_STATUS_UNSUPPORTED;
5020 if (! _pattern_supported (pattern))
5021 return CAIRO_INT_STATUS_UNSUPPORTED;
5023 if (op == CAIRO_OPERATOR_OVER) {
5024 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
5025 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
5027 if ( _cairo_surface_is_meta (surface_pattern->surface)) {
5028 if (pattern->extend == CAIRO_EXTEND_PAD)
5029 return CAIRO_INT_STATUS_UNSUPPORTED;
5030 else
5031 return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
5036 if (op == CAIRO_OPERATOR_OVER)
5037 return CAIRO_STATUS_SUCCESS;
5039 /* The SOURCE operator is supported if the pattern is opaque or if
5040 * there is nothing painted underneath. */
5041 if (op == CAIRO_OPERATOR_SOURCE) {
5042 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
5043 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
5045 if (_cairo_surface_is_meta (surface_pattern->surface)) {
5046 if (_cairo_pattern_is_opaque (pattern)) {
5047 return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
5048 } else {
5049 /* FIXME: The analysis surface does not yet have
5050 * the capability to analyze a non opaque meta
5051 * surface and mark it supported if there is
5052 * nothing underneath. For now meta surfaces of
5053 * type CONTENT_COLOR_ALPHA painted with
5054 * OPERATOR_SOURCE will result in a fallback
5055 * image. */
5057 return CAIRO_INT_STATUS_UNSUPPORTED;
5059 } else {
5060 return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
5061 surface_pattern);
5065 if (_cairo_pattern_is_opaque (pattern))
5066 return CAIRO_STATUS_SUCCESS;
5067 else
5068 return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
5071 return CAIRO_INT_STATUS_UNSUPPORTED;
5074 static cairo_bool_t
5075 _cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
5076 cairo_operator_t op,
5077 const cairo_pattern_t *pattern)
5079 if (_cairo_pdf_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
5080 return TRUE;
5081 else
5082 return FALSE;
5085 static cairo_int_status_t
5086 _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
5088 cairo_status_t status;
5090 status = _cairo_pdf_surface_close_content_stream (surface);
5091 if (unlikely (status))
5092 return status;
5094 status = _cairo_array_append (&surface->knockout_group, &surface->content);
5095 if (unlikely (status))
5096 return status;
5098 _cairo_pdf_group_resources_clear (&surface->resources);
5099 return _cairo_pdf_surface_open_content_stream (surface, NULL, TRUE);
5102 static cairo_int_status_t
5103 _cairo_pdf_surface_paint (void *abstract_surface,
5104 cairo_operator_t op,
5105 const cairo_pattern_t *source,
5106 cairo_rectangle_int_t *extents)
5108 cairo_pdf_surface_t *surface = abstract_surface;
5109 cairo_status_t status;
5110 cairo_pdf_smask_group_t *group;
5111 cairo_pdf_resource_t pattern_res, gstate_res;
5113 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
5114 return _cairo_pdf_surface_analyze_operation (surface, op, source);
5115 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
5116 status = _cairo_pdf_surface_start_fallback (surface);
5117 if (unlikely (status))
5118 return status;
5121 assert (_cairo_pdf_surface_operation_supported (surface, op, source));
5123 pattern_res.id = 0;
5124 gstate_res.id = 0;
5125 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
5126 &pattern_res, &gstate_res);
5127 if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
5128 return CAIRO_STATUS_SUCCESS;
5129 if (unlikely (status))
5130 return status;
5132 if (gstate_res.id != 0) {
5133 group = _cairo_pdf_surface_create_smask_group (surface);
5134 if (unlikely (group == NULL))
5135 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5137 group->operation = PDF_PAINT;
5138 status = _cairo_pattern_create_copy (&group->source, source);
5139 if (unlikely (status)) {
5140 _cairo_pdf_smask_group_destroy (group);
5141 return status;
5143 group->source_res = pattern_res;
5144 status = _cairo_pdf_surface_add_smask_group (surface, group);
5145 if (unlikely (status)) {
5146 _cairo_pdf_smask_group_destroy (group);
5147 return status;
5150 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5151 if (unlikely (status))
5152 return status;
5154 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
5155 if (unlikely (status))
5156 return status;
5158 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5159 if (unlikely (status))
5160 return status;
5162 _cairo_output_stream_printf (surface->output,
5163 "q /s%d gs /x%d Do Q\n",
5164 gstate_res.id,
5165 group->group_res.id);
5166 } else {
5167 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
5168 if (unlikely (status))
5169 return status;
5171 _cairo_output_stream_printf (surface->output,
5172 "0 0 %f %f re f\n",
5173 surface->width, surface->height);
5175 status = _cairo_pdf_surface_unselect_pattern (surface);
5176 if (unlikely (status))
5177 return status;
5180 return _cairo_output_stream_get_status (surface->output);
5183 static cairo_int_status_t
5184 _cairo_pdf_surface_mask (void *abstract_surface,
5185 cairo_operator_t op,
5186 const cairo_pattern_t *source,
5187 const cairo_pattern_t *mask,
5188 cairo_rectangle_int_t *extents)
5190 cairo_pdf_surface_t *surface = abstract_surface;
5191 cairo_pdf_smask_group_t *group;
5192 cairo_status_t status;
5194 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
5195 cairo_status_t source_status, mask_status;
5197 source_status = _cairo_pdf_surface_analyze_operation (surface, op, source);
5198 if (_cairo_status_is_error (source_status))
5199 return source_status;
5201 mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask);
5202 if (_cairo_status_is_error (mask_status))
5203 return mask_status;
5205 return _cairo_analysis_surface_merge_status (source_status,
5206 mask_status);
5207 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
5208 status = _cairo_pdf_surface_start_fallback (surface);
5209 if (unlikely (status))
5210 return status;
5213 assert (_cairo_pdf_surface_operation_supported (surface, op, source));
5214 assert (_cairo_pdf_surface_operation_supported (surface, op, mask));
5216 group = _cairo_pdf_surface_create_smask_group (surface);
5217 if (unlikely (group == NULL))
5218 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5220 group->operation = PDF_MASK;
5221 status = _cairo_pattern_create_copy (&group->source, source);
5222 if (unlikely (status)) {
5223 _cairo_pdf_smask_group_destroy (group);
5224 return status;
5226 status = _cairo_pattern_create_copy (&group->mask, mask);
5227 if (unlikely (status)) {
5228 _cairo_pdf_smask_group_destroy (group);
5229 return status;
5231 group->source_res = _cairo_pdf_surface_new_object (surface);
5232 if (group->source_res.id == 0) {
5233 _cairo_pdf_smask_group_destroy (group);
5234 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5237 status = _cairo_pdf_surface_add_smask_group (surface, group);
5238 if (unlikely (status)) {
5239 _cairo_pdf_smask_group_destroy (group);
5240 return status;
5243 status = _cairo_pdf_surface_add_smask (surface, group->group_res);
5244 if (unlikely (status))
5245 return status;
5247 status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
5248 if (unlikely (status))
5249 return status;
5251 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5252 if (unlikely (status))
5253 return status;
5255 _cairo_output_stream_printf (surface->output,
5256 "q /s%d gs /x%d Do Q\n",
5257 group->group_res.id,
5258 group->source_res.id);
5260 return _cairo_output_stream_get_status (surface->output);
5263 static cairo_int_status_t
5264 _cairo_pdf_surface_stroke (void *abstract_surface,
5265 cairo_operator_t op,
5266 const cairo_pattern_t *source,
5267 cairo_path_fixed_t *path,
5268 cairo_stroke_style_t *style,
5269 cairo_matrix_t *ctm,
5270 cairo_matrix_t *ctm_inverse,
5271 double tolerance,
5272 cairo_antialias_t antialias,
5273 cairo_rectangle_int_t *extents)
5275 cairo_pdf_surface_t *surface = abstract_surface;
5276 cairo_status_t status;
5277 cairo_pdf_smask_group_t *group;
5278 cairo_pdf_resource_t pattern_res, gstate_res;
5280 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
5281 return _cairo_pdf_surface_analyze_operation (surface, op, source);
5283 assert (_cairo_pdf_surface_operation_supported (surface, op, source));
5285 pattern_res.id = 0;
5286 gstate_res.id = 0;
5287 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
5288 &pattern_res, &gstate_res);
5289 if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
5290 return CAIRO_STATUS_SUCCESS;
5291 if (unlikely (status))
5292 return status;
5294 if (gstate_res.id != 0) {
5295 group = _cairo_pdf_surface_create_smask_group (surface);
5296 if (unlikely (group == NULL))
5297 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5299 group->operation = PDF_STROKE;
5300 status = _cairo_pattern_create_copy (&group->source, source);
5301 if (unlikely (status)) {
5302 _cairo_pdf_smask_group_destroy (group);
5303 return status;
5305 group->source_res = pattern_res;
5306 status = _cairo_path_fixed_init_copy (&group->path, path);
5307 if (unlikely (status)) {
5308 _cairo_pdf_smask_group_destroy (group);
5309 return status;
5312 group->style = style;
5313 group->ctm = *ctm;
5314 group->ctm_inverse = *ctm_inverse;
5315 status = _cairo_pdf_surface_add_smask_group (surface, group);
5316 if (unlikely (status)) {
5317 _cairo_pdf_smask_group_destroy (group);
5318 return status;
5321 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5322 if (unlikely (status))
5323 return status;
5325 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
5326 if (unlikely (status))
5327 return status;
5329 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5330 if (unlikely (status))
5331 return status;
5333 _cairo_output_stream_printf (surface->output,
5334 "q /s%d gs /x%d Do Q\n",
5335 gstate_res.id,
5336 group->group_res.id);
5337 } else {
5338 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
5339 if (unlikely (status))
5340 return status;
5342 status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
5343 path,
5344 style,
5345 ctm,
5346 ctm_inverse);
5347 if (unlikely (status))
5348 return status;
5350 status = _cairo_pdf_surface_unselect_pattern (surface);
5351 if (unlikely (status))
5352 return status;
5355 return _cairo_output_stream_get_status (surface->output);
5358 static cairo_int_status_t
5359 _cairo_pdf_surface_fill (void *abstract_surface,
5360 cairo_operator_t op,
5361 const cairo_pattern_t *source,
5362 cairo_path_fixed_t *path,
5363 cairo_fill_rule_t fill_rule,
5364 double tolerance,
5365 cairo_antialias_t antialias,
5366 cairo_rectangle_int_t *extents)
5368 cairo_pdf_surface_t *surface = abstract_surface;
5369 cairo_status_t status;
5370 cairo_pdf_smask_group_t *group;
5371 cairo_pdf_resource_t pattern_res, gstate_res;
5373 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
5374 return _cairo_pdf_surface_analyze_operation (surface, op, source);
5375 } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
5376 status = _cairo_pdf_surface_start_fallback (surface);
5377 if (unlikely (status))
5378 return status;
5381 assert (_cairo_pdf_surface_operation_supported (surface, op, source));
5383 pattern_res.id = 0;
5384 gstate_res.id = 0;
5385 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
5386 &pattern_res, &gstate_res);
5387 if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
5388 return CAIRO_STATUS_SUCCESS;
5389 if (unlikely (status))
5390 return status;
5392 if (gstate_res.id != 0) {
5393 group = _cairo_pdf_surface_create_smask_group (surface);
5394 if (unlikely (group == NULL))
5395 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5397 group->operation = PDF_FILL;
5398 status = _cairo_pattern_create_copy (&group->source, source);
5399 if (unlikely (status)) {
5400 _cairo_pdf_smask_group_destroy (group);
5401 return status;
5403 group->source_res = pattern_res;
5404 status = _cairo_path_fixed_init_copy (&group->path, path);
5405 if (unlikely (status)) {
5406 _cairo_pdf_smask_group_destroy (group);
5407 return status;
5410 group->fill_rule = fill_rule;
5411 status = _cairo_pdf_surface_add_smask_group (surface, group);
5412 if (unlikely (status)) {
5413 _cairo_pdf_smask_group_destroy (group);
5414 return status;
5417 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5418 if (unlikely (status))
5419 return status;
5421 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
5422 if (unlikely (status))
5423 return status;
5425 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5426 if (unlikely (status))
5427 return status;
5429 _cairo_output_stream_printf (surface->output,
5430 "q /s%d gs /x%d Do Q\n",
5431 gstate_res.id,
5432 group->group_res.id);
5433 } else {
5434 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
5435 if (unlikely (status))
5436 return status;
5438 status = _cairo_pdf_operators_fill (&surface->pdf_operators,
5439 path,
5440 fill_rule);
5441 if (unlikely (status))
5442 return status;
5444 status = _cairo_pdf_surface_unselect_pattern (surface);
5445 if (unlikely (status))
5446 return status;
5449 return _cairo_output_stream_get_status (surface->output);
5452 static cairo_int_status_t
5453 _cairo_pdf_surface_fill_stroke (void *abstract_surface,
5454 cairo_operator_t fill_op,
5455 const cairo_pattern_t *fill_source,
5456 cairo_fill_rule_t fill_rule,
5457 double fill_tolerance,
5458 cairo_antialias_t fill_antialias,
5459 cairo_path_fixed_t *path,
5460 cairo_operator_t stroke_op,
5461 const cairo_pattern_t *stroke_source,
5462 cairo_stroke_style_t *stroke_style,
5463 cairo_matrix_t *stroke_ctm,
5464 cairo_matrix_t *stroke_ctm_inverse,
5465 double stroke_tolerance,
5466 cairo_antialias_t stroke_antialias,
5467 cairo_rectangle_int_t *extents)
5469 cairo_pdf_surface_t *surface = abstract_surface;
5470 cairo_status_t status;
5471 cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res;
5473 /* During analysis we return unsupported and let the _fill and
5474 * _stroke functions that are on the fallback path do the analysis
5475 * for us. During render we may still encounter unsupported
5476 * combinations of fill/stroke patterns. However we can return
5477 * unsupported anytime to let the _fill and _stroke functions take
5478 * over.
5480 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
5481 return CAIRO_INT_STATUS_UNSUPPORTED;
5483 /* PDF rendering of fill-stroke is not the same as cairo when
5484 * either the fill or stroke is not opaque.
5486 if ( !_cairo_pattern_is_opaque (fill_source) ||
5487 !_cairo_pattern_is_opaque (stroke_source))
5489 return CAIRO_INT_STATUS_UNSUPPORTED;
5492 fill_pattern_res.id = 0;
5493 gstate_res.id = 0;
5494 status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
5495 extents,
5496 &fill_pattern_res,
5497 &gstate_res);
5498 if (unlikely (status))
5499 return status;
5501 assert (gstate_res.id == 0);
5503 stroke_pattern_res.id = 0;
5504 gstate_res.id = 0;
5505 status = _cairo_pdf_surface_add_pdf_pattern (surface,
5506 stroke_source,
5507 extents,
5508 &stroke_pattern_res,
5509 &gstate_res);
5510 if (unlikely (status))
5511 return status;
5513 assert (gstate_res.id == 0);
5515 /* As PDF has separate graphics state for fill and stroke we can
5516 * select both at the same time */
5517 status = _cairo_pdf_surface_select_pattern (surface, fill_source,
5518 fill_pattern_res, FALSE);
5519 if (unlikely (status))
5520 return status;
5522 status = _cairo_pdf_surface_select_pattern (surface, stroke_source,
5523 stroke_pattern_res, TRUE);
5524 if (unlikely (status))
5525 return status;
5527 status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators,
5528 path,
5529 fill_rule,
5530 stroke_style,
5531 stroke_ctm,
5532 stroke_ctm_inverse);
5533 if (unlikely (status))
5534 return status;
5536 status = _cairo_pdf_surface_unselect_pattern (surface);
5537 if (unlikely (status))
5538 return status;
5540 return _cairo_output_stream_get_status (surface->output);
5543 static cairo_bool_t
5544 _cairo_pdf_surface_has_show_text_glyphs (void *abstract_surface)
5546 return TRUE;
5549 static cairo_int_status_t
5550 _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
5551 cairo_operator_t op,
5552 const cairo_pattern_t *source,
5553 const char *utf8,
5554 int utf8_len,
5555 cairo_glyph_t *glyphs,
5556 int num_glyphs,
5557 const cairo_text_cluster_t *clusters,
5558 int num_clusters,
5559 cairo_text_cluster_flags_t cluster_flags,
5560 cairo_scaled_font_t *scaled_font,
5561 cairo_rectangle_int_t *extents)
5563 cairo_pdf_surface_t *surface = abstract_surface;
5564 cairo_status_t status;
5565 cairo_pdf_smask_group_t *group;
5566 cairo_pdf_resource_t pattern_res, gstate_res;
5568 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
5569 return _cairo_pdf_surface_analyze_operation (surface, op, source);
5571 assert (_cairo_pdf_surface_operation_supported (surface, op, source));
5573 pattern_res.id = 0;
5574 gstate_res.id = 0;
5575 status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
5576 &pattern_res, &gstate_res);
5577 if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
5578 return CAIRO_STATUS_SUCCESS;
5579 if (unlikely (status))
5580 return status;
5582 if (gstate_res.id != 0) {
5583 group = _cairo_pdf_surface_create_smask_group (surface);
5584 if (unlikely (group == NULL))
5585 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5587 group->operation = PDF_SHOW_GLYPHS;
5588 status = _cairo_pattern_create_copy (&group->source, source);
5589 if (unlikely (status)) {
5590 _cairo_pdf_smask_group_destroy (group);
5591 return status;
5593 group->source_res = pattern_res;
5595 if (utf8_len) {
5596 group->utf8 = malloc (utf8_len);
5597 if (unlikely (group->utf8 == NULL)) {
5598 _cairo_pdf_smask_group_destroy (group);
5599 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5601 memcpy (group->utf8, utf8, utf8_len);
5603 group->utf8_len = utf8_len;
5605 if (num_glyphs) {
5606 group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
5607 if (unlikely (group->glyphs == NULL)) {
5608 _cairo_pdf_smask_group_destroy (group);
5609 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5611 memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
5613 group->num_glyphs = num_glyphs;
5615 if (num_clusters) {
5616 group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
5617 if (unlikely (group->clusters == NULL)) {
5618 _cairo_pdf_smask_group_destroy (group);
5619 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5621 memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
5623 group->num_clusters = num_clusters;
5625 group->scaled_font = cairo_scaled_font_reference (scaled_font);
5626 status = _cairo_pdf_surface_add_smask_group (surface, group);
5627 if (unlikely (status)) {
5628 _cairo_pdf_smask_group_destroy (group);
5629 return status;
5632 status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5633 if (unlikely (status))
5634 return status;
5636 status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
5637 if (unlikely (status))
5638 return status;
5640 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5641 if (unlikely (status))
5642 return status;
5644 _cairo_output_stream_printf (surface->output,
5645 "q /s%d gs /x%d Do Q\n",
5646 gstate_res.id,
5647 group->group_res.id);
5648 } else {
5649 status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
5650 if (unlikely (status))
5651 return status;
5653 /* Each call to show_glyphs() with a transclucent pattern must
5654 * be in a separate text object otherwise overlapping text
5655 * from separate calls to show_glyphs will not composite with
5656 * each other. */
5657 if (! _cairo_pattern_is_opaque (source)) {
5658 status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5659 if (unlikely (status))
5660 return status;
5663 status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
5664 utf8, utf8_len,
5665 glyphs, num_glyphs,
5666 clusters, num_clusters,
5667 cluster_flags,
5668 scaled_font);
5669 if (unlikely (status))
5670 return status;
5672 status = _cairo_pdf_surface_unselect_pattern (surface);
5673 if (unlikely (status))
5674 return status;
5677 return _cairo_output_stream_get_status (surface->output);
5681 static void
5682 _cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
5683 cairo_paginated_mode_t paginated_mode)
5685 cairo_pdf_surface_t *surface = abstract_surface;
5687 surface->paginated_mode = paginated_mode;
5690 static const cairo_surface_backend_t cairo_pdf_surface_backend = {
5691 CAIRO_SURFACE_TYPE_PDF,
5692 _cairo_pdf_surface_create_similar,
5693 _cairo_pdf_surface_finish,
5694 NULL, /* acquire_source_image */
5695 NULL, /* release_source_image */
5696 NULL, /* acquire_dest_image */
5697 NULL, /* release_dest_image */
5698 NULL, /* clone_similar */
5699 NULL, /* composite */
5700 NULL, /* fill_rectangles */
5701 NULL, /* composite_trapezoids */
5702 NULL, /* create_span_renderer */
5703 NULL, /* check_span_renderer */
5704 NULL, /* _cairo_pdf_surface_copy_page */
5705 _cairo_pdf_surface_show_page,
5706 NULL, /* set_clip_region */
5707 _cairo_pdf_surface_intersect_clip_path,
5708 _cairo_pdf_surface_get_extents,
5709 NULL, /* old_show_glyphs */
5710 _cairo_pdf_surface_get_font_options,
5711 NULL, /* flush */
5712 NULL, /* mark_dirty_rectangle */
5713 NULL, /* scaled_font_fini */
5714 NULL, /* scaled_glyph_fini */
5716 /* Here are the drawing functions */
5718 _cairo_pdf_surface_paint,
5719 _cairo_pdf_surface_mask,
5720 _cairo_pdf_surface_stroke,
5721 _cairo_pdf_surface_fill,
5722 NULL, /* show_glyphs */
5723 NULL, /* snapshot */
5725 NULL, /* is_compatible */
5726 NULL, /* reset */
5727 _cairo_pdf_surface_fill_stroke,
5728 NULL, /* create_solid_pattern_surface */
5729 NULL, /* can_repaint_solid_pattern_surface */
5730 _cairo_pdf_surface_has_show_text_glyphs,
5731 _cairo_pdf_surface_show_text_glyphs,
5734 static const cairo_paginated_surface_backend_t
5735 cairo_pdf_surface_paginated_backend = {
5736 _cairo_pdf_surface_start_page,
5737 _cairo_pdf_surface_set_paginated_mode,
5738 NULL, /* set_bounding_box */
5739 _cairo_pdf_surface_has_fallback_images,
5740 _cairo_pdf_surface_supports_fine_grained_fallbacks,