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
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() */
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"
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
79 * This PDF surface has three types of streams:
84 * Calling _cairo_output_stream_printf (surface->output, ...) will
85 * write to the currently open 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.
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.
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
] =
128 typedef struct _cairo_pdf_object
{
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
;
138 typedef struct _cairo_pdf_rgb_linear_function
{
139 cairo_pdf_resource_t resource
;
142 } cairo_pdf_rgb_linear_function_t
;
144 typedef struct _cairo_pdf_alpha_linear_function
{
145 cairo_pdf_resource_t resource
;
148 } cairo_pdf_alpha_linear_function_t
;
150 static cairo_pdf_resource_t
151 _cairo_pdf_surface_new_object (cairo_pdf_surface_t
*surface
);
154 _cairo_pdf_surface_clear (cairo_pdf_surface_t
*surface
);
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
,
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
,
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
);
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
);
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
);
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
)) {
218 resource
= surface
->next_available_resource
;
219 surface
->next_available_resource
.id
++;
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
);
235 _cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t
*surface
,
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
,
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
);
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
);
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
);
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
,
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
,
322 _cairo_pdf_operators_enable_actual_text(&surface
->pdf_operators
, TRUE
);
324 surface
->paginated_surface
= _cairo_paginated_surface_create (
326 CAIRO_CONTENT_COLOR_ALPHA
,
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
;
338 _cairo_scaled_font_subsets_destroy (surface
->font_subsets
);
340 _cairo_hash_table_destroy (surface
->all_surfaces
);
342 _cairo_array_fini (&surface
->objects
);
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
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.
375 cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func
,
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
,
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
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
403 * Return value: a pointer to the newly created surface. The caller
404 * owns the surface and should call cairo_surface_destroy() when done
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.
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
,
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
;
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
);
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
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
);
487 status
= _cairo_surface_set_error (abstract_surface
, status
);
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().
509 cairo_pdf_get_versions (cairo_pdf_version_t
const **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.
532 cairo_pdf_version_to_string (cairo_pdf_version_t version
)
534 if (version
>= CAIRO_PDF_VERSION_LAST
)
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
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().
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
);
571 _cairo_pdf_surface_set_size_internal (pdf_surface
,
574 status
= _cairo_paginated_surface_set_size (pdf_surface
->paginated_surface
,
577 if (unlikely (status
))
578 status
= _cairo_surface_set_error (surface
, status
);
582 _cairo_pdf_surface_clear (cairo_pdf_surface_t
*surface
)
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);
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
));
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
);
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
,
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
) {
657 return CAIRO_STATUS_SUCCESS
;
661 status
= _cairo_array_append (&res
->alphas
, &alpha
);
662 if (unlikely (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
,
696 cairo_pdf_surface_t
*surface
= closure
;
697 cairo_pdf_font_t font
;
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
))
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
;
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
;
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
;
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
,
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",
774 for (i
= 0; i
< num_smasks
; i
++) {
775 smask
= _cairo_array_index (&res
->smasks
, i
);
776 _cairo_output_stream_printf (surface
->output
,
778 smask
->id
, smask
->id
);
781 _cairo_output_stream_printf (surface
->output
,
785 num_resources
= _cairo_array_num_elements (&res
->patterns
);
786 if (num_resources
> 0) {
787 _cairo_output_stream_printf (surface
->output
,
789 for (i
= 0; i
< num_resources
; i
++) {
790 pattern
= _cairo_array_index (&res
->patterns
, i
);
791 _cairo_output_stream_printf (surface
->output
,
793 pattern
->id
, pattern
->id
);
796 _cairo_output_stream_printf (surface
->output
,
800 num_resources
= _cairo_array_num_elements (&res
->xobjects
);
801 if (num_resources
> 0) {
802 _cairo_output_stream_printf (surface
->output
,
805 for (i
= 0; i
< num_resources
; i
++) {
806 xobject
= _cairo_array_index (&res
->xobjects
, i
);
807 _cairo_output_stream_printf (surface
->output
,
809 xobject
->id
, xobject
->id
);
812 _cairo_output_stream_printf (surface
->output
,
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",
825 font
->subset_resource
.id
);
827 _cairo_output_stream_printf (surface
->output
, " >>\n");
830 _cairo_output_stream_printf (surface
->output
,
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
);
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
);
851 group
->width
= surface
->width
;
852 group
->height
= surface
->height
;
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
);
863 cairo_pattern_destroy (group
->source
);
865 cairo_pattern_destroy (group
->mask
);
869 free (group
->glyphs
);
871 free (group
->clusters
);
872 if (group
->scaled_font
)
873 cairo_scaled_font_destroy (group
->scaled_font
);
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
);
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
);
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
,
932 cairo_image_surface_t
*image
;
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
))
946 *width
= extents
.width
;
947 *height
= extents
.height
;
952 status
= _get_jpx_image_info (source
, &info
, &mime_data
, &mime_data_length
);
953 if (status
== CAIRO_STATUS_SUCCESS
) {
955 *height
= info
.height
;
956 } else if (_cairo_status_is_error (status
)) {
960 status
= _get_jpeg_image_info (source
, &info
, &mime_data
, &mime_data_length
);
961 if (status
== CAIRO_STATUS_SUCCESS
) {
963 *height
= info
.height
;
964 } else if (_cairo_status_is_error (status
)) {
968 status
= _cairo_surface_acquire_source_image (source
, &image
, &image_extra
);
969 if (unlikely (status
))
972 *width
= image
->width
;
973 *height
= image
->height
;
975 _cairo_surface_release_source_image (source
, image
, image_extra
);
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
,
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
;
995 case CAIRO_FILTER_GOOD
:
996 case CAIRO_FILTER_BEST
:
997 case CAIRO_FILTER_BILINEAR
:
1000 case CAIRO_FILTER_FAST
:
1001 case CAIRO_FILTER_NEAREST
:
1002 case CAIRO_FILTER_GAUSSIAN
:
1003 interpolate
= FALSE
;
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
);
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
;
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;
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;
1086 return CAIRO_STATUS_SUCCESS
;
1090 status
= _cairo_pattern_create_copy (&pdf_pattern
.pattern
, pattern
);
1091 if (unlikely (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
;
1117 pdf_pattern
.extents
= *extents
;
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
);
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
,
1145 cairo_pdf_resource_t self
, length
;
1146 cairo_output_stream_t
*output
= NULL
;
1150 _cairo_pdf_surface_update_object (surface
, self
);
1152 self
= _cairo_pdf_surface_new_object (surface
);
1154 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1157 length
= _cairo_pdf_surface_new_object (surface
);
1159 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
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
,
1176 "<< /Length %d 0 R\n",
1177 surface
->pdf_stream
.self
.id
,
1178 surface
->pdf_stream
.length
.id
);
1180 _cairo_output_stream_printf (surface
->output
,
1181 " /Filter /FlateDecode\n");
1185 _cairo_output_stream_vprintf (surface
->output
, fmt
, ap
);
1189 _cairo_output_stream_printf (surface
->output
,
1193 surface
->pdf_stream
.start_offset
= _cairo_output_stream_get_position (surface
->output
);
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
;
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
))
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
,
1230 length
= _cairo_output_stream_get_position (surface
->output
) -
1231 surface
->pdf_stream
.start_offset
;
1232 _cairo_output_stream_printf (surface
->output
,
1236 _cairo_pdf_surface_update_object (surface
,
1237 surface
->pdf_stream
.length
);
1238 _cairo_output_stream_printf (surface
->output
,
1242 surface
->pdf_stream
.length
.id
,
1245 surface
->pdf_stream
.active
= FALSE
;
1247 if (likely (status
== CAIRO_STATUS_SUCCESS
))
1248 status
= _cairo_output_stream_get_status (surface
->output
);
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
,
1264 "<< /Type /XObject\n"
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
,
1276 " /BBox [ 0 0 %f %f ]\n"
1279 " /S /Transparency\n"
1280 " /CS /DeviceRGB\n",
1284 if (is_knockout_group
)
1285 _cairo_output_stream_printf (surface
->output
,
1288 _cairo_output_stream_printf (surface
->output
,
1291 _cairo_pdf_surface_emit_group_resources (surface
, resources
);
1292 _cairo_output_stream_printf (surface
->output
,
1295 _cairo_memory_stream_copy (mem_stream
, surface
->output
);
1296 _cairo_output_stream_printf (surface
->output
,
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
);
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
);
1330 surface
->group_stream
.resource
= *resource
;
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
;
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
))
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
))
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
,
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
);
1384 *group
= surface
->group_stream
.resource
;
1386 status2
= _cairo_output_stream_destroy (surface
->group_stream
.mem_stream
);
1387 if (status
== CAIRO_STATUS_SUCCESS
)
1390 surface
->group_stream
.mem_stream
= NULL
;
1391 surface
->group_stream
.stream
= NULL
;
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
);
1412 _cairo_pdf_surface_open_stream (surface
,
1414 surface
->compress_content
,
1417 " /BBox [ 0 0 %f %f ]\n"
1420 " /S /Transparency\n"
1423 " /Resources %d 0 R\n",
1426 surface
->content_resources
.id
);
1429 _cairo_pdf_surface_open_stream (surface
,
1431 surface
->compress_content
,
1434 if (unlikely (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
))
1456 _cairo_output_stream_printf (surface
->output
, "Q\n");
1457 status
= _cairo_pdf_surface_close_stream (surface
);
1458 if (unlikely (status
))
1461 _cairo_pdf_surface_update_object (surface
, surface
->content_resources
);
1462 _cairo_output_stream_printf (surface
->output
,
1464 surface
->content_resources
.id
);
1465 _cairo_pdf_surface_emit_group_resources (surface
, &surface
->resources
);
1466 _cairo_output_stream_printf (surface
->output
,
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
,
1478 return _cairo_meta_surface_create (content
, width
, height
);
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
;
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
,
1521 surface
->next_available_resource
.id
,
1525 _cairo_output_stream_printf (surface
->output
,
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
)
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
)
1543 if (surface
->group_stream
.stream
!= NULL
) {
1544 status2
= _cairo_output_stream_destroy (surface
->group_stream
.stream
);
1545 if (status
== CAIRO_STATUS_SUCCESS
)
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
)
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
)
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
;
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
:
1602 case CAIRO_PDF_VERSION_1_5
:
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
))
1631 return CAIRO_STATUS_SUCCESS
;
1635 _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface
)
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
;
1653 unsigned long alpha_size
;
1657 cairo_bool_t opaque
;
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
);
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
);
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
);
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;
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
++) {
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
++) {
1706 a
= CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a
);
1714 /* Bail out without emitting smask if it's all opaque. */
1718 status
= _cairo_pdf_surface_open_stream (surface
,
1722 " /Subtype /Image\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
))
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
);
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
;
1752 unsigned long rgb_size
;
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
);
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
1786 if (image
->format
== CAIRO_FORMAT_ARGB32
) {
1788 a
= (*pixel
& 0xff000000) >> 24;
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;
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
))
1823 case CAIRO_FILTER_GOOD
:
1824 case CAIRO_FILTER_BEST
:
1825 case CAIRO_FILTER_BILINEAR
:
1826 interpolate
= "true";
1828 case CAIRO_FILTER_FAST
:
1829 case CAIRO_FILTER_NEAREST
:
1830 case CAIRO_FILTER_GAUSSIAN
:
1831 interpolate
= "false";
1835 #define IMAGE_DICTIONARY " /Type /XObject\n" \
1836 " /Subtype /Image\n" \
1839 " /ColorSpace /DeviceRGB\n" \
1840 " /Interpolate %s\n" \
1841 " /BitsPerComponent 8\n"
1844 status
= _cairo_pdf_surface_open_stream (surface
,
1849 image
->width
, image
->height
,
1853 status
= _cairo_pdf_surface_open_stream (surface
,
1857 image
->width
, image
->height
,
1859 if (unlikely (status
))
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
);
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
);
1897 status
= _cairo_pdf_surface_open_stream (surface
,
1901 " /Subtype /Image\n"
1904 " /ColorSpace /DeviceRGB\n"
1905 " /Filter /JPXDecode\n",
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
);
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
))
1939 if (info
.num_components
!= 1 && info
.num_components
!= 3)
1940 return CAIRO_INT_STATUS_UNSUPPORTED
;
1942 status
= _cairo_pdf_surface_open_stream (surface
,
1946 " /Subtype /Image\n"
1950 " /BitsPerComponent %d\n"
1951 " /Filter /DCTDecode\n",
1954 info
.num_components
== 1 ? "/DeviceGray" : "/DeviceRGB",
1955 info
.bits_per_component
);
1956 if (unlikely (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
);
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
;
1974 cairo_status_t status
;
1976 status
= _cairo_pdf_surface_emit_jpx_image (surface
, source
, resource
);
1977 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
1980 status
= _cairo_pdf_surface_emit_jpeg_image (surface
, source
, resource
);
1981 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
1984 status
= _cairo_surface_acquire_source_image (source
, &image
, &image_extra
);
1985 if (unlikely (status
))
1988 status
= _cairo_pdf_surface_emit_image (surface
, image
,
1989 &resource
, interpolate
);
1990 if (unlikely (status
))
1994 _cairo_surface_release_source_image (source
, image
, image_extra
);
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
,
2008 cairo_image_surface_t
*image
;
2009 cairo_surface_t
*pad_image
;
2011 cairo_status_t status
;
2012 cairo_surface_pattern_t
*pattern
= (cairo_surface_pattern_t
*) pdf_pattern
->pattern
;
2015 cairo_bool_t interpolate
;
2017 status
= _cairo_surface_acquire_source_image (pattern
->surface
, &image
, &image_extra
);
2018 if (unlikely (status
))
2021 pad_image
= &image
->base
;
2022 if (cairo_pattern_get_extend (&pattern
->base
) == CAIRO_EXTEND_PAD
) {
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
);
2034 pad_image
= _cairo_image_surface_create_with_content (pattern
->surface
->content
,
2037 if (pad_image
->status
) {
2038 status
= pad_image
->status
;
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
,
2054 _cairo_pattern_fini (&pad_pattern
.base
);
2055 if (unlikely (status
))
2059 switch (pdf_pattern
->pattern
->filter
) {
2060 case CAIRO_FILTER_GOOD
:
2061 case CAIRO_FILTER_BEST
:
2062 case CAIRO_FILTER_BILINEAR
:
2065 case CAIRO_FILTER_FAST
:
2066 case CAIRO_FILTER_NEAREST
:
2067 case CAIRO_FILTER_GAUSSIAN
:
2068 interpolate
= FALSE
;
2072 *resource
= _cairo_pdf_surface_new_object (surface
);
2073 if (resource
->id
== 0) {
2074 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2078 status
= _cairo_pdf_surface_emit_image (surface
, (cairo_image_surface_t
*)pad_image
,
2079 resource
, interpolate
);
2080 if (unlikely (status
))
2083 *width
= ((cairo_image_surface_t
*)pad_image
)->width
;
2084 *height
= ((cairo_image_surface_t
*)pad_image
)->height
;
2089 if (pad_image
!= &image
->base
)
2090 cairo_surface_destroy (pad_image
);
2092 _cairo_surface_release_source_image (pattern
->surface
, image
, image_extra
);
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
;
2110 status
= _cairo_surface_get_extents (meta_surface
, &meta_extents
);
2111 if (unlikely (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
,
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
))
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
))
2136 _cairo_output_stream_printf (surface
->output
,
2137 "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
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
))
2149 status
= _cairo_surface_set_clip (&surface
->base
, old_clip
);
2150 if (unlikely (status
))
2153 status
= _cairo_pdf_surface_close_content_stream (surface
);
2155 _cairo_pdf_surface_set_size_internal (surface
,
2158 surface
->paginated_mode
= old_paginated_mode
;
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
);
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 */
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
,
2210 status
= _cairo_pdf_surface_add_source_surface (surface
,
2212 pdf_pattern
->pattern
->filter
,
2217 if (unlikely (status
))
2220 status
= _cairo_surface_get_extents (&surface
->base
, &surface_extents
);
2221 if (unlikely (status
))
2224 bbox_x
= pattern_width
;
2225 bbox_y
= pattern_height
;
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
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
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
,
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
);
2256 case CAIRO_EXTEND_REPEAT
:
2257 xstep
= pattern_width
;
2258 ystep
= pattern_height
;
2260 case CAIRO_EXTEND_REFLECT
:
2261 bbox_x
= pattern_width
*2;
2262 bbox_y
= pattern_height
*2;
2266 /* All the rest (if any) should have been analyzed away, so this
2267 * case should be unreachable. */
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
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
,
2319 " /BBox [0 0 %d %d]\n"
2324 " /Matrix [ %f %f %f %f %f %f ]\n"
2325 " /Resources << /XObject << /x%d %d 0 R >> >>\n",
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
))
2336 if (_cairo_surface_is_meta (pattern
->surface
)) {
2337 snprintf(draw_surface
,
2338 sizeof (draw_surface
),
2340 pattern_resource
.id
);
2342 snprintf(draw_surface
,
2343 sizeof (draw_surface
),
2344 "q %d 0 0 %d 0 0 cm /x%d Do Q",
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
,
2358 pattern_width
*2, pattern_width
, pattern_height
,
2360 pattern_height
*2, pattern_width
, pattern_height
,
2362 pattern_width
*2, pattern_height
*2, pattern_width
, pattern_height
,
2365 _cairo_output_stream_printf (surface
->output
,
2370 status
= _cairo_pdf_surface_close_stream (surface
);
2371 if (unlikely (status
))
2374 return _cairo_output_stream_get_status (surface
->output
);
2377 typedef struct _cairo_pdf_color_stop
{
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
)
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)
2399 if (memcmp (&elem
.color2
[0], &stop2
->color
[0], sizeof (double)*3) != 0)
2401 *function
= elem
.resource
;
2402 return CAIRO_STATUS_SUCCESS
;
2405 res
= _cairo_pdf_surface_new_object (surface
);
2407 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2409 _cairo_output_stream_printf (surface
->output
,
2411 "<< /FunctionType 2\n"
2412 " /Domain [ 0 1 ]\n"
2413 " /C0 [ %f %f %f ]\n"
2414 " /C1 [ %f %f %f ]\n"
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
);
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
)
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])
2452 if (elem
.alpha2
!= stop2
->color
[3])
2454 *function
= elem
.resource
;
2455 return CAIRO_STATUS_SUCCESS
;
2458 res
= _cairo_pdf_surface_new_object (surface
);
2460 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2462 _cairo_output_stream_printf (surface
->output
,
2464 "<< /FunctionType 2\n"
2465 " /Domain [ 0 1 ]\n"
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
);
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
;
2494 cairo_status_t status
;
2496 /* emit linear gradients between pairs of subsequent stops... */
2497 for (i
= 0; i
< n_stops
-1; i
++) {
2499 status
= cairo_pdf_surface_emit_alpha_linear_function (surface
,
2502 &stops
[i
].resource
);
2503 if (unlikely (status
))
2506 status
= cairo_pdf_surface_emit_rgb_linear_function (surface
,
2509 &stops
[i
].resource
);
2510 if (unlikely (status
))
2515 /* ... and stitch them together */
2516 res
= _cairo_pdf_surface_new_object (surface
);
2518 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2520 _cairo_output_stream_printf (surface
->output
,
2522 "<< /FunctionType 3\n"
2523 " /Domain [ %f %f ]\n",
2526 stops
[n_stops
- 1].offset
);
2528 _cairo_output_stream_printf (surface
->output
,
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
,
2536 _cairo_output_stream_printf (surface
->output
,
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
,
2544 _cairo_output_stream_printf (surface
->output
,
2546 for (i
= 1; i
< n_stops
; i
++)
2547 _cairo_output_stream_printf (surface
->output
,
2549 _cairo_output_stream_printf (surface
->output
,
2552 _cairo_output_stream_printf (surface
->output
,
2558 return _cairo_output_stream_get_status (surface
->output
);
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
)
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
;
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]))
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
));
2614 calc_gradient_color (&allstops
[0], &stops
[0], &stops
[n_stops
-1]);
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
));
2626 calc_gradient_color (&stops
[n_stops
], &stops
[0], &stops
[n_stops
-1]);
2630 stops
[n_stops
-1].offset
= 1.0;
2634 /* no need for stitched function */
2635 status
= cairo_pdf_surface_emit_rgb_linear_function (surface
,
2639 if (unlikely (status
))
2643 status
= cairo_pdf_surface_emit_alpha_linear_function (surface
,
2647 if (unlikely (status
))
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
,
2658 if (unlikely (status
))
2662 status
= _cairo_pdf_surface_emit_stitched_colorgradient (surface
,
2667 if (unlikely (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
,
2684 cairo_pdf_resource_t res
;
2687 res
= _cairo_pdf_surface_new_object (surface
);
2689 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2691 _cairo_output_stream_printf (surface
->output
,
2693 "<< /FunctionType 3\n"
2694 " /Domain [ %d %d ]\n",
2699 _cairo_output_stream_printf (surface
->output
,
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
,
2707 _cairo_output_stream_printf (surface
->output
,
2709 for (i
= begin
+ 1; i
< end
; i
++)
2710 _cairo_output_stream_printf (surface
->output
,
2712 _cairo_output_stream_printf (surface
->output
,
2715 _cairo_output_stream_printf (surface
->output
,
2717 for (i
= begin
; i
< end
; i
++) {
2718 if ((i
% 2) && pattern
->base
.extend
== CAIRO_EXTEND_REFLECT
) {
2719 _cairo_output_stream_printf (surface
->output
,
2722 _cairo_output_stream_printf (surface
->output
,
2726 _cairo_output_stream_printf (surface
->output
,
2729 _cairo_output_stream_printf (surface
->output
,
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
,
2748 surface
->compress_content
,
2752 " /BBox [ 0 0 %f %f ]\n"
2755 " << /a0 << /ca 1 /CA 1 >>"
2758 " << /p%d %d 0 R >>\n"
2761 " << /Type /Group\n"
2762 " /S /Transparency\n"
2763 " /CS /DeviceGray\n"
2769 if (unlikely (status
))
2772 _cairo_output_stream_printf (surface
->output
,
2775 "/Pattern cs /p%d scn\n"
2783 status
= _cairo_pdf_surface_close_stream (surface
);
2784 if (unlikely (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
,
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
,
2806 "<< /Type /ExtGState\n"
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
) {
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
);
2863 x_rep
= (int) ceil (surface
->width
/dx
);
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
;
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) {
2903 status
= _cairo_pdf_surface_emit_pattern_stops (surface
,
2907 if (unlikely (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
,
2917 if (unlikely (status
))
2920 if (alpha_function
.id
!= 0) {
2921 status
= _cairo_pdf_surface_emit_repeating_function (surface
,
2926 if (unlikely (status
))
2931 _cairo_pdf_surface_update_object (surface
, pdf_pattern
->pattern_res
);
2932 _cairo_output_stream_printf (surface
->output
,
2934 "<< /Type /Pattern\n"
2936 " /Matrix [ %f %f %f %f %f %f ]\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
,
2948 first_stop
, last_stop
,
2951 if (extend
== CAIRO_EXTEND_PAD
) {
2952 _cairo_output_stream_printf (surface
->output
,
2953 " /Extend [ true true ]\n");
2955 _cairo_output_stream_printf (surface
->output
,
2956 " /Extend [ false false ]\n");
2959 _cairo_output_stream_printf (surface
->output
,
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
,
2976 "<< /Type /Pattern\n"
2978 " /Matrix [ %f %f %f %f %f %f ]\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",
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
,
2990 first_stop
, last_stop
,
2993 if (extend
== CAIRO_EXTEND_PAD
) {
2994 _cairo_output_stream_printf (surface
->output
,
2995 " /Extend [ true true ]\n");
2997 _cairo_output_stream_printf (surface
->output
,
2998 " /Extend [ false false ]\n");
3001 _cairo_output_stream_printf (surface
->output
,
3005 status
= _cairo_pdf_surface_add_pattern (surface
, mask_resource
);
3006 if (unlikely (status
))
3009 status
= cairo_pdf_surface_emit_transparency_group (surface
,
3010 pdf_pattern
->gstate_res
,
3012 if (unlikely (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
,
3038 if (unlikely (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
,
3058 "<< /Type /Pattern\n"
3060 " /Matrix [ %f %f %f %f %f %f ]\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
,
3073 if (extend
== CAIRO_EXTEND_PAD
) {
3074 _cairo_output_stream_printf (surface
->output
,
3075 " /Extend [ true true ]\n");
3077 _cairo_output_stream_printf (surface
->output
,
3078 " /Extend [ false false ]\n");
3081 _cairo_output_stream_printf (surface
->output
,
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
,
3098 "<< /Type /Pattern\n"
3100 " /Matrix [ %f %f %f %f %f %f ]\n"
3102 " << /ShadingType 3\n"
3103 " /ColorSpace /DeviceGray\n"
3104 " /Coords [ %f %f %f %f %f %f ]\n"
3105 " /Function %d 0 R\n",
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
,
3113 if (extend
== CAIRO_EXTEND_PAD
) {
3114 _cairo_output_stream_printf (surface
->output
,
3115 " /Extend [ true true ]\n");
3117 _cairo_output_stream_printf (surface
->output
,
3118 " /Extend [ false false ]\n");
3121 _cairo_output_stream_printf (surface
->output
,
3126 status
= cairo_pdf_surface_emit_transparency_group (surface
,
3127 pdf_pattern
->gstate_res
,
3129 if (unlikely (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
,
3146 pdf_pattern
->height
);
3148 switch (pdf_pattern
->pattern
->type
) {
3149 case CAIRO_PATTERN_TYPE_SOLID
:
3151 status
= _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
3154 case CAIRO_PATTERN_TYPE_SURFACE
:
3155 status
= _cairo_pdf_surface_emit_surface_pattern (surface
, pdf_pattern
);
3158 case CAIRO_PATTERN_TYPE_LINEAR
:
3159 status
= _cairo_pdf_surface_emit_linear_pattern (surface
, pdf_pattern
);
3162 case CAIRO_PATTERN_TYPE_RADIAL
:
3163 status
= _cairo_pdf_surface_emit_radial_pattern (surface
, pdf_pattern
);
3168 status
= _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
3172 _cairo_pdf_surface_set_size_internal (surface
,
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
;
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
))
3215 _cairo_output_stream_printf (surface
->output
,
3222 _cairo_output_stream_printf (surface
->output
, "RG ");
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
))
3239 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
3240 if (unlikely (status
))
3243 _cairo_output_stream_printf (surface
->output
,
3246 surface
->current_color_alpha
= solid_color
->alpha
;
3249 surface
->current_pattern_is_solid_color
= TRUE
;
3251 status
= _cairo_pdf_surface_add_alpha (surface
, 1.0, &alpha
);
3252 if (unlikely (status
))
3255 status
= _cairo_pdf_surface_add_pattern (surface
, pattern_res
);
3256 if (unlikely (status
))
3259 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
3260 if (unlikely (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 ");
3269 _cairo_output_stream_printf (surface
->output
,
3270 "/Pattern CS /p%d SCN ",
3273 _cairo_output_stream_printf (surface
->output
,
3274 "/Pattern cs /p%d scn ",
3277 _cairo_output_stream_printf (surface
->output
,
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
))
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
))
3315 status
= _cairo_pdf_surface_write_page (surface
);
3316 if (unlikely (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
;
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
,
3348 cairo_antialias_t antialias
)
3350 cairo_pdf_surface_t
*surface
= abstract_surface
;
3351 cairo_int_status_t status
;
3354 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
3355 if (unlikely (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
);
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
);
3388 _cairo_output_stream_printf (surface
->output
,
3390 "<< /Creator (cairo %s (http://cairographics.org))\n"
3391 " /Producer (cairo %s (http://cairographics.org))\n"
3395 cairo_version_string (),
3396 cairo_version_string ());
3402 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t
*surface
)
3404 cairo_pdf_resource_t page
;
3407 _cairo_pdf_surface_update_object (surface
, surface
->pages_resource
);
3408 _cairo_output_stream_printf (surface
->output
,
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
3426 _cairo_output_stream_printf (surface
->output
,
3431 static cairo_status_t
3432 _cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t
*surface
,
3435 uint16_t *utf16
= NULL
;
3437 cairo_status_t status
;
3440 if (utf8
&& *utf8
) {
3441 status
= _cairo_utf8_to_utf16 (utf8
, -1, &utf16
, &utf16_len
);
3442 if (unlikely (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
,
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
, ">");
3466 return CAIRO_STATUS_SUCCESS
;
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); \
3489 _hash_data (const unsigned char *data
, int length
, uint32_t initval
)
3491 uint32_t a
, b
, c
, len
;
3494 a
= b
= 0x9e3779b9; /* the golden ratio; an arbitrary value */
3495 c
= initval
; /* the previous hash value */
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));
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];
3526 _create_font_subset_tag (cairo_scaled_font_subset_t
*font_subset
,
3527 const char *font_name
,
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);
3543 tag
[i
] = 'A' + d
.rem
;
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
;
3559 status
= _cairo_pdf_surface_open_stream (surface
,
3561 surface
->compress_content
,
3563 if (unlikely (status
))
3566 _cairo_output_stream_printf (surface
->output
,
3567 "/CIDInit /ProcSet findresource begin\n"
3571 "<< /Registry (Adobe)\n"
3572 " /Ordering (UCS)\n"
3575 "/CMapName /Adobe-Identity-UCS def\n"
3577 "1 begincodespacerange\n");
3580 _cairo_output_stream_printf (surface
->output
,
3583 _cairo_output_stream_printf (surface
->output
,
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
,
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
,
3602 num_bfchar
- i
> 100 ? 100 : num_bfchar
- i
);
3605 _cairo_output_stream_printf (surface
->output
,
3609 _cairo_output_stream_printf (surface
->output
,
3613 status
= _cairo_pdf_surface_emit_unicode_for_glyph (surface
,
3614 font_subset
->utf8
[i
+ 1]);
3615 if (unlikely (status
))
3618 _cairo_output_stream_printf (surface
->output
,
3621 _cairo_output_stream_printf (surface
->output
,
3624 _cairo_output_stream_printf (surface
->output
,
3626 "CMapName currentdict /CMap defineresource pop\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
;
3643 cairo_status_t status
;
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
,
3657 " /Subtype /CIDFontType0C\n");
3658 if (unlikely (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
))
3668 status
= _cairo_pdf_surface_emit_to_unicode_stream (surface
,
3670 &to_unicode_stream
);
3671 if (_cairo_status_is_error (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
,
3680 "<< /Type /FontDescriptor\n"
3681 " /FontName /%s+%s\n",
3686 if (subset
->font_name
) {
3687 _cairo_output_stream_printf (surface
->output
,
3688 " /FontFamily (%s)\n",
3692 _cairo_output_stream_printf (surface
->output
,
3694 " /FontBBox [ %ld %ld %ld %ld ]\n"
3701 " /FontFile3 %u 0 R\n"
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
,
3719 " /Subtype /CIDFontType0\n"
3720 " /BaseFont /%s+%s\n"
3722 " << /Registry (Adobe)\n"
3723 " /Ordering (Identity)\n"
3726 " /FontDescriptor %d 0 R\n"
3733 for (i
= 0; i
< font_subset
->num_glyphs
; i
++)
3734 _cairo_output_stream_printf (surface
->output
,
3738 _cairo_output_stream_printf (surface
->output
,
3743 _cairo_pdf_surface_update_object (surface
, subset_resource
);
3744 _cairo_output_stream_printf (surface
->output
,
3747 " /Subtype /Type0\n"
3748 " /BaseFont /%s+%s\n"
3749 " /Encoding /Identity-H\n"
3750 " /DescendantFonts [ %d 0 R]\n",
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
,
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
);
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
;
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
))
3787 status
= _cairo_pdf_surface_emit_cff_font (surface
, font_subset
, &subset
);
3789 _cairo_cff_subset_fini (&subset
);
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
;
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
))
3808 status
= _cairo_pdf_surface_emit_cff_font (surface
, font_subset
, &subset
);
3810 _cairo_cff_fallback_fini (&subset
);
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
;
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
,
3843 subset
->header_length
,
3844 subset
->data_length
);
3845 if (unlikely (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
))
3854 status
= _cairo_pdf_surface_emit_to_unicode_stream (surface
,
3856 &to_unicode_stream
);
3857 if (_cairo_status_is_error (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
,
3866 "<< /Type /FontDescriptor\n"
3867 " /FontName /%s+%s\n"
3869 " /FontBBox [ %ld %ld %ld %ld ]\n"
3876 " /FontFile %u 0 R\n"
3890 _cairo_pdf_surface_update_object (surface
, subset_resource
);
3891 _cairo_output_stream_printf (surface
->output
,
3894 " /Subtype /Type1\n"
3895 " /BaseFont /%s+%s\n"
3898 " /FontDescriptor %d 0 R\n"
3903 font_subset
->num_glyphs
- 1,
3906 for (i
= 0; i
< font_subset
->num_glyphs
; i
++)
3907 _cairo_output_stream_printf (surface
->output
,
3911 _cairo_output_stream_printf (surface
->output
,
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
,
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
;
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
))
3944 status
= _cairo_pdf_surface_emit_type1_font (surface
, font_subset
, &subset
);
3946 _cairo_type1_subset_fini (&subset
);
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
;
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
))
3965 status
= _cairo_pdf_surface_emit_type1_font (surface
, font_subset
, &subset
);
3967 _cairo_type1_fallback_fini (&subset
);
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
;
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
))
3995 _create_font_subset_tag (font_subset
, subset
.ps_name
, tag
);
3997 status
= _cairo_pdf_surface_open_stream (surface
,
4001 subset
.data_length
);
4002 if (unlikely (status
)) {
4003 _cairo_truetype_subset_fini (&subset
);
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
);
4016 status
= _cairo_pdf_surface_emit_to_unicode_stream (surface
,
4018 &to_unicode_stream
);
4019 if (_cairo_status_is_error (status
)) {
4020 _cairo_truetype_subset_fini (&subset
);
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
,
4032 "<< /Type /FontDescriptor\n"
4033 " /FontName /%s+%s\n",
4038 if (subset
.font_name
) {
4039 _cairo_output_stream_printf (surface
->output
,
4040 " /FontFamily (%s)\n",
4044 _cairo_output_stream_printf (surface
->output
,
4046 " /FontBBox [ %ld %ld %ld %ld ]\n"
4053 " /FontFile2 %u 0 R\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
),
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
,
4074 " /Subtype /CIDFontType2\n"
4075 " /BaseFont /%s+%s\n"
4077 " << /Registry (Adobe)\n"
4078 " /Ordering (Identity)\n"
4081 " /FontDescriptor %d 0 R\n"
4088 for (i
= 0; i
< font_subset
->num_glyphs
; i
++)
4089 _cairo_output_stream_printf (surface
->output
,
4091 (long)(subset
.widths
[i
]*PDF_UNITS_PER_EM
));
4093 _cairo_output_stream_printf (surface
->output
,
4098 _cairo_pdf_surface_update_object (surface
, subset_resource
);
4099 _cairo_output_stream_printf (surface
->output
,
4102 " /Subtype /Type0\n"
4103 " /BaseFont /%s+%s\n"
4104 " /Encoding /Identity-H\n"
4105 " /DescendantFonts [ %d 0 R]\n",
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
,
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
);
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
4139 assert (image
->format
== CAIRO_FORMAT_A1
);
4141 _cairo_output_stream_printf (stream
,
4151 _cairo_output_stream_printf (stream
,
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);
4164 _cairo_output_stream_printf (stream
,
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
,
4174 cairo_pdf_surface_t
*surface
= closure
;
4175 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
4176 cairo_status_t status2
;
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
,
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
,
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
))
4202 cairo_surface_destroy (type3_surface
);
4203 status2
= _cairo_output_stream_destroy (null_stream
);
4204 if (status
== CAIRO_STATUS_SUCCESS
)
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
;
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
)) {
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
,
4245 _cairo_pdf_emit_imagemask
,
4246 surface
->font_subsets
);
4247 if (unlikely (type3_surface
->status
)) {
4250 return type3_surface
->status
;
4253 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface
,
4254 _cairo_pdf_surface_add_font
,
4257 for (i
= 0; i
< font_subset
->num_glyphs
; i
++) {
4258 status
= _cairo_pdf_surface_open_stream (surface
,
4260 surface
->compress_content
,
4262 if (unlikely (status
))
4265 glyphs
[i
] = surface
->pdf_stream
.self
;
4266 status
= _cairo_type3_glyph_surface_emit_glyph (type3_surface
,
4268 font_subset
->glyphs
[i
],
4271 if (unlikely (status
))
4274 status
= _cairo_pdf_surface_close_stream (surface
);
4275 if (unlikely (status
))
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
;
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
)) {
4301 encoding
= _cairo_pdf_surface_new_object (surface
);
4302 if (encoding
.id
== 0) {
4305 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
4308 _cairo_output_stream_printf (surface
->output
,
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
,
4315 _cairo_output_stream_printf (surface
->output
,
4320 char_procs
= _cairo_pdf_surface_new_object (surface
);
4321 if (char_procs
.id
== 0) {
4324 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
4327 _cairo_output_stream_printf (surface
->output
,
4329 "<<\n", char_procs
.id
);
4330 for (i
= 0; i
< font_subset
->num_glyphs
; i
++)
4331 _cairo_output_stream_printf (surface
->output
,
4334 _cairo_output_stream_printf (surface
->output
,
4340 status
= _cairo_pdf_surface_emit_to_unicode_stream (surface
,
4342 &to_unicode_stream
);
4343 if (_cairo_status_is_error (status
)) {
4348 _cairo_pdf_surface_update_object (surface
, subset_resource
);
4349 _cairo_output_stream_printf (surface
->output
,
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"
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
),
4366 font_subset
->num_glyphs
- 1);
4368 _cairo_output_stream_printf (surface
->output
,
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
,
4376 _cairo_output_stream_printf (surface
->output
,
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
,
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
,
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
)
4407 status
= _cairo_pdf_surface_emit_truetype_font_subset (surface
, font_subset
);
4408 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
4411 status
= _cairo_pdf_surface_emit_cff_fallback_font (surface
, font_subset
);
4412 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
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
)
4421 status
= _cairo_pdf_surface_emit_type1_fallback_font (surface
, font_subset
);
4422 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
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
,
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
)
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
,
4454 if (unlikely (status
))
4457 status
= _cairo_scaled_font_subsets_foreach_unscaled (surface
->font_subsets
,
4458 _cairo_pdf_surface_emit_unscaled_font_subset
,
4460 if (unlikely (status
))
4463 status
= _cairo_scaled_font_subsets_foreach_scaled (surface
->font_subsets
,
4464 _cairo_pdf_surface_emit_scaled_font_subset
,
4466 if (unlikely (status
))
4469 status
= _cairo_scaled_font_subsets_foreach_user (surface
->font_subsets
,
4470 _cairo_pdf_surface_emit_scaled_font_subset
,
4474 _cairo_scaled_font_subsets_destroy (surface
->font_subsets
);
4475 surface
->font_subsets
= NULL
;
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)
4489 _cairo_output_stream_printf (surface
->output
,
4491 "<< /Type /Catalog\n"
4496 surface
->pages_resource
.id
);
4502 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t
*surface
)
4504 cairo_pdf_object_t
*object
;
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
,
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
);
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
))
4546 status
= _cairo_pdf_surface_add_pdf_pattern (surface
, group
->mask
, NULL
,
4547 &pattern_res
, &gstate_res
);
4548 if (unlikely (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
);
4565 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
4566 if (unlikely (status
))
4569 status
= _cairo_pdf_surface_add_xobject (surface
, smask_group
->group_res
);
4570 if (unlikely (status
))
4573 _cairo_output_stream_printf (surface
->output
,
4574 "q /s%d gs /x%d Do Q\n",
4576 smask_group
->group_res
.id
);
4578 status
= _cairo_pdf_surface_select_pattern (surface
, group
->mask
, pattern_res
, FALSE
);
4579 if (unlikely (status
))
4582 _cairo_output_stream_printf (surface
->output
,
4584 surface
->width
, surface
->height
);
4586 status
= _cairo_pdf_surface_unselect_pattern (surface
);
4587 if (unlikely (status
))
4591 status
= _cairo_pdf_surface_close_group (surface
, &mask_group
);
4592 if (unlikely (status
))
4595 /* Create source group */
4596 status
= _cairo_pdf_surface_open_group (surface
, &group
->source_res
);
4597 if (unlikely (status
))
4602 status
= _cairo_pdf_surface_add_pdf_pattern (surface
, group
->source
, NULL
,
4603 &pattern_res
, &gstate_res
);
4604 if (unlikely (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
);
4621 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
4622 if (unlikely (status
))
4625 status
= _cairo_pdf_surface_add_xobject (surface
, smask_group
->group_res
);
4626 if (unlikely (status
))
4629 _cairo_output_stream_printf (surface
->output
,
4630 "q /s%d gs /x%d Do Q\n",
4632 smask_group
->group_res
.id
);
4634 status
= _cairo_pdf_surface_select_pattern (surface
, group
->source
, pattern_res
, FALSE
);
4635 if (unlikely (status
))
4638 _cairo_output_stream_printf (surface
->output
,
4640 surface
->width
, surface
->height
);
4642 status
= _cairo_pdf_surface_unselect_pattern (surface
);
4643 if (unlikely (status
))
4647 status
= _cairo_pdf_surface_close_group (surface
, NULL
);
4648 if (unlikely (status
))
4651 /* Create an smask based on the alpha component of mask_group */
4652 smask
= _cairo_pdf_surface_new_object (surface
);
4654 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
4656 _cairo_output_stream_printf (surface
->output
,
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
,
4670 "<< /Type /ExtGState\n"
4677 group
->group_res
.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
,
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
);
4702 status
= _cairo_pdf_surface_open_group (surface
, &group
->group_res
);
4703 if (unlikely (status
))
4706 status
= _cairo_pdf_surface_select_pattern (surface
,
4709 group
->operation
== PDF_STROKE
);
4710 if (unlikely (status
))
4713 switch (group
->operation
) {
4715 _cairo_output_stream_printf (surface
->output
,
4717 surface
->width
, surface
->height
);
4723 status
= _cairo_pdf_operators_fill (&surface
->pdf_operators
,
4728 status
= _cairo_pdf_operators_stroke (&surface
->pdf_operators
,
4732 &group
->ctm_inverse
);
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
);
4743 if (unlikely (status
))
4746 status
= _cairo_pdf_surface_unselect_pattern (surface
);
4747 if (unlikely (status
))
4750 status
= _cairo_pdf_surface_close_group (surface
, NULL
);
4753 _cairo_pdf_surface_set_size_internal (surface
,
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.
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
))
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
))
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
))
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
;
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
))
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
,
4826 status
= _cairo_pdf_surface_add_xobject (surface
, res
);
4827 if (unlikely (status
))
4830 _cairo_output_stream_printf (surface
->output
,
4832 surface
->content
.id
);
4833 status
= _cairo_pdf_surface_add_xobject (surface
, surface
->content
);
4834 if (unlikely (status
))
4837 status
= _cairo_pdf_surface_close_group (surface
, &knockout
);
4838 if (unlikely (status
))
4841 _cairo_pdf_group_resources_clear (&surface
->resources
);
4842 status
= _cairo_pdf_surface_open_content_stream (surface
, NULL
, FALSE
);
4843 if (unlikely (status
))
4846 _cairo_output_stream_printf (surface
->output
,
4849 status
= _cairo_pdf_surface_add_xobject (surface
, knockout
);
4850 if (unlikely (status
))
4853 status
= _cairo_pdf_surface_close_content_stream (surface
);
4854 if (unlikely (status
))
4858 page
= _cairo_pdf_surface_new_object (surface
);
4860 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
4862 _cairo_output_stream_printf (surface
->output
,
4866 " /MediaBox [ 0 0 %f %f ]\n"
4867 " /Contents %d 0 R\n"
4870 " /S /Transparency\n"
4873 " /Resources %d 0 R\n"
4877 surface
->pages_resource
.id
,
4880 surface
->content
.id
,
4881 surface
->content_resources
.id
);
4883 status
= _cairo_array_append (&surface
->pages
, &page
);
4884 if (unlikely (status
))
4887 status
= _cairo_pdf_surface_write_patterns_and_smask_groups (surface
);
4888 if (unlikely (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
;
4900 cairo_int_status_t status
;
4901 cairo_image_transparency_t transparency
;
4903 status
= _cairo_surface_acquire_source_image (pattern
->surface
,
4906 if (unlikely (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
;
4916 status
= CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY
;
4918 _cairo_surface_release_source_image (pattern
->surface
, image
, image_extra
);
4924 _surface_pattern_supported (cairo_surface_pattern_t
*pattern
)
4926 cairo_extend_t extend
;
4928 if (_cairo_surface_is_meta (pattern
->surface
))
4931 if (pattern
->surface
->backend
->acquire_source_image
== NULL
)
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)
4943 extend
= cairo_pattern_get_extend (&pattern
->base
);
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
:
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
) {
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
)) {
4994 _pattern_supported (const cairo_pattern_t
*pattern
)
4996 if (pattern
->type
== CAIRO_PATTERN_TYPE_SOLID
)
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
);
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
;
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
;
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
5057 return CAIRO_INT_STATUS_UNSUPPORTED
;
5060 return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface
,
5065 if (_cairo_pattern_is_opaque (pattern
))
5066 return CAIRO_STATUS_SUCCESS
;
5068 return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY
;
5071 return CAIRO_INT_STATUS_UNSUPPORTED
;
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
)
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
))
5094 status
= _cairo_array_append (&surface
->knockout_group
, &surface
->content
);
5095 if (unlikely (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
))
5121 assert (_cairo_pdf_surface_operation_supported (surface
, op
, source
));
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
))
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
);
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
);
5150 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
5151 if (unlikely (status
))
5154 status
= _cairo_pdf_surface_add_xobject (surface
, group
->group_res
);
5155 if (unlikely (status
))
5158 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
5159 if (unlikely (status
))
5162 _cairo_output_stream_printf (surface
->output
,
5163 "q /s%d gs /x%d Do Q\n",
5165 group
->group_res
.id
);
5167 status
= _cairo_pdf_surface_select_pattern (surface
, source
, pattern_res
, FALSE
);
5168 if (unlikely (status
))
5171 _cairo_output_stream_printf (surface
->output
,
5173 surface
->width
, surface
->height
);
5175 status
= _cairo_pdf_surface_unselect_pattern (surface
);
5176 if (unlikely (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
))
5205 return _cairo_analysis_surface_merge_status (source_status
,
5207 } else if (surface
->paginated_mode
== CAIRO_PAGINATED_MODE_FALLBACK
) {
5208 status
= _cairo_pdf_surface_start_fallback (surface
);
5209 if (unlikely (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
);
5226 status
= _cairo_pattern_create_copy (&group
->mask
, mask
);
5227 if (unlikely (status
)) {
5228 _cairo_pdf_smask_group_destroy (group
);
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
);
5243 status
= _cairo_pdf_surface_add_smask (surface
, group
->group_res
);
5244 if (unlikely (status
))
5247 status
= _cairo_pdf_surface_add_xobject (surface
, group
->source_res
);
5248 if (unlikely (status
))
5251 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
5252 if (unlikely (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
,
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
));
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
))
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
);
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
);
5312 group
->style
= style
;
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
);
5321 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
5322 if (unlikely (status
))
5325 status
= _cairo_pdf_surface_add_xobject (surface
, group
->group_res
);
5326 if (unlikely (status
))
5329 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
5330 if (unlikely (status
))
5333 _cairo_output_stream_printf (surface
->output
,
5334 "q /s%d gs /x%d Do Q\n",
5336 group
->group_res
.id
);
5338 status
= _cairo_pdf_surface_select_pattern (surface
, source
, pattern_res
, TRUE
);
5339 if (unlikely (status
))
5342 status
= _cairo_pdf_operators_stroke (&surface
->pdf_operators
,
5347 if (unlikely (status
))
5350 status
= _cairo_pdf_surface_unselect_pattern (surface
);
5351 if (unlikely (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
,
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
))
5381 assert (_cairo_pdf_surface_operation_supported (surface
, op
, source
));
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
))
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
);
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
);
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
);
5417 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
5418 if (unlikely (status
))
5421 status
= _cairo_pdf_surface_add_xobject (surface
, group
->group_res
);
5422 if (unlikely (status
))
5425 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
5426 if (unlikely (status
))
5429 _cairo_output_stream_printf (surface
->output
,
5430 "q /s%d gs /x%d Do Q\n",
5432 group
->group_res
.id
);
5434 status
= _cairo_pdf_surface_select_pattern (surface
, source
, pattern_res
, FALSE
);
5435 if (unlikely (status
))
5438 status
= _cairo_pdf_operators_fill (&surface
->pdf_operators
,
5441 if (unlikely (status
))
5444 status
= _cairo_pdf_surface_unselect_pattern (surface
);
5445 if (unlikely (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
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;
5494 status
= _cairo_pdf_surface_add_pdf_pattern (surface
, fill_source
,
5498 if (unlikely (status
))
5501 assert (gstate_res
.id
== 0);
5503 stroke_pattern_res
.id
= 0;
5505 status
= _cairo_pdf_surface_add_pdf_pattern (surface
,
5508 &stroke_pattern_res
,
5510 if (unlikely (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
))
5522 status
= _cairo_pdf_surface_select_pattern (surface
, stroke_source
,
5523 stroke_pattern_res
, TRUE
);
5524 if (unlikely (status
))
5527 status
= _cairo_pdf_operators_fill_stroke (&surface
->pdf_operators
,
5532 stroke_ctm_inverse
);
5533 if (unlikely (status
))
5536 status
= _cairo_pdf_surface_unselect_pattern (surface
);
5537 if (unlikely (status
))
5540 return _cairo_output_stream_get_status (surface
->output
);
5544 _cairo_pdf_surface_has_show_text_glyphs (void *abstract_surface
)
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
,
5555 cairo_glyph_t
*glyphs
,
5557 const cairo_text_cluster_t
*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
));
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
))
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
);
5593 group
->source_res
= pattern_res
;
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
;
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
;
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
);
5632 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
5633 if (unlikely (status
))
5636 status
= _cairo_pdf_surface_add_xobject (surface
, group
->group_res
);
5637 if (unlikely (status
))
5640 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
5641 if (unlikely (status
))
5644 _cairo_output_stream_printf (surface
->output
,
5645 "q /s%d gs /x%d Do Q\n",
5647 group
->group_res
.id
);
5649 status
= _cairo_pdf_surface_select_pattern (surface
, source
, pattern_res
, FALSE
);
5650 if (unlikely (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
5657 if (! _cairo_pattern_is_opaque (source
)) {
5658 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
5659 if (unlikely (status
))
5663 status
= _cairo_pdf_operators_show_text_glyphs (&surface
->pdf_operators
,
5666 clusters
, num_clusters
,
5669 if (unlikely (status
))
5672 status
= _cairo_pdf_surface_unselect_pattern (surface
);
5673 if (unlikely (status
))
5677 return _cairo_output_stream_get_status (surface
->output
);
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
,
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 */
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
,