1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2004 Red Hat, Inc
5 * Copyright © 2006 Red Hat, Inc
6 * Copyright © 2007, 2008 Adrian Johnson
8 * This library is free software; you can redistribute it and/or
9 * modify it either under the terms of the GNU Lesser General Public
10 * License version 2.1 as published by the Free Software Foundation
11 * (the "LGPL") or, at your option, under the terms of the Mozilla
12 * Public License Version 1.1 (the "MPL"). If you do not alter this
13 * notice, a recipient may use your version of this file under either
14 * the MPL or the LGPL.
16 * You should have received a copy of the LGPL along with this library
17 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19 * You should have received a copy of the MPL along with this library
20 * in the file COPYING-MPL-1.1
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License at
25 * http://www.mozilla.org/MPL/
27 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29 * the specific language governing rights and limitations.
31 * The Original Code is the cairo graphics library.
33 * The Initial Developer of the Original Code is University of Southern
37 * Kristian Høgsberg <krh@redhat.com>
38 * Carl Worth <cworth@cworth.org>
39 * Adrian Johnson <ajohnson@redneon.com>
42 #define _BSD_SOURCE /* for snprintf() */
45 #include "cairo-pdf.h"
46 #include "cairo-pdf-surface-private.h"
47 #include "cairo-pdf-operators-private.h"
48 #include "cairo-pdf-shading-private.h"
50 #include "cairo-array-private.h"
51 #include "cairo-analysis-surface-private.h"
52 #include "cairo-composite-rectangles-private.h"
53 #include "cairo-default-context-private.h"
54 #include "cairo-error-private.h"
55 #include "cairo-image-surface-inline.h"
56 #include "cairo-image-info-private.h"
57 #include "cairo-recording-surface-private.h"
58 #include "cairo-output-stream-private.h"
59 #include "cairo-paginated-private.h"
60 #include "cairo-scaled-font-subsets-private.h"
61 #include "cairo-surface-clipper-private.h"
62 #include "cairo-surface-snapshot-inline.h"
63 #include "cairo-surface-subsurface-private.h"
64 #include "cairo-type3-glyph-surface-private.h"
71 * - We embed an image in the stream each time it's composited. We
72 * could add generation counters to surfaces and remember the stream
73 * ID for a particular generation for a particular surface.
75 * - Backend specific meta data.
79 * Page Structure of the Generated PDF:
81 * Each page requiring fallbacks images contains a knockout group at
82 * the top level. The first operation of the knockout group paints a
83 * group containing all the supported drawing operations. Fallback
84 * images (if any) are painted in the knockout group. This ensures
85 * that fallback images do not composite with any content under the
90 * This PDF surface has three types of streams:
95 * Calling _cairo_output_stream_printf (surface->output, ...) will
96 * write to the currently open stream.
99 * A PDF Stream may be opened and closed with the following functions:
100 * _cairo_pdf_surface_open stream ()
101 * _cairo_pdf_surface_close_stream ()
103 * PDF Streams are written directly to the PDF file. They are used for
104 * fonts, images and patterns.
107 * The Content Stream is opened and closed with the following functions:
108 * _cairo_pdf_surface_open_content_stream ()
109 * _cairo_pdf_surface_close_content_stream ()
111 * The Content Stream contains the text and graphics operators.
114 * A Group Stream may be opened and closed with the following functions:
115 * _cairo_pdf_surface_open_group ()
116 * _cairo_pdf_surface_close_group ()
118 * A Group Stream is a Form XObject. It is used for short sequences
119 * of operators. As the content is very short the group is stored in
120 * memory until it is closed. This allows some optimization such as
121 * including the Resource dictionary and stream length inside the
122 * XObject instead of using an indirect object.
127 * @Title: PDF Surfaces
128 * @Short_Description: Rendering PDF documents
129 * @See_Also: #cairo_surface_t
131 * The PDF surface is used to render cairo graphics to Adobe
132 * PDF files and is a multi-page vector surface backend.
134 * The following mime types are supported: %CAIRO_MIME_TYPE_JPEG,
135 * %CAIRO_MIME_TYPE_JP2, %CAIRO_MIME_TYPE_UNIQUE_ID,
136 * %CAIRO_MIME_TYPE_JBIG2, %CAIRO_MIME_TYPE_JBIG2_GLOBAL,
137 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
139 * JBIG2 data in PDF must be in the embedded format as described in
140 * ISO/IEC 11544. Image specific JBIG2 data must be in
141 * %CAIRO_MIME_TYPE_JBIG2. Any global segments in the JBIG2 data
142 * (segments with page association field set to 0) must be in
143 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data may be shared by
144 * multiple images. All images sharing the same global data must set
145 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID to a unique identifer. At least
146 * one of the images must provide the global data using
147 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data will only be
148 * embedded once but shared by all JBIG2 images with the same
149 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
153 _cairo_pdf_surface_get_extents (void *abstract_surface
,
154 cairo_rectangle_int_t
*rectangle
);
157 * CAIRO_HAS_PDF_SURFACE:
159 * Defined if the PDF surface backend is available.
160 * This macro can be used to conditionally compile backend-specific code.
165 static const cairo_pdf_version_t _cairo_pdf_versions
[] =
167 CAIRO_PDF_VERSION_1_4
,
168 CAIRO_PDF_VERSION_1_5
171 #define CAIRO_PDF_VERSION_LAST ARRAY_LENGTH (_cairo_pdf_versions)
173 static const char * _cairo_pdf_version_strings
[CAIRO_PDF_VERSION_LAST
] =
179 static const char *_cairo_pdf_supported_mime_types
[] =
181 CAIRO_MIME_TYPE_JPEG
,
183 CAIRO_MIME_TYPE_UNIQUE_ID
,
184 CAIRO_MIME_TYPE_JBIG2
,
185 CAIRO_MIME_TYPE_JBIG2_GLOBAL
,
186 CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID
,
190 typedef struct _cairo_pdf_object
{
192 } cairo_pdf_object_t
;
194 typedef struct _cairo_pdf_font
{
195 unsigned int font_id
;
196 unsigned int subset_id
;
197 cairo_pdf_resource_t subset_resource
;
200 typedef struct _cairo_pdf_rgb_linear_function
{
201 cairo_pdf_resource_t resource
;
204 } cairo_pdf_rgb_linear_function_t
;
206 typedef struct _cairo_pdf_alpha_linear_function
{
207 cairo_pdf_resource_t resource
;
210 } cairo_pdf_alpha_linear_function_t
;
212 static cairo_pdf_resource_t
213 _cairo_pdf_surface_new_object (cairo_pdf_surface_t
*surface
);
216 _cairo_pdf_surface_clear (cairo_pdf_surface_t
*surface
);
219 _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t
*group
);
221 static cairo_int_status_t
222 _cairo_pdf_surface_add_font (unsigned int font_id
,
223 unsigned int subset_id
,
227 _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t
*res
);
229 static cairo_int_status_t
230 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t
*surface
,
231 cairo_pdf_resource_t
*resource
,
232 cairo_bool_t compressed
,
234 ...) CAIRO_PRINTF_FORMAT(4, 5);
235 static cairo_int_status_t
236 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t
*surface
);
238 static cairo_int_status_t
239 _cairo_pdf_surface_write_page (cairo_pdf_surface_t
*surface
);
242 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t
*surface
);
244 static cairo_pdf_resource_t
245 _cairo_pdf_surface_write_info (cairo_pdf_surface_t
*surface
);
247 static cairo_pdf_resource_t
248 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t
*surface
);
251 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t
*surface
);
253 static cairo_int_status_t
254 _cairo_pdf_surface_write_page (cairo_pdf_surface_t
*surface
);
256 static cairo_int_status_t
257 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t
*surface
);
260 _cairo_pdf_source_surface_equal (const void *key_a
, const void *key_b
);
262 static const cairo_surface_backend_t cairo_pdf_surface_backend
;
263 static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend
;
265 static cairo_pdf_resource_t
266 _cairo_pdf_surface_new_object (cairo_pdf_surface_t
*surface
)
268 cairo_pdf_resource_t resource
;
269 cairo_int_status_t status
;
270 cairo_pdf_object_t object
;
272 object
.offset
= _cairo_output_stream_get_position (surface
->output
);
274 status
= _cairo_array_append (&surface
->objects
, &object
);
275 if (unlikely (status
)) {
280 resource
= surface
->next_available_resource
;
281 surface
->next_available_resource
.id
++;
287 _cairo_pdf_surface_update_object (cairo_pdf_surface_t
*surface
,
288 cairo_pdf_resource_t resource
)
290 cairo_pdf_object_t
*object
;
292 object
= _cairo_array_index (&surface
->objects
, resource
.id
- 1);
293 object
->offset
= _cairo_output_stream_get_position (surface
->output
);
297 _cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t
*surface
,
301 surface
->width
= width
;
302 surface
->height
= height
;
303 cairo_matrix_init (&surface
->cairo_to_pdf
, 1, 0, 0, -1, 0, height
);
304 _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface
->pdf_operators
,
305 &surface
->cairo_to_pdf
);
309 _path_covers_bbox (cairo_pdf_surface_t
*surface
,
310 cairo_path_fixed_t
*path
)
314 return _cairo_path_fixed_is_box (path
, &box
) &&
317 box
.p2
.x
>= _cairo_fixed_from_double (surface
->width
) &&
318 box
.p2
.y
>= _cairo_fixed_from_double (surface
->height
);
321 static cairo_status_t
322 _cairo_pdf_surface_clipper_intersect_clip_path (cairo_surface_clipper_t
*clipper
,
323 cairo_path_fixed_t
*path
,
324 cairo_fill_rule_t fill_rule
,
326 cairo_antialias_t antialias
)
328 cairo_pdf_surface_t
*surface
= cairo_container_of (clipper
,
331 cairo_int_status_t status
;
333 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
334 if (unlikely (status
))
338 _cairo_output_stream_printf (surface
->output
, "Q q\n");
340 surface
->current_pattern_is_solid_color
= FALSE
;
341 _cairo_pdf_operators_reset (&surface
->pdf_operators
);
343 return CAIRO_STATUS_SUCCESS
;
346 if (_path_covers_bbox (surface
, path
))
347 return CAIRO_STATUS_SUCCESS
;
349 return _cairo_pdf_operators_clip (&surface
->pdf_operators
, path
, fill_rule
);
352 static cairo_surface_t
*
353 _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t
*output
,
357 cairo_pdf_surface_t
*surface
;
358 cairo_status_t status
, status_ignored
;
360 surface
= malloc (sizeof (cairo_pdf_surface_t
));
361 if (unlikely (surface
== NULL
)) {
362 /* destroy stream on behalf of caller */
363 status
= _cairo_output_stream_destroy (output
);
364 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
367 _cairo_surface_init (&surface
->base
,
368 &cairo_pdf_surface_backend
,
370 CAIRO_CONTENT_COLOR_ALPHA
);
372 surface
->output
= output
;
373 surface
->width
= width
;
374 surface
->height
= height
;
375 cairo_matrix_init (&surface
->cairo_to_pdf
, 1, 0, 0, -1, 0, height
);
377 _cairo_array_init (&surface
->objects
, sizeof (cairo_pdf_object_t
));
378 _cairo_array_init (&surface
->pages
, sizeof (cairo_pdf_resource_t
));
379 _cairo_array_init (&surface
->rgb_linear_functions
, sizeof (cairo_pdf_rgb_linear_function_t
));
380 _cairo_array_init (&surface
->alpha_linear_functions
, sizeof (cairo_pdf_alpha_linear_function_t
));
381 _cairo_array_init (&surface
->fonts
, sizeof (cairo_pdf_font_t
));
382 _cairo_array_init (&surface
->smask_groups
, sizeof (cairo_pdf_smask_group_t
*));
383 _cairo_array_init (&surface
->knockout_group
, sizeof (cairo_pdf_resource_t
));
385 _cairo_array_init (&surface
->page_patterns
, sizeof (cairo_pdf_pattern_t
));
386 _cairo_array_init (&surface
->page_surfaces
, sizeof (cairo_pdf_source_surface_t
));
387 _cairo_array_init (&surface
->jbig2_global
, sizeof (cairo_pdf_jbig2_global_t
));
388 surface
->all_surfaces
= _cairo_hash_table_create (_cairo_pdf_source_surface_equal
);
389 if (unlikely (surface
->all_surfaces
== NULL
)) {
390 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
394 _cairo_pdf_group_resources_init (&surface
->resources
);
396 surface
->font_subsets
= _cairo_scaled_font_subsets_create_composite ();
397 if (! surface
->font_subsets
) {
398 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
402 _cairo_scaled_font_subsets_enable_latin_subset (surface
->font_subsets
, TRUE
);
404 surface
->next_available_resource
.id
= 1;
405 surface
->pages_resource
= _cairo_pdf_surface_new_object (surface
);
406 if (surface
->pages_resource
.id
== 0) {
407 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
411 surface
->pdf_version
= CAIRO_PDF_VERSION_1_5
;
412 surface
->compress_content
= TRUE
;
413 surface
->pdf_stream
.active
= FALSE
;
414 surface
->pdf_stream
.old_output
= NULL
;
415 surface
->group_stream
.active
= FALSE
;
416 surface
->group_stream
.stream
= NULL
;
417 surface
->group_stream
.mem_stream
= NULL
;
419 surface
->paginated_mode
= CAIRO_PAGINATED_MODE_ANALYZE
;
421 surface
->force_fallbacks
= FALSE
;
422 surface
->select_pattern_gstate_saved
= FALSE
;
423 surface
->current_pattern_is_solid_color
= FALSE
;
424 surface
->current_operator
= CAIRO_OPERATOR_OVER
;
425 surface
->header_emitted
= FALSE
;
427 _cairo_surface_clipper_init (&surface
->clipper
,
428 _cairo_pdf_surface_clipper_intersect_clip_path
);
430 _cairo_pdf_operators_init (&surface
->pdf_operators
,
432 &surface
->cairo_to_pdf
,
433 surface
->font_subsets
,
435 _cairo_pdf_operators_set_font_subsets_callback (&surface
->pdf_operators
,
436 _cairo_pdf_surface_add_font
,
438 _cairo_pdf_operators_enable_actual_text(&surface
->pdf_operators
, TRUE
);
440 surface
->paginated_surface
= _cairo_paginated_surface_create (
442 CAIRO_CONTENT_COLOR_ALPHA
,
443 &cairo_pdf_surface_paginated_backend
);
445 status
= surface
->paginated_surface
->status
;
446 if (status
== CAIRO_STATUS_SUCCESS
) {
447 /* paginated keeps the only reference to surface now, drop ours */
448 cairo_surface_destroy (&surface
->base
);
449 return surface
->paginated_surface
;
453 _cairo_scaled_font_subsets_destroy (surface
->font_subsets
);
455 _cairo_hash_table_destroy (surface
->all_surfaces
);
457 _cairo_array_fini (&surface
->objects
);
460 /* destroy stream on behalf of caller */
461 status_ignored
= _cairo_output_stream_destroy (output
);
463 return _cairo_surface_create_in_error (status
);
467 * cairo_pdf_surface_create_for_stream:
468 * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
469 * to indicate a no-op @write_func. With a no-op @write_func,
470 * the surface may be queried or used as a source without
471 * generating any temporary files.
472 * @closure: the closure argument for @write_func
473 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
474 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
476 * Creates a PDF surface of the specified size in points to be written
477 * incrementally to the stream represented by @write_func and @closure.
479 * Return value: a pointer to the newly created surface. The caller
480 * owns the surface and should call cairo_surface_destroy() when done
483 * This function always returns a valid pointer, but it will return a
484 * pointer to a "nil" surface if an error such as out of memory
485 * occurs. You can use cairo_surface_status() to check for this.
490 cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func
,
492 double width_in_points
,
493 double height_in_points
)
495 cairo_output_stream_t
*output
;
497 output
= _cairo_output_stream_create (write_func
, NULL
, closure
);
498 if (_cairo_output_stream_get_status (output
))
499 return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output
));
501 return _cairo_pdf_surface_create_for_stream_internal (output
,
507 * cairo_pdf_surface_create:
508 * @filename: a filename for the PDF output (must be writable), %NULL may be
509 * used to specify no output. This will generate a PDF surface that
510 * may be queried and used as a source, without generating a
512 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
513 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
515 * Creates a PDF surface of the specified size in points to be written
518 * Return value: a pointer to the newly created surface. The caller
519 * owns the surface and should call cairo_surface_destroy() when done
522 * This function always returns a valid pointer, but it will return a
523 * pointer to a "nil" surface if an error such as out of memory
524 * occurs. You can use cairo_surface_status() to check for this.
529 cairo_pdf_surface_create (const char *filename
,
530 double width_in_points
,
531 double height_in_points
)
533 cairo_output_stream_t
*output
;
535 output
= _cairo_output_stream_create_for_filename (filename
);
536 if (_cairo_output_stream_get_status (output
))
537 return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output
));
539 return _cairo_pdf_surface_create_for_stream_internal (output
,
545 _cairo_surface_is_pdf (cairo_surface_t
*surface
)
547 return surface
->backend
== &cairo_pdf_surface_backend
;
550 /* If the abstract_surface is a paginated surface, and that paginated
551 * surface's target is a pdf_surface, then set pdf_surface to that
552 * target. Otherwise return FALSE.
555 _extract_pdf_surface (cairo_surface_t
*surface
,
556 cairo_pdf_surface_t
**pdf_surface
)
558 cairo_surface_t
*target
;
559 cairo_status_t status_ignored
;
563 if (surface
->finished
) {
564 status_ignored
= _cairo_surface_set_error (surface
,
565 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED
));
569 if (! _cairo_surface_is_paginated (surface
)) {
570 status_ignored
= _cairo_surface_set_error (surface
,
571 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
));
575 target
= _cairo_paginated_surface_get_target (surface
);
576 if (target
->status
) {
577 status_ignored
= _cairo_surface_set_error (surface
,
581 if (target
->finished
) {
582 status_ignored
= _cairo_surface_set_error (surface
,
583 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED
));
587 if (! _cairo_surface_is_pdf (target
)) {
588 status_ignored
= _cairo_surface_set_error (surface
,
589 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
));
593 *pdf_surface
= (cairo_pdf_surface_t
*) target
;
598 * cairo_pdf_surface_restrict_to_version:
599 * @surface: a PDF #cairo_surface_t
600 * @version: PDF version
602 * Restricts the generated PDF file to @version. See cairo_pdf_get_versions()
603 * for a list of available version values that can be used here.
605 * This function should only be called before any drawing operations
606 * have been performed on the given surface. The simplest way to do
607 * this is to call this function immediately after creating the
613 cairo_pdf_surface_restrict_to_version (cairo_surface_t
*abstract_surface
,
614 cairo_pdf_version_t version
)
616 cairo_pdf_surface_t
*surface
= NULL
; /* hide compiler warning */
618 if (! _extract_pdf_surface (abstract_surface
, &surface
))
621 if (version
< CAIRO_PDF_VERSION_LAST
)
622 surface
->pdf_version
= version
;
624 _cairo_pdf_operators_enable_actual_text(&surface
->pdf_operators
,
625 version
>= CAIRO_PDF_VERSION_1_5
);
629 * cairo_pdf_get_versions:
630 * @versions: supported version list
631 * @num_versions: list length
633 * Used to retrieve the list of supported versions. See
634 * cairo_pdf_surface_restrict_to_version().
639 cairo_pdf_get_versions (cairo_pdf_version_t
const **versions
,
642 if (versions
!= NULL
)
643 *versions
= _cairo_pdf_versions
;
645 if (num_versions
!= NULL
)
646 *num_versions
= CAIRO_PDF_VERSION_LAST
;
650 * cairo_pdf_version_to_string:
651 * @version: a version id
653 * Get the string representation of the given @version id. This function
654 * will return %NULL if @version isn't valid. See cairo_pdf_get_versions()
655 * for a way to get the list of valid version ids.
657 * Return value: the string associated to given version.
662 cairo_pdf_version_to_string (cairo_pdf_version_t version
)
664 if (version
>= CAIRO_PDF_VERSION_LAST
)
667 return _cairo_pdf_version_strings
[version
];
671 * cairo_pdf_surface_set_size:
672 * @surface: a PDF #cairo_surface_t
673 * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
674 * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
676 * Changes the size of a PDF surface for the current (and
679 * This function should only be called before any drawing operations
680 * have been performed on the current page. The simplest way to do
681 * this is to call this function immediately after creating the
682 * surface or immediately after completing a page with either
683 * cairo_show_page() or cairo_copy_page().
688 cairo_pdf_surface_set_size (cairo_surface_t
*surface
,
689 double width_in_points
,
690 double height_in_points
)
692 cairo_pdf_surface_t
*pdf_surface
= NULL
; /* hide compiler warning */
693 cairo_status_t status
;
695 if (! _extract_pdf_surface (surface
, &pdf_surface
))
698 _cairo_pdf_surface_set_size_internal (pdf_surface
,
701 status
= _cairo_paginated_surface_set_size (pdf_surface
->paginated_surface
,
705 status
= _cairo_surface_set_error (surface
, status
);
709 _cairo_pdf_surface_clear (cairo_pdf_surface_t
*surface
)
712 cairo_pdf_pattern_t
*pattern
;
713 cairo_pdf_source_surface_t
*src_surface
;
714 cairo_pdf_smask_group_t
*group
;
716 size
= _cairo_array_num_elements (&surface
->page_patterns
);
717 for (i
= 0; i
< size
; i
++) {
718 pattern
= (cairo_pdf_pattern_t
*) _cairo_array_index (&surface
->page_patterns
, i
);
719 cairo_pattern_destroy (pattern
->pattern
);
721 _cairo_array_truncate (&surface
->page_patterns
, 0);
723 size
= _cairo_array_num_elements (&surface
->page_surfaces
);
724 for (i
= 0; i
< size
; i
++) {
725 src_surface
= (cairo_pdf_source_surface_t
*) _cairo_array_index (&surface
->page_surfaces
, i
);
726 cairo_surface_destroy (src_surface
->surface
);
728 _cairo_array_truncate (&surface
->page_surfaces
, 0);
730 size
= _cairo_array_num_elements (&surface
->smask_groups
);
731 for (i
= 0; i
< size
; i
++) {
732 _cairo_array_copy_element (&surface
->smask_groups
, i
, &group
);
733 _cairo_pdf_smask_group_destroy (group
);
735 _cairo_array_truncate (&surface
->smask_groups
, 0);
736 _cairo_array_truncate (&surface
->knockout_group
, 0);
740 _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t
*res
)
744 for (i
= 0; i
< CAIRO_NUM_OPERATORS
; i
++)
745 res
->operators
[i
] = FALSE
;
747 _cairo_array_init (&res
->alphas
, sizeof (double));
748 _cairo_array_init (&res
->smasks
, sizeof (cairo_pdf_resource_t
));
749 _cairo_array_init (&res
->patterns
, sizeof (cairo_pdf_resource_t
));
750 _cairo_array_init (&res
->shadings
, sizeof (cairo_pdf_resource_t
));
751 _cairo_array_init (&res
->xobjects
, sizeof (cairo_pdf_resource_t
));
752 _cairo_array_init (&res
->fonts
, sizeof (cairo_pdf_font_t
));
756 _cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t
*res
)
758 _cairo_array_fini (&res
->alphas
);
759 _cairo_array_fini (&res
->smasks
);
760 _cairo_array_fini (&res
->patterns
);
761 _cairo_array_fini (&res
->shadings
);
762 _cairo_array_fini (&res
->xobjects
);
763 _cairo_array_fini (&res
->fonts
);
767 _cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t
*res
)
771 for (i
= 0; i
< CAIRO_NUM_OPERATORS
; i
++)
772 res
->operators
[i
] = FALSE
;
774 _cairo_array_truncate (&res
->alphas
, 0);
775 _cairo_array_truncate (&res
->smasks
, 0);
776 _cairo_array_truncate (&res
->patterns
, 0);
777 _cairo_array_truncate (&res
->shadings
, 0);
778 _cairo_array_truncate (&res
->xobjects
, 0);
779 _cairo_array_truncate (&res
->fonts
, 0);
783 _cairo_pdf_surface_add_operator (cairo_pdf_surface_t
*surface
,
786 cairo_pdf_group_resources_t
*res
= &surface
->resources
;
788 res
->operators
[op
] = TRUE
;
791 static cairo_int_status_t
792 _cairo_pdf_surface_add_alpha (cairo_pdf_surface_t
*surface
,
798 cairo_int_status_t status
;
799 cairo_pdf_group_resources_t
*res
= &surface
->resources
;
801 num_alphas
= _cairo_array_num_elements (&res
->alphas
);
802 for (i
= 0; i
< num_alphas
; i
++) {
803 _cairo_array_copy_element (&res
->alphas
, i
, &other
);
804 if (alpha
== other
) {
806 return CAIRO_STATUS_SUCCESS
;
810 status
= _cairo_array_append (&res
->alphas
, &alpha
);
811 if (unlikely (status
))
814 *index
= _cairo_array_num_elements (&res
->alphas
) - 1;
816 return CAIRO_STATUS_SUCCESS
;
819 static cairo_int_status_t
820 _cairo_pdf_surface_add_smask (cairo_pdf_surface_t
*surface
,
821 cairo_pdf_resource_t smask
)
823 return _cairo_array_append (&(surface
->resources
.smasks
), &smask
);
826 static cairo_int_status_t
827 _cairo_pdf_surface_add_pattern (cairo_pdf_surface_t
*surface
,
828 cairo_pdf_resource_t pattern
)
830 return _cairo_array_append (&(surface
->resources
.patterns
), &pattern
);
833 static cairo_int_status_t
834 _cairo_pdf_surface_add_shading (cairo_pdf_surface_t
*surface
,
835 cairo_pdf_resource_t shading
)
837 return _cairo_array_append (&(surface
->resources
.shadings
), &shading
);
841 static cairo_int_status_t
842 _cairo_pdf_surface_add_xobject (cairo_pdf_surface_t
*surface
,
843 cairo_pdf_resource_t xobject
)
845 return _cairo_array_append (&(surface
->resources
.xobjects
), &xobject
);
848 static cairo_int_status_t
849 _cairo_pdf_surface_add_font (unsigned int font_id
,
850 unsigned int subset_id
,
853 cairo_pdf_surface_t
*surface
= closure
;
854 cairo_pdf_font_t font
;
856 cairo_int_status_t status
;
857 cairo_pdf_group_resources_t
*res
= &surface
->resources
;
859 num_fonts
= _cairo_array_num_elements (&res
->fonts
);
860 for (i
= 0; i
< num_fonts
; i
++) {
861 _cairo_array_copy_element (&res
->fonts
, i
, &font
);
862 if (font
.font_id
== font_id
&&
863 font
.subset_id
== subset_id
)
864 return CAIRO_STATUS_SUCCESS
;
867 num_fonts
= _cairo_array_num_elements (&surface
->fonts
);
868 for (i
= 0; i
< num_fonts
; i
++) {
869 _cairo_array_copy_element (&surface
->fonts
, i
, &font
);
870 if (font
.font_id
== font_id
&&
871 font
.subset_id
== subset_id
)
872 return _cairo_array_append (&res
->fonts
, &font
);
875 font
.font_id
= font_id
;
876 font
.subset_id
= subset_id
;
877 font
.subset_resource
= _cairo_pdf_surface_new_object (surface
);
878 if (font
.subset_resource
.id
== 0)
879 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
881 status
= _cairo_array_append (&surface
->fonts
, &font
);
882 if (unlikely (status
))
885 return _cairo_array_append (&res
->fonts
, &font
);
888 static cairo_pdf_resource_t
889 _cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t
*surface
,
890 unsigned int font_id
,
891 unsigned int subset_id
)
893 cairo_pdf_font_t font
;
896 num_fonts
= _cairo_array_num_elements (&surface
->fonts
);
897 for (i
= 0; i
< num_fonts
; i
++) {
898 _cairo_array_copy_element (&surface
->fonts
, i
, &font
);
899 if (font
.font_id
== font_id
&& font
.subset_id
== subset_id
)
900 return font
.subset_resource
;
903 font
.subset_resource
.id
= 0;
904 return font
.subset_resource
;
908 _cairo_operator_to_pdf_blend_mode (cairo_operator_t op
)
911 /* The extend blend mode operators */
912 case CAIRO_OPERATOR_MULTIPLY
: return "Multiply";
913 case CAIRO_OPERATOR_SCREEN
: return "Screen";
914 case CAIRO_OPERATOR_OVERLAY
: return "Overlay";
915 case CAIRO_OPERATOR_DARKEN
: return "Darken";
916 case CAIRO_OPERATOR_LIGHTEN
: return "Lighten";
917 case CAIRO_OPERATOR_COLOR_DODGE
: return "ColorDodge";
918 case CAIRO_OPERATOR_COLOR_BURN
: return "ColorBurn";
919 case CAIRO_OPERATOR_HARD_LIGHT
: return "HardLight";
920 case CAIRO_OPERATOR_SOFT_LIGHT
: return "SoftLight";
921 case CAIRO_OPERATOR_DIFFERENCE
: return "Difference";
922 case CAIRO_OPERATOR_EXCLUSION
: return "Exclusion";
923 case CAIRO_OPERATOR_HSL_HUE
: return "Hue";
924 case CAIRO_OPERATOR_HSL_SATURATION
: return "Saturation";
925 case CAIRO_OPERATOR_HSL_COLOR
: return "Color";
926 case CAIRO_OPERATOR_HSL_LUMINOSITY
: return "Luminosity";
929 /* The original Porter-Duff set */
930 case CAIRO_OPERATOR_CLEAR
:
931 case CAIRO_OPERATOR_SOURCE
:
932 case CAIRO_OPERATOR_OVER
:
933 case CAIRO_OPERATOR_IN
:
934 case CAIRO_OPERATOR_OUT
:
935 case CAIRO_OPERATOR_ATOP
:
936 case CAIRO_OPERATOR_DEST
:
937 case CAIRO_OPERATOR_DEST_OVER
:
938 case CAIRO_OPERATOR_DEST_IN
:
939 case CAIRO_OPERATOR_DEST_OUT
:
940 case CAIRO_OPERATOR_DEST_ATOP
:
941 case CAIRO_OPERATOR_XOR
:
942 case CAIRO_OPERATOR_ADD
:
943 case CAIRO_OPERATOR_SATURATE
:
949 _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t
*surface
,
950 cairo_pdf_group_resources_t
*res
)
952 int num_alphas
, num_smasks
, num_resources
, i
;
954 cairo_pdf_resource_t
*smask
, *pattern
, *shading
, *xobject
;
955 cairo_pdf_font_t
*font
;
957 _cairo_output_stream_printf (surface
->output
, "<<\n");
959 num_alphas
= _cairo_array_num_elements (&res
->alphas
);
960 num_smasks
= _cairo_array_num_elements (&res
->smasks
);
961 if (num_alphas
> 0 || num_smasks
> 0) {
962 _cairo_output_stream_printf (surface
->output
,
965 for (i
= 0; i
< CAIRO_NUM_OPERATORS
; i
++) {
966 if (res
->operators
[i
]) {
967 _cairo_output_stream_printf (surface
->output
,
968 " /b%d << /BM /%s >>\n",
969 i
, _cairo_operator_to_pdf_blend_mode(i
));
973 for (i
= 0; i
< num_alphas
; i
++) {
974 _cairo_array_copy_element (&res
->alphas
, i
, &alpha
);
975 _cairo_output_stream_printf (surface
->output
,
976 " /a%d << /CA %f /ca %f >>\n",
980 for (i
= 0; i
< num_smasks
; i
++) {
981 smask
= _cairo_array_index (&res
->smasks
, i
);
982 _cairo_output_stream_printf (surface
->output
,
984 smask
->id
, smask
->id
);
987 _cairo_output_stream_printf (surface
->output
,
991 num_resources
= _cairo_array_num_elements (&res
->patterns
);
992 if (num_resources
> 0) {
993 _cairo_output_stream_printf (surface
->output
,
995 for (i
= 0; i
< num_resources
; i
++) {
996 pattern
= _cairo_array_index (&res
->patterns
, i
);
997 _cairo_output_stream_printf (surface
->output
,
999 pattern
->id
, pattern
->id
);
1002 _cairo_output_stream_printf (surface
->output
,
1006 num_resources
= _cairo_array_num_elements (&res
->shadings
);
1007 if (num_resources
> 0) {
1008 _cairo_output_stream_printf (surface
->output
,
1010 for (i
= 0; i
< num_resources
; i
++) {
1011 shading
= _cairo_array_index (&res
->shadings
, i
);
1012 _cairo_output_stream_printf (surface
->output
,
1014 shading
->id
, shading
->id
);
1017 _cairo_output_stream_printf (surface
->output
,
1021 num_resources
= _cairo_array_num_elements (&res
->xobjects
);
1022 if (num_resources
> 0) {
1023 _cairo_output_stream_printf (surface
->output
,
1026 for (i
= 0; i
< num_resources
; i
++) {
1027 xobject
= _cairo_array_index (&res
->xobjects
, i
);
1028 _cairo_output_stream_printf (surface
->output
,
1030 xobject
->id
, xobject
->id
);
1033 _cairo_output_stream_printf (surface
->output
,
1037 num_resources
= _cairo_array_num_elements (&res
->fonts
);
1038 if (num_resources
> 0) {
1039 _cairo_output_stream_printf (surface
->output
," /Font <<\n");
1040 for (i
= 0; i
< num_resources
; i
++) {
1041 font
= _cairo_array_index (&res
->fonts
, i
);
1042 _cairo_output_stream_printf (surface
->output
,
1043 " /f-%d-%d %d 0 R\n",
1046 font
->subset_resource
.id
);
1048 _cairo_output_stream_printf (surface
->output
, " >>\n");
1051 _cairo_output_stream_printf (surface
->output
,
1055 static cairo_pdf_smask_group_t
*
1056 _cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t
*surface
,
1057 const cairo_rectangle_int_t
*extents
)
1059 cairo_pdf_smask_group_t
*group
;
1061 group
= calloc (1, sizeof (cairo_pdf_smask_group_t
));
1062 if (unlikely (group
== NULL
)) {
1063 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
1067 group
->group_res
= _cairo_pdf_surface_new_object (surface
);
1068 if (group
->group_res
.id
== 0) {
1069 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
1073 group
->width
= surface
->width
;
1074 group
->height
= surface
->height
;
1075 if (extents
!= NULL
) {
1076 group
->extents
= *extents
;
1078 group
->extents
.x
= 0;
1079 group
->extents
.y
= 0;
1080 group
->extents
.width
= surface
->width
;
1081 group
->extents
.height
= surface
->height
;
1083 group
->extents
= *extents
;
1089 _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t
*group
)
1091 if (group
->operation
== PDF_FILL
|| group
->operation
== PDF_STROKE
)
1092 _cairo_path_fixed_fini (&group
->path
);
1094 cairo_pattern_destroy (group
->source
);
1096 cairo_pattern_destroy (group
->mask
);
1098 free (group
->glyphs
);
1099 free (group
->clusters
);
1100 if (group
->scaled_font
)
1101 cairo_scaled_font_destroy (group
->scaled_font
);
1105 static cairo_int_status_t
1106 _cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t
*surface
,
1107 cairo_pdf_smask_group_t
*group
)
1109 return _cairo_array_append (&surface
->smask_groups
, &group
);
1113 _cairo_pdf_source_surface_equal (const void *key_a
, const void *key_b
)
1115 const cairo_pdf_source_surface_entry_t
*a
= key_a
;
1116 const cairo_pdf_source_surface_entry_t
*b
= key_b
;
1118 if (a
->interpolate
!= b
->interpolate
)
1121 if (a
->unique_id
&& b
->unique_id
&& a
->unique_id_length
== b
->unique_id_length
)
1122 return (memcmp (a
->unique_id
, b
->unique_id
, a
->unique_id_length
) == 0);
1124 return (a
->id
== b
->id
);
1128 _cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t
*key
)
1130 if (key
->unique_id
&& key
->unique_id_length
> 0) {
1131 key
->base
.hash
= _cairo_hash_bytes (_CAIRO_HASH_INIT_VALUE
,
1132 key
->unique_id
, key
->unique_id_length
);
1134 key
->base
.hash
= key
->id
;
1138 static cairo_int_status_t
1139 _cairo_pdf_surface_acquire_source_image_from_pattern (cairo_pdf_surface_t
*surface
,
1140 const cairo_pattern_t
*pattern
,
1141 cairo_image_surface_t
**image
,
1144 switch (pattern
->type
) {
1145 case CAIRO_PATTERN_TYPE_SURFACE
: {
1146 cairo_surface_pattern_t
*surf_pat
= (cairo_surface_pattern_t
*) pattern
;
1147 return _cairo_surface_acquire_source_image (surf_pat
->surface
, image
, image_extra
);
1150 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
: {
1151 cairo_surface_t
*surf
;
1152 surf
= _cairo_raster_source_pattern_acquire (pattern
, &surface
->base
, NULL
);
1154 return CAIRO_INT_STATUS_UNSUPPORTED
;
1155 assert (_cairo_surface_is_image (surf
));
1156 *image
= (cairo_image_surface_t
*) surf
;
1159 case CAIRO_PATTERN_TYPE_SOLID
:
1160 case CAIRO_PATTERN_TYPE_LINEAR
:
1161 case CAIRO_PATTERN_TYPE_RADIAL
:
1162 case CAIRO_PATTERN_TYPE_MESH
:
1168 return CAIRO_STATUS_SUCCESS
;
1172 _cairo_pdf_surface_release_source_image_from_pattern (cairo_pdf_surface_t
*surface
,
1173 const cairo_pattern_t
*pattern
,
1174 cairo_image_surface_t
*image
,
1177 switch (pattern
->type
) {
1178 case CAIRO_PATTERN_TYPE_SURFACE
: {
1179 cairo_surface_pattern_t
*surf_pat
= (cairo_surface_pattern_t
*) pattern
;
1180 _cairo_surface_release_source_image (surf_pat
->surface
, image
, image_extra
);
1183 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
1184 _cairo_raster_source_pattern_release (pattern
, &image
->base
);
1187 case CAIRO_PATTERN_TYPE_SOLID
:
1188 case CAIRO_PATTERN_TYPE_LINEAR
:
1189 case CAIRO_PATTERN_TYPE_RADIAL
:
1190 case CAIRO_PATTERN_TYPE_MESH
:
1198 static cairo_int_status_t
1199 _get_jbig2_image_info (cairo_surface_t
*source
,
1200 cairo_image_info_t
*info
,
1201 const unsigned char **mime_data
,
1202 unsigned long *mime_data_length
)
1204 cairo_surface_get_mime_data (source
, CAIRO_MIME_TYPE_JBIG2
,
1205 mime_data
, mime_data_length
);
1206 if (*mime_data
== NULL
)
1207 return CAIRO_INT_STATUS_UNSUPPORTED
;
1209 return _cairo_image_info_get_jbig2_info (info
, *mime_data
, *mime_data_length
);
1212 static cairo_int_status_t
1213 _get_jpx_image_info (cairo_surface_t
*source
,
1214 cairo_image_info_t
*info
,
1215 const unsigned char **mime_data
,
1216 unsigned long *mime_data_length
)
1218 cairo_surface_get_mime_data (source
, CAIRO_MIME_TYPE_JP2
,
1219 mime_data
, mime_data_length
);
1220 if (*mime_data
== NULL
)
1221 return CAIRO_INT_STATUS_UNSUPPORTED
;
1223 return _cairo_image_info_get_jpx_info (info
, *mime_data
, *mime_data_length
);
1226 static cairo_int_status_t
1227 _get_jpeg_image_info (cairo_surface_t
*source
,
1228 cairo_image_info_t
*info
,
1229 const unsigned char **mime_data
,
1230 unsigned long *mime_data_length
)
1232 cairo_surface_get_mime_data (source
, CAIRO_MIME_TYPE_JPEG
,
1233 mime_data
, mime_data_length
);
1234 if (*mime_data
== NULL
)
1235 return CAIRO_INT_STATUS_UNSUPPORTED
;
1237 return _cairo_image_info_get_jpeg_info (info
, *mime_data
, *mime_data_length
);
1240 static cairo_int_status_t
1241 _get_source_surface_size (cairo_surface_t
*source
,
1244 cairo_rectangle_int_t
*extents
)
1246 cairo_int_status_t status
;
1247 cairo_image_info_t info
;
1248 const unsigned char *mime_data
;
1249 unsigned long mime_data_length
;
1251 if (source
->type
== CAIRO_SURFACE_TYPE_RECORDING
) {
1252 if (source
->backend
->type
== CAIRO_SURFACE_TYPE_SUBSURFACE
) {
1253 cairo_surface_subsurface_t
*sub
= (cairo_surface_subsurface_t
*) source
;
1255 *extents
= sub
->extents
;
1256 *width
= extents
->width
;
1257 *height
= extents
->height
;
1259 cairo_surface_t
*free_me
= NULL
;
1260 cairo_rectangle_int_t surf_extents
;
1262 cairo_bool_t bounded
;
1264 if (_cairo_surface_is_snapshot (source
))
1265 free_me
= source
= _cairo_surface_snapshot_get_target (source
);
1267 status
= _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t
*)source
,
1269 if (unlikely (status
)) {
1270 cairo_surface_destroy (free_me
);
1274 bounded
= _cairo_surface_get_extents (source
, &surf_extents
);
1275 cairo_surface_destroy (free_me
);
1277 *width
= surf_extents
.width
;
1278 *height
= surf_extents
.height
;
1280 _cairo_box_round_to_rectangle (&box
, extents
);
1283 return CAIRO_STATUS_SUCCESS
;
1289 status
= _get_jbig2_image_info (source
, &info
, &mime_data
, &mime_data_length
);
1290 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
) {
1291 *width
= info
.width
;
1292 *height
= info
.height
;
1293 extents
->width
= info
.width
;
1294 extents
->height
= info
.height
;
1298 status
= _get_jpx_image_info (source
, &info
, &mime_data
, &mime_data_length
);
1299 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
) {
1300 *width
= info
.width
;
1301 *height
= info
.height
;
1302 extents
->width
= info
.width
;
1303 extents
->height
= info
.height
;
1307 status
= _get_jpeg_image_info (source
, &info
, &mime_data
, &mime_data_length
);
1308 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
) {
1309 *width
= info
.width
;
1310 *height
= info
.height
;
1311 extents
->width
= info
.width
;
1312 extents
->height
= info
.height
;
1316 if (! _cairo_surface_get_extents (source
, extents
))
1317 return CAIRO_INT_STATUS_UNSUPPORTED
;
1319 *width
= extents
->width
;
1320 *height
= extents
->height
;
1322 return CAIRO_STATUS_SUCCESS
;
1326 * _cairo_pdf_surface_add_source_surface:
1327 * @surface: the pdf surface
1328 * @source_surface: A #cairo_surface_t to use as the source surface
1329 * @source_pattern: A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source
1330 * @op: the operator used to composite this source
1331 * @filter: filter type of the source pattern
1332 * @stencil_mask: if true, the surface will be written to the PDF as an /ImageMask
1333 * @smask: if true, only the alpha channel will be written (images only)
1334 * @extents: extents of the operation that is using this source
1335 * @smask_res: if not NULL, the image written will specify this resource as the smask for the image (images only)
1336 * @surface_res: return PDF resource number of the surface
1337 * @width: returns width of surface
1338 * @height: returns height of surface
1339 * @x_offset: x offset of surface
1340 * @t_offset: y offset of surface
1341 * @source_extents: returns extents of source (either ink extents or extents needed to cover @extents)
1343 * Add surface or raster_source pattern to list of surfaces to be
1344 * written to the PDF file when the current page is finished. Returns
1345 * a PDF resource to reference the image. A hash table of all images
1346 * in the PDF files (keyed by CAIRO_MIME_TYPE_UNIQUE_ID or surface
1347 * unique_id) to ensure surfaces with the same id are only written
1348 * once to the PDF file.
1350 * Only one of @source_pattern or @source_surface is to be
1351 * specified. Set the other to NULL.
1353 static cairo_int_status_t
1354 _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t
*surface
,
1355 cairo_surface_t
*source_surface
,
1356 const cairo_pattern_t
*source_pattern
,
1357 cairo_operator_t op
,
1358 cairo_filter_t filter
,
1359 cairo_bool_t stencil_mask
,
1361 const cairo_rectangle_int_t
*extents
,
1362 cairo_pdf_resource_t
*smask_res
,
1363 cairo_pdf_resource_t
*surface_res
,
1368 cairo_rectangle_int_t
*source_extents
)
1370 cairo_pdf_source_surface_t src_surface
;
1371 cairo_pdf_source_surface_entry_t surface_key
;
1372 cairo_pdf_source_surface_entry_t
*surface_entry
;
1373 cairo_int_status_t status
;
1374 cairo_bool_t interpolate
;
1375 unsigned char *unique_id
= NULL
;
1376 unsigned long unique_id_length
= 0;
1377 cairo_image_surface_t
*image
;
1382 case CAIRO_FILTER_GOOD
:
1383 case CAIRO_FILTER_BEST
:
1384 case CAIRO_FILTER_BILINEAR
:
1387 case CAIRO_FILTER_FAST
:
1388 case CAIRO_FILTER_NEAREST
:
1389 case CAIRO_FILTER_GAUSSIAN
:
1390 interpolate
= FALSE
;
1396 if (source_pattern
) {
1397 if (source_pattern
->type
== CAIRO_PATTERN_TYPE_RASTER_SOURCE
) {
1398 status
= _cairo_pdf_surface_acquire_source_image_from_pattern (surface
, source_pattern
,
1399 &image
, &image_extra
);
1400 if (unlikely (status
))
1402 source_surface
= &image
->base
;
1403 cairo_surface_get_device_offset (source_surface
, x_offset
, y_offset
);
1405 cairo_surface_pattern_t
*surface_pattern
= (cairo_surface_pattern_t
*) source_pattern
;
1406 source_surface
= surface_pattern
->surface
;
1410 surface_key
.id
= source_surface
->unique_id
;
1411 surface_key
.interpolate
= interpolate
;
1412 cairo_surface_get_mime_data (source_surface
, CAIRO_MIME_TYPE_UNIQUE_ID
,
1413 (const unsigned char **) &surface_key
.unique_id
,
1414 &surface_key
.unique_id_length
);
1415 _cairo_pdf_source_surface_init_key (&surface_key
);
1416 surface_entry
= _cairo_hash_table_lookup (surface
->all_surfaces
, &surface_key
.base
);
1417 if (surface_entry
) {
1418 *surface_res
= surface_entry
->surface_res
;
1419 *width
= surface_entry
->width
;
1420 *height
= surface_entry
->height
;
1421 *source_extents
= surface_entry
->extents
;
1422 status
= CAIRO_STATUS_SUCCESS
;
1424 status
= _get_source_surface_size (source_surface
,
1428 if (unlikely(status
))
1429 goto release_source
;
1431 if (surface_key
.unique_id
&& surface_key
.unique_id_length
> 0) {
1432 unique_id
= _cairo_malloc (surface_key
.unique_id_length
);
1433 if (unique_id
== NULL
) {
1434 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1435 goto release_source
;
1438 unique_id_length
= surface_key
.unique_id_length
;
1439 memcpy (unique_id
, surface_key
.unique_id
, unique_id_length
);
1442 unique_id_length
= 0;
1447 if (source_pattern
&& source_pattern
->type
== CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
1448 _cairo_pdf_surface_release_source_image_from_pattern (surface
, source_pattern
, image
, image_extra
);
1450 if (status
|| surface_entry
)
1453 surface_entry
= malloc (sizeof (cairo_pdf_source_surface_entry_t
));
1454 if (surface_entry
== NULL
) {
1455 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1459 surface_entry
->id
= surface_key
.id
;
1460 surface_entry
->operator = op
;
1461 surface_entry
->interpolate
= interpolate
;
1462 surface_entry
->stencil_mask
= stencil_mask
;
1463 surface_entry
->smask
= smask
;
1464 surface_entry
->unique_id_length
= unique_id_length
;
1465 surface_entry
->unique_id
= unique_id
;
1466 surface_entry
->width
= *width
;
1467 surface_entry
->height
= *height
;
1468 surface_entry
->extents
= *source_extents
;
1470 surface_entry
->smask_res
= *smask_res
;
1472 surface_entry
->smask_res
.id
= 0;
1473 _cairo_pdf_source_surface_init_key (surface_entry
);
1475 src_surface
.hash_entry
= surface_entry
;
1476 if (source_pattern
&& source_pattern
->type
== CAIRO_PATTERN_TYPE_RASTER_SOURCE
) {
1477 src_surface
.type
= CAIRO_PATTERN_TYPE_RASTER_SOURCE
;
1478 src_surface
.surface
= NULL
;
1479 status
= _cairo_pattern_create_copy (&src_surface
.raster_pattern
, source_pattern
);
1480 if (unlikely (status
))
1484 src_surface
.type
= CAIRO_PATTERN_TYPE_SURFACE
;
1485 src_surface
.surface
= cairo_surface_reference (source_surface
);
1486 src_surface
.raster_pattern
= NULL
;
1489 surface_entry
->surface_res
= _cairo_pdf_surface_new_object (surface
);
1490 if (surface_entry
->surface_res
.id
== 0) {
1491 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1495 status
= _cairo_array_append (&surface
->page_surfaces
, &src_surface
);
1496 if (unlikely (status
))
1499 status
= _cairo_hash_table_insert (surface
->all_surfaces
,
1500 &surface_entry
->base
);
1501 if (unlikely(status
))
1504 *surface_res
= surface_entry
->surface_res
;
1509 if (source_pattern
&& source_pattern
->type
== CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
1510 cairo_pattern_destroy (src_surface
.raster_pattern
);
1512 cairo_surface_destroy (src_surface
.surface
);
1515 free (surface_entry
);
1523 static cairo_int_status_t
1524 _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t
*surface
,
1525 const cairo_pattern_t
*pattern
,
1526 cairo_operator_t op
,
1527 const cairo_rectangle_int_t
*extents
,
1528 cairo_bool_t is_shading
,
1529 cairo_pdf_resource_t
*pattern_res
,
1530 cairo_pdf_resource_t
*gstate_res
)
1532 cairo_pdf_pattern_t pdf_pattern
;
1533 cairo_int_status_t status
;
1535 pdf_pattern
.is_shading
= is_shading
;
1536 pdf_pattern
.operator = op
;
1538 /* Solid colors are emitted into the content stream */
1539 if (pattern
->type
== CAIRO_PATTERN_TYPE_SOLID
) {
1540 pattern_res
->id
= 0;
1542 return CAIRO_INT_STATUS_SUCCESS
;
1545 status
= _cairo_pattern_create_copy (&pdf_pattern
.pattern
, pattern
);
1546 if (unlikely (status
))
1549 pdf_pattern
.pattern_res
= _cairo_pdf_surface_new_object (surface
);
1550 if (pdf_pattern
.pattern_res
.id
== 0) {
1551 cairo_pattern_destroy (pdf_pattern
.pattern
);
1552 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1555 pdf_pattern
.gstate_res
.id
= 0;
1557 /* gradient patterns require an smask object to implement transparency */
1558 if (pattern
->type
== CAIRO_PATTERN_TYPE_LINEAR
||
1559 pattern
->type
== CAIRO_PATTERN_TYPE_RADIAL
||
1560 pattern
->type
== CAIRO_PATTERN_TYPE_MESH
)
1564 _cairo_pattern_alpha_range (pattern
, &min_alpha
, NULL
);
1565 if (! CAIRO_ALPHA_IS_OPAQUE (min_alpha
)) {
1566 pdf_pattern
.gstate_res
= _cairo_pdf_surface_new_object (surface
);
1567 if (pdf_pattern
.gstate_res
.id
== 0) {
1568 cairo_pattern_destroy (pdf_pattern
.pattern
);
1569 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1574 pdf_pattern
.width
= surface
->width
;
1575 pdf_pattern
.height
= surface
->height
;
1576 if (extents
!= NULL
) {
1577 pdf_pattern
.extents
= *extents
;
1579 pdf_pattern
.extents
.x
= 0;
1580 pdf_pattern
.extents
.y
= 0;
1581 pdf_pattern
.extents
.width
= surface
->width
;
1582 pdf_pattern
.extents
.height
= surface
->height
;
1585 *pattern_res
= pdf_pattern
.pattern_res
;
1586 *gstate_res
= pdf_pattern
.gstate_res
;
1588 status
= _cairo_array_append (&surface
->page_patterns
, &pdf_pattern
);
1589 if (unlikely (status
)) {
1590 cairo_pattern_destroy (pdf_pattern
.pattern
);
1594 return CAIRO_INT_STATUS_SUCCESS
;
1597 /* Get BBox in PDF coordinates from extents in cairo coordinates */
1599 _get_bbox_from_extents (double surface_height
,
1600 const cairo_rectangle_int_t
*extents
,
1601 cairo_box_double_t
*bbox
)
1603 bbox
->p1
.x
= extents
->x
;
1604 bbox
->p1
.y
= surface_height
- (extents
->y
+ extents
->height
);
1605 bbox
->p2
.x
= extents
->x
+ extents
->width
;
1606 bbox
->p2
.y
= surface_height
- extents
->y
;
1609 static cairo_int_status_t
1610 _cairo_pdf_surface_add_pdf_shading (cairo_pdf_surface_t
*surface
,
1611 const cairo_pattern_t
*pattern
,
1612 cairo_operator_t op
,
1613 const cairo_rectangle_int_t
*extents
,
1614 cairo_pdf_resource_t
*shading_res
,
1615 cairo_pdf_resource_t
*gstate_res
)
1617 return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface
,
1626 static cairo_int_status_t
1627 _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t
*surface
,
1628 const cairo_pattern_t
*pattern
,
1629 cairo_operator_t op
,
1630 const cairo_rectangle_int_t
*extents
,
1631 cairo_pdf_resource_t
*pattern_res
,
1632 cairo_pdf_resource_t
*gstate_res
)
1634 return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface
,
1643 static cairo_int_status_t
1644 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t
*surface
,
1645 cairo_pdf_resource_t
*resource
,
1646 cairo_bool_t compressed
,
1651 cairo_pdf_resource_t self
, length
;
1652 cairo_output_stream_t
*output
= NULL
;
1656 _cairo_pdf_surface_update_object (surface
, self
);
1658 self
= _cairo_pdf_surface_new_object (surface
);
1660 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1663 length
= _cairo_pdf_surface_new_object (surface
);
1665 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1668 output
= _cairo_deflate_stream_create (surface
->output
);
1669 if (_cairo_output_stream_get_status (output
))
1670 return _cairo_output_stream_destroy (output
);
1673 surface
->pdf_stream
.active
= TRUE
;
1674 surface
->pdf_stream
.self
= self
;
1675 surface
->pdf_stream
.length
= length
;
1676 surface
->pdf_stream
.compressed
= compressed
;
1677 surface
->current_pattern_is_solid_color
= FALSE
;
1678 surface
->current_operator
= CAIRO_OPERATOR_OVER
;
1679 _cairo_pdf_operators_reset (&surface
->pdf_operators
);
1681 _cairo_output_stream_printf (surface
->output
,
1683 "<< /Length %d 0 R\n",
1684 surface
->pdf_stream
.self
.id
,
1685 surface
->pdf_stream
.length
.id
);
1687 _cairo_output_stream_printf (surface
->output
,
1688 " /Filter /FlateDecode\n");
1692 _cairo_output_stream_vprintf (surface
->output
, fmt
, ap
);
1696 _cairo_output_stream_printf (surface
->output
,
1700 surface
->pdf_stream
.start_offset
= _cairo_output_stream_get_position (surface
->output
);
1703 assert (surface
->pdf_stream
.old_output
== NULL
);
1704 surface
->pdf_stream
.old_output
= surface
->output
;
1705 surface
->output
= output
;
1706 _cairo_pdf_operators_set_stream (&surface
->pdf_operators
, surface
->output
);
1709 return _cairo_output_stream_get_status (surface
->output
);
1712 static cairo_int_status_t
1713 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t
*surface
)
1715 cairo_int_status_t status
;
1718 if (! surface
->pdf_stream
.active
)
1719 return CAIRO_INT_STATUS_SUCCESS
;
1721 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
1723 if (surface
->pdf_stream
.compressed
) {
1724 cairo_int_status_t status2
;
1726 status2
= _cairo_output_stream_destroy (surface
->output
);
1727 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
))
1730 surface
->output
= surface
->pdf_stream
.old_output
;
1731 _cairo_pdf_operators_set_stream (&surface
->pdf_operators
, surface
->output
);
1732 surface
->pdf_stream
.old_output
= NULL
;
1735 length
= _cairo_output_stream_get_position (surface
->output
) -
1736 surface
->pdf_stream
.start_offset
;
1737 _cairo_output_stream_printf (surface
->output
,
1742 _cairo_pdf_surface_update_object (surface
,
1743 surface
->pdf_stream
.length
);
1744 _cairo_output_stream_printf (surface
->output
,
1748 surface
->pdf_stream
.length
.id
,
1751 surface
->pdf_stream
.active
= FALSE
;
1753 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
))
1754 status
= _cairo_output_stream_get_status (surface
->output
);
1760 _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t
*surface
,
1761 cairo_output_stream_t
*mem_stream
,
1762 cairo_pdf_resource_t resource
,
1763 cairo_pdf_group_resources_t
*resources
,
1764 cairo_bool_t is_knockout_group
,
1765 const cairo_box_double_t
*bbox
)
1767 _cairo_pdf_surface_update_object (surface
, resource
);
1769 _cairo_output_stream_printf (surface
->output
,
1771 "<< /Type /XObject\n"
1774 _cairo_memory_stream_length (mem_stream
));
1776 if (surface
->compress_content
) {
1777 _cairo_output_stream_printf (surface
->output
,
1778 " /Filter /FlateDecode\n");
1781 _cairo_output_stream_printf (surface
->output
,
1783 " /BBox [ %f %f %f %f ]\n"
1786 " /S /Transparency\n"
1788 " /CS /DeviceRGB\n",
1789 bbox
->p1
.x
, bbox
->p1
.y
, bbox
->p2
.x
, bbox
->p2
.y
);
1791 if (is_knockout_group
)
1792 _cairo_output_stream_printf (surface
->output
,
1795 _cairo_output_stream_printf (surface
->output
,
1798 _cairo_pdf_surface_emit_group_resources (surface
, resources
);
1799 _cairo_output_stream_printf (surface
->output
,
1802 _cairo_memory_stream_copy (mem_stream
, surface
->output
);
1803 _cairo_output_stream_printf (surface
->output
,
1808 static cairo_int_status_t
1809 _cairo_pdf_surface_open_group (cairo_pdf_surface_t
*surface
,
1810 const cairo_box_double_t
*bbox
,
1811 cairo_pdf_resource_t
*resource
)
1813 cairo_int_status_t status
;
1815 assert (surface
->pdf_stream
.active
== FALSE
);
1816 assert (surface
->group_stream
.active
== FALSE
);
1818 surface
->group_stream
.active
= TRUE
;
1819 surface
->current_pattern_is_solid_color
= FALSE
;
1820 surface
->current_operator
= CAIRO_OPERATOR_OVER
;
1821 _cairo_pdf_operators_reset (&surface
->pdf_operators
);
1823 surface
->group_stream
.mem_stream
= _cairo_memory_stream_create ();
1825 if (surface
->compress_content
) {
1826 surface
->group_stream
.stream
=
1827 _cairo_deflate_stream_create (surface
->group_stream
.mem_stream
);
1829 surface
->group_stream
.stream
= surface
->group_stream
.mem_stream
;
1831 status
= _cairo_output_stream_get_status (surface
->group_stream
.stream
);
1833 surface
->group_stream
.old_output
= surface
->output
;
1834 surface
->output
= surface
->group_stream
.stream
;
1835 _cairo_pdf_operators_set_stream (&surface
->pdf_operators
, surface
->output
);
1836 _cairo_pdf_group_resources_clear (&surface
->resources
);
1839 surface
->group_stream
.resource
= *resource
;
1841 surface
->group_stream
.resource
= _cairo_pdf_surface_new_object (surface
);
1842 if (surface
->group_stream
.resource
.id
== 0)
1843 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1845 surface
->group_stream
.is_knockout
= FALSE
;
1846 surface
->group_stream
.bbox
= *bbox
;
1851 static cairo_int_status_t
1852 _cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t
*surface
,
1853 const cairo_box_double_t
*bbox
)
1855 cairo_int_status_t status
;
1857 status
= _cairo_pdf_surface_open_group (surface
, bbox
, NULL
);
1858 if (unlikely (status
))
1861 surface
->group_stream
.is_knockout
= TRUE
;
1863 return CAIRO_INT_STATUS_SUCCESS
;
1866 static cairo_int_status_t
1867 _cairo_pdf_surface_close_group (cairo_pdf_surface_t
*surface
,
1868 cairo_pdf_resource_t
*group
)
1870 cairo_int_status_t status
= CAIRO_INT_STATUS_SUCCESS
, status2
;
1872 assert (surface
->pdf_stream
.active
== FALSE
);
1873 assert (surface
->group_stream
.active
== TRUE
);
1875 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
1876 if (unlikely (status
))
1879 if (surface
->compress_content
) {
1880 status
= _cairo_output_stream_destroy (surface
->group_stream
.stream
);
1881 surface
->group_stream
.stream
= NULL
;
1883 _cairo_output_stream_printf (surface
->group_stream
.mem_stream
,
1886 surface
->output
= surface
->group_stream
.old_output
;
1887 _cairo_pdf_operators_set_stream (&surface
->pdf_operators
, surface
->output
);
1888 surface
->group_stream
.active
= FALSE
;
1889 _cairo_pdf_surface_write_memory_stream (surface
,
1890 surface
->group_stream
.mem_stream
,
1891 surface
->group_stream
.resource
,
1892 &surface
->resources
,
1893 surface
->group_stream
.is_knockout
,
1894 &surface
->group_stream
.bbox
);
1896 *group
= surface
->group_stream
.resource
;
1898 status2
= _cairo_output_stream_destroy (surface
->group_stream
.mem_stream
);
1899 if (status
== CAIRO_INT_STATUS_SUCCESS
)
1902 surface
->group_stream
.mem_stream
= NULL
;
1903 surface
->group_stream
.stream
= NULL
;
1908 static cairo_int_status_t
1909 _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t
*surface
,
1910 const cairo_box_double_t
*bbox
,
1911 cairo_pdf_resource_t
*resource
,
1912 cairo_bool_t is_form
,
1913 cairo_bool_t is_group
)
1915 cairo_int_status_t status
;
1917 assert (surface
->pdf_stream
.active
== FALSE
);
1918 assert (surface
->group_stream
.active
== FALSE
);
1920 surface
->content_resources
= _cairo_pdf_surface_new_object (surface
);
1921 if (surface
->content_resources
.id
== 0)
1922 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1925 assert (bbox
!= NULL
);
1929 _cairo_pdf_surface_open_stream (surface
,
1931 surface
->compress_content
,
1934 " /BBox [ %f %f %f %f ]\n"
1937 " /S /Transparency\n"
1941 " /Resources %d 0 R\n",
1946 surface
->content_resources
.id
);
1949 _cairo_pdf_surface_open_stream (surface
,
1951 surface
->compress_content
,
1954 " /BBox [ %f %f %f %f ]\n"
1955 " /Resources %d 0 R\n",
1960 surface
->content_resources
.id
);
1964 _cairo_pdf_surface_open_stream (surface
,
1966 surface
->compress_content
,
1969 if (unlikely (status
))
1972 surface
->content
= surface
->pdf_stream
.self
;
1974 _cairo_output_stream_printf (surface
->output
, "q\n");
1976 return _cairo_output_stream_get_status (surface
->output
);
1979 static cairo_int_status_t
1980 _cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t
*surface
)
1982 cairo_int_status_t status
;
1984 assert (surface
->pdf_stream
.active
== TRUE
);
1985 assert (surface
->group_stream
.active
== FALSE
);
1987 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
1988 if (unlikely (status
))
1991 _cairo_output_stream_printf (surface
->output
, "Q\n");
1992 status
= _cairo_pdf_surface_close_stream (surface
);
1993 if (unlikely (status
))
1996 _cairo_pdf_surface_update_object (surface
, surface
->content_resources
);
1997 _cairo_output_stream_printf (surface
->output
,
1999 surface
->content_resources
.id
);
2000 _cairo_pdf_surface_emit_group_resources (surface
, &surface
->resources
);
2001 _cairo_output_stream_printf (surface
->output
,
2004 return _cairo_output_stream_get_status (surface
->output
);
2008 _cairo_pdf_source_surface_entry_pluck (void *entry
, void *closure
)
2010 cairo_pdf_source_surface_entry_t
*surface_entry
= entry
;
2011 cairo_hash_table_t
*patterns
= closure
;
2013 _cairo_hash_table_remove (patterns
, &surface_entry
->base
);
2014 free (surface_entry
->unique_id
);
2016 free (surface_entry
);
2019 static cairo_status_t
2020 _cairo_pdf_surface_finish (void *abstract_surface
)
2022 cairo_pdf_surface_t
*surface
= abstract_surface
;
2024 cairo_pdf_resource_t info
, catalog
;
2025 cairo_status_t status
, status2
;
2027 cairo_pdf_jbig2_global_t
*global
;
2029 status
= surface
->base
.status
;
2030 if (status
== CAIRO_STATUS_SUCCESS
)
2031 status
= _cairo_pdf_surface_emit_font_subsets (surface
);
2033 _cairo_pdf_surface_write_pages (surface
);
2035 info
= _cairo_pdf_surface_write_info (surface
);
2036 if (info
.id
== 0 && status
== CAIRO_STATUS_SUCCESS
)
2037 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2039 catalog
= _cairo_pdf_surface_write_catalog (surface
);
2040 if (catalog
.id
== 0 && status
== CAIRO_STATUS_SUCCESS
)
2041 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2043 offset
= _cairo_pdf_surface_write_xref (surface
);
2045 _cairo_output_stream_printf (surface
->output
,
2051 surface
->next_available_resource
.id
,
2055 _cairo_output_stream_printf (surface
->output
,
2061 /* pdf_operators has already been flushed when the last stream was
2062 * closed so we should never be writing anything here - however,
2063 * the stream may itself be in an error state. */
2064 status2
= _cairo_pdf_operators_fini (&surface
->pdf_operators
);
2065 if (status
== CAIRO_STATUS_SUCCESS
)
2068 /* close any active streams still open due to fatal errors */
2069 status2
= _cairo_pdf_surface_close_stream (surface
);
2070 if (status
== CAIRO_STATUS_SUCCESS
)
2073 if (surface
->group_stream
.stream
!= NULL
) {
2074 status2
= _cairo_output_stream_destroy (surface
->group_stream
.stream
);
2075 if (status
== CAIRO_STATUS_SUCCESS
)
2078 if (surface
->group_stream
.mem_stream
!= NULL
) {
2079 status2
= _cairo_output_stream_destroy (surface
->group_stream
.mem_stream
);
2080 if (status
== CAIRO_STATUS_SUCCESS
)
2083 if (surface
->pdf_stream
.active
)
2084 surface
->output
= surface
->pdf_stream
.old_output
;
2085 if (surface
->group_stream
.active
)
2086 surface
->output
= surface
->group_stream
.old_output
;
2088 /* and finish the pdf surface */
2089 status2
= _cairo_output_stream_destroy (surface
->output
);
2090 if (status
== CAIRO_STATUS_SUCCESS
)
2093 _cairo_pdf_surface_clear (surface
);
2094 _cairo_pdf_group_resources_fini (&surface
->resources
);
2096 _cairo_array_fini (&surface
->objects
);
2097 _cairo_array_fini (&surface
->pages
);
2098 _cairo_array_fini (&surface
->rgb_linear_functions
);
2099 _cairo_array_fini (&surface
->alpha_linear_functions
);
2100 _cairo_array_fini (&surface
->page_patterns
);
2101 _cairo_array_fini (&surface
->page_surfaces
);
2102 _cairo_hash_table_foreach (surface
->all_surfaces
,
2103 _cairo_pdf_source_surface_entry_pluck
,
2104 surface
->all_surfaces
);
2105 _cairo_hash_table_destroy (surface
->all_surfaces
);
2106 _cairo_array_fini (&surface
->smask_groups
);
2107 _cairo_array_fini (&surface
->fonts
);
2108 _cairo_array_fini (&surface
->knockout_group
);
2110 if (surface
->font_subsets
) {
2111 _cairo_scaled_font_subsets_destroy (surface
->font_subsets
);
2112 surface
->font_subsets
= NULL
;
2115 size
= _cairo_array_num_elements (&surface
->jbig2_global
);
2116 for (i
= 0; i
< size
; i
++) {
2117 global
= (cairo_pdf_jbig2_global_t
*) _cairo_array_index (&surface
->jbig2_global
, i
);
2119 if (!global
->emitted
)
2120 return _cairo_error (CAIRO_STATUS_JBIG2_GLOBAL_MISSING
);
2122 _cairo_array_fini (&surface
->jbig2_global
);
2124 _cairo_array_truncate (&surface
->page_surfaces
, 0);
2126 _cairo_surface_clipper_reset (&surface
->clipper
);
2131 static cairo_int_status_t
2132 _cairo_pdf_surface_start_page (void *abstract_surface
)
2134 cairo_pdf_surface_t
*surface
= abstract_surface
;
2136 /* Document header */
2137 if (! surface
->header_emitted
) {
2138 const char *version
;
2140 switch (surface
->pdf_version
) {
2141 case CAIRO_PDF_VERSION_1_4
:
2145 case CAIRO_PDF_VERSION_1_5
:
2150 _cairo_output_stream_printf (surface
->output
,
2151 "%%PDF-%s\n", version
);
2152 _cairo_output_stream_printf (surface
->output
,
2153 "%%%c%c%c%c\n", 181, 237, 174, 251);
2154 surface
->header_emitted
= TRUE
;
2157 _cairo_pdf_group_resources_clear (&surface
->resources
);
2159 return CAIRO_STATUS_SUCCESS
;
2162 static cairo_int_status_t
2163 _cairo_pdf_surface_has_fallback_images (void *abstract_surface
,
2164 cairo_bool_t has_fallbacks
)
2166 cairo_int_status_t status
;
2167 cairo_pdf_surface_t
*surface
= abstract_surface
;
2168 cairo_box_double_t bbox
;
2170 surface
->has_fallback_images
= has_fallbacks
;
2173 bbox
.p2
.x
= surface
->width
;
2174 bbox
.p2
.y
= surface
->height
;
2175 status
= _cairo_pdf_surface_open_content_stream (surface
, &bbox
, NULL
, has_fallbacks
, has_fallbacks
);
2176 if (unlikely (status
))
2179 return CAIRO_STATUS_SUCCESS
;
2183 _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface
)
2188 static cairo_int_status_t
2189 _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t
*surface
,
2190 const cairo_pattern_t
*source
,
2191 const cairo_rectangle_int_t
*extents
,
2192 cairo_pdf_resource_t
*surface_res
,
2198 cairo_image_surface_t
*image
;
2199 cairo_surface_t
*pad_image
;
2201 cairo_int_status_t status
;
2203 cairo_rectangle_int_t extents2
;
2205 cairo_rectangle_int_t rect
;
2206 cairo_surface_pattern_t pad_pattern
;
2208 status
= _cairo_pdf_surface_acquire_source_image_from_pattern (surface
, source
,
2209 &image
, &image_extra
);
2210 if (unlikely (status
))
2213 pad_image
= &image
->base
;
2215 /* get the operation extents in pattern space */
2216 _cairo_box_from_rectangle (&box
, extents
);
2217 _cairo_matrix_transform_bounding_box_fixed (&source
->matrix
, &box
, NULL
);
2218 _cairo_box_round_to_rectangle (&box
, &rect
);
2220 /* Check if image needs padding to fill extents */
2223 if (_cairo_fixed_integer_ceil(box
.p1
.x
) < 0 ||
2224 _cairo_fixed_integer_ceil(box
.p1
.y
) < 0 ||
2225 _cairo_fixed_integer_floor(box
.p2
.x
) > w
||
2226 _cairo_fixed_integer_floor(box
.p2
.y
) > h
)
2228 pad_image
= _cairo_image_surface_create_with_content (image
->base
.content
,
2231 if (pad_image
->status
) {
2232 status
= pad_image
->status
;
2236 _cairo_pattern_init_for_surface (&pad_pattern
, &image
->base
);
2237 cairo_matrix_init_translate (&pad_pattern
.base
.matrix
, rect
.x
, rect
.y
);
2238 pad_pattern
.base
.extend
= CAIRO_EXTEND_PAD
;
2239 status
= _cairo_surface_paint (pad_image
,
2240 CAIRO_OPERATOR_SOURCE
, &pad_pattern
.base
,
2242 _cairo_pattern_fini (&pad_pattern
.base
);
2243 if (unlikely (status
))
2247 status
= _cairo_pdf_surface_add_source_surface (surface
,
2262 if (unlikely (status
))
2265 if (pad_image
!= &image
->base
) {
2266 /* If using a padded image, replace _add_source_surface
2267 * x/y_offset with padded image offset. Note:
2268 * _add_source_surface only sets a non zero x/y_offset for
2269 * RASTER_SOURCE patterns. _add_source_surface will always set
2270 * x/y_offset to 0 for surfaces so we can ignore the returned
2271 * offset and replace it with the offset required for the
2278 if (pad_image
!= &image
->base
)
2279 cairo_surface_destroy (pad_image
);
2281 _cairo_pdf_surface_release_source_image_from_pattern (surface
, source
, image
, image_extra
);
2286 /* Emit alpha channel from the image into stream_res.
2288 static cairo_int_status_t
2289 _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t
*surface
,
2290 cairo_image_surface_t
*image
,
2291 cairo_bool_t stencil_mask
,
2292 cairo_bool_t interpolate
,
2293 cairo_pdf_resource_t
*stream_res
)
2295 cairo_int_status_t status
= CAIRO_STATUS_SUCCESS
;
2297 unsigned long alpha_size
;
2300 int i
, x
, y
, bit
, a
;
2301 cairo_image_transparency_t transparency
;
2303 /* This is the only image format we support, which simplifies things. */
2304 assert (image
->format
== CAIRO_FORMAT_ARGB32
||
2305 image
->format
== CAIRO_FORMAT_RGB24
||
2306 image
->format
== CAIRO_FORMAT_A8
||
2307 image
->format
== CAIRO_FORMAT_A1
);
2309 transparency
= _cairo_image_analyze_transparency (image
);
2311 assert (transparency
== CAIRO_IMAGE_IS_OPAQUE
||
2312 transparency
== CAIRO_IMAGE_HAS_BILEVEL_ALPHA
);
2314 assert (transparency
!= CAIRO_IMAGE_IS_OPAQUE
);
2317 if (transparency
== CAIRO_IMAGE_HAS_BILEVEL_ALPHA
|| transparency
== CAIRO_IMAGE_IS_OPAQUE
) {
2318 alpha_size
= (image
->width
+ 7) / 8 * image
->height
;
2319 alpha
= _cairo_malloc_ab ((image
->width
+7) / 8, image
->height
);
2321 alpha_size
= image
->height
* image
->width
;
2322 alpha
= _cairo_malloc_ab (image
->height
, image
->width
);
2325 if (unlikely (alpha
== NULL
)) {
2326 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2331 for (y
= 0; y
< image
->height
; y
++) {
2332 if (transparency
== CAIRO_IMAGE_IS_OPAQUE
) {
2333 for (x
= 0; x
< (image
->width
+ 7) / 8; x
++)
2335 } else if (image
->format
== CAIRO_FORMAT_A1
) {
2336 pixel8
= (uint8_t *) (image
->data
+ y
* image
->stride
);
2338 for (x
= 0; x
< (image
->width
+ 7) / 8; x
++, pixel8
++) {
2340 a
= CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a
);
2344 pixel8
= (uint8_t *) (image
->data
+ y
* image
->stride
);
2345 pixel32
= (uint32_t *) (image
->data
+ y
* image
->stride
);
2347 for (x
= 0; x
< image
->width
; x
++) {
2348 if (image
->format
== CAIRO_FORMAT_ARGB32
) {
2349 a
= (*pixel32
& 0xff000000) >> 24;
2356 if (transparency
== CAIRO_IMAGE_HAS_ALPHA
) {
2358 } else { /* transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA or CAIRO_IMAGE_IS_OPAQUE */
2362 alpha
[i
] |= (1 << bit
);
2376 status
= _cairo_pdf_surface_open_stream (surface
,
2380 " /Subtype /Image\n"
2381 " /ImageMask true\n"
2384 " /Interpolate %s\n"
2385 " /BitsPerComponent 1\n"
2387 image
->width
, image
->height
,
2388 interpolate
? "true" : "false");
2390 status
= _cairo_pdf_surface_open_stream (surface
,
2394 " /Subtype /Image\n"
2397 " /ColorSpace /DeviceGray\n"
2398 " /Interpolate %s\n"
2399 " /BitsPerComponent %d\n",
2400 image
->width
, image
->height
,
2401 interpolate
? "true" : "false",
2402 transparency
== CAIRO_IMAGE_HAS_ALPHA
? 8 : 1);
2404 if (unlikely (status
))
2407 _cairo_output_stream_write (surface
->output
, alpha
, alpha_size
);
2408 status
= _cairo_pdf_surface_close_stream (surface
);
2417 * _cairo_pdf_surface_emit_image:
2418 * @surface: the pdf surface
2419 * @image_surf: The image to write
2420 * @surface_entry: Contains image resource, smask resource, interpolate and stencil mask parameters.
2422 * Emit an image stream using the @image_res resource and write out
2423 * the image data from @image_surf. If @smask_res is not null, @smask_res will
2424 * be specified as the smask for the image. Otherwise emit the an smask if
2425 * the image is requires one.
2427 static cairo_int_status_t
2428 _cairo_pdf_surface_emit_image (cairo_pdf_surface_t
*surface
,
2429 cairo_image_surface_t
*image_surf
,
2430 cairo_pdf_source_surface_entry_t
*surface_entry
)
2432 cairo_int_status_t status
= CAIRO_STATUS_SUCCESS
;
2434 unsigned long data_size
;
2437 cairo_pdf_resource_t smask
= {0}; /* squelch bogus compiler warning */
2438 cairo_bool_t need_smask
;
2439 cairo_image_color_t color
;
2440 cairo_image_surface_t
*image
;
2441 cairo_image_transparency_t transparency
;
2445 if (image
->format
!= CAIRO_FORMAT_RGB24
&&
2446 image
->format
!= CAIRO_FORMAT_ARGB32
&&
2447 image
->format
!= CAIRO_FORMAT_A8
&&
2448 image
->format
!= CAIRO_FORMAT_A1
)
2450 cairo_surface_t
*surf
;
2451 cairo_surface_pattern_t pattern
;
2453 surf
= _cairo_image_surface_create_with_content (image_surf
->base
.content
,
2455 image_surf
->height
);
2456 image
= (cairo_image_surface_t
*) surf
;
2458 status
= surf
->status
;
2462 _cairo_pattern_init_for_surface (&pattern
, &image_surf
->base
);
2463 status
= _cairo_surface_paint (surf
,
2464 CAIRO_OPERATOR_SOURCE
, &pattern
.base
,
2466 _cairo_pattern_fini (&pattern
.base
);
2467 if (unlikely (status
))
2471 if (surface_entry
->smask
|| surface_entry
->stencil_mask
) {
2472 return _cairo_pdf_surface_emit_smask (surface
, image
,
2473 surface_entry
->stencil_mask
,
2474 surface_entry
->interpolate
,
2475 &surface_entry
->surface_res
);
2478 color
= _cairo_image_analyze_color (image
);
2481 case CAIRO_IMAGE_UNKNOWN_COLOR
:
2483 case CAIRO_IMAGE_IS_COLOR
:
2484 data_size
= image
->height
* image
->width
* 3;
2485 data
= _cairo_malloc_abc (image
->width
, image
->height
, 3);
2488 case CAIRO_IMAGE_IS_GRAYSCALE
:
2489 data_size
= image
->height
* image
->width
;
2490 data
= _cairo_malloc_ab (image
->width
, image
->height
);
2492 case CAIRO_IMAGE_IS_MONOCHROME
:
2493 data_size
= (image
->width
+ 7) / 8 * image
->height
;
2494 data
= _cairo_malloc_ab ((image
->width
+7) / 8, image
->height
);
2497 if (unlikely (data
== NULL
)) {
2498 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2503 for (y
= 0; y
< image
->height
; y
++) {
2504 pixel
= (uint32_t *) (image
->data
+ y
* image
->stride
);
2507 for (x
= 0; x
< image
->width
; x
++, pixel
++) {
2510 /* XXX: We're un-premultiplying alpha here. My reading of the PDF
2511 * specification suggests that we should be able to avoid having
2512 * to do this by filling in the SMask's Matte dictionary
2513 * appropriately, but my attempts to do that so far have
2515 if (image
->format
== CAIRO_FORMAT_ARGB32
) {
2517 a
= (*pixel
& 0xff000000) >> 24;
2521 r
= (((*pixel
& 0xff0000) >> 16) * 255 + a
/ 2) / a
;
2522 g
= (((*pixel
& 0x00ff00) >> 8) * 255 + a
/ 2) / a
;
2523 b
= (((*pixel
& 0x0000ff) >> 0) * 255 + a
/ 2) / a
;
2525 } else if (image
->format
== CAIRO_FORMAT_RGB24
) {
2526 r
= (*pixel
& 0x00ff0000) >> 16;
2527 g
= (*pixel
& 0x0000ff00) >> 8;
2528 b
= (*pixel
& 0x000000ff) >> 0;
2534 case CAIRO_IMAGE_IS_COLOR
:
2535 case CAIRO_IMAGE_UNKNOWN_COLOR
:
2541 case CAIRO_IMAGE_IS_GRAYSCALE
:
2545 case CAIRO_IMAGE_IS_MONOCHROME
:
2549 data
[i
] |= (1 << bit
);
2562 if (surface_entry
->smask_res
.id
!= 0) {
2564 smask
= surface_entry
->smask_res
;
2567 if (image
->format
== CAIRO_FORMAT_ARGB32
||
2568 image
->format
== CAIRO_FORMAT_A8
||
2569 image
->format
== CAIRO_FORMAT_A1
)
2571 transparency
= _cairo_image_analyze_transparency (image
);
2572 if (transparency
!= CAIRO_IMAGE_IS_OPAQUE
) {
2574 smask
= _cairo_pdf_surface_new_object (surface
);
2575 if (smask
.id
== 0) {
2576 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2580 status
= _cairo_pdf_surface_emit_smask (surface
, image
, FALSE
, surface_entry
->interpolate
, &smask
);
2581 if (unlikely (status
))
2588 snprintf(smask_buf
, sizeof(smask_buf
), " /SMask %d 0 R\n", smask
.id
);
2592 status
= _cairo_pdf_surface_open_stream (surface
,
2593 &surface_entry
->surface_res
,
2596 " /Subtype /Image\n"
2600 " /Interpolate %s\n"
2601 " /BitsPerComponent %d\n"
2605 color
== CAIRO_IMAGE_IS_COLOR
? "/DeviceRGB" : "/DeviceGray",
2606 surface_entry
->interpolate
? "true" : "false",
2607 color
== CAIRO_IMAGE_IS_MONOCHROME
? 1 : 8,
2609 if (unlikely (status
))
2612 #undef IMAGE_DICTIONARY
2614 _cairo_output_stream_write (surface
->output
, data
, data_size
);
2615 status
= _cairo_pdf_surface_close_stream (surface
);
2620 if (image
!= image_surf
)
2621 cairo_surface_destroy (&image
->base
);
2626 static cairo_int_status_t
2627 _cairo_pdf_surface_lookup_jbig2_global (cairo_pdf_surface_t
*surface
,
2628 const unsigned char *global_id
,
2629 unsigned long global_id_length
,
2630 cairo_pdf_jbig2_global_t
**entry
)
2632 cairo_pdf_jbig2_global_t global
;
2634 cairo_int_status_t status
;
2636 size
= _cairo_array_num_elements (&surface
->jbig2_global
);
2637 for (i
= 0; i
< size
; i
++) {
2638 *entry
= (cairo_pdf_jbig2_global_t
*) _cairo_array_index (&surface
->jbig2_global
, i
);
2639 if ((*entry
)->id
&& global_id
&& (*entry
)->id_length
== global_id_length
2640 && memcmp((*entry
)->id
, global_id
, global_id_length
) == 0) {
2641 return CAIRO_STATUS_SUCCESS
;
2645 global
.id
= malloc(global_id_length
);
2646 if (unlikely (global
.id
== NULL
)) {
2647 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2650 memcpy (global
.id
, global_id
, global_id_length
);
2651 global
.id_length
= global_id_length
;
2652 global
.res
= _cairo_pdf_surface_new_object (surface
);
2653 if (global
.res
.id
== 0) {
2655 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2658 global
.emitted
= FALSE
;
2659 status
= _cairo_array_append (&surface
->jbig2_global
, &global
);
2660 if (unlikely(status
))
2663 size
= _cairo_array_num_elements (&surface
->jbig2_global
);
2664 *entry
= (cairo_pdf_jbig2_global_t
*) _cairo_array_index (&surface
->jbig2_global
, size
- 1);
2665 return CAIRO_STATUS_SUCCESS
;
2668 static cairo_int_status_t
2669 _cairo_pdf_surface_emit_jbig2_image (cairo_pdf_surface_t
*surface
,
2670 cairo_surface_t
*source
,
2671 cairo_pdf_source_surface_entry_t
*surface_entry
)
2673 cairo_int_status_t status
;
2674 const unsigned char *mime_data
;
2675 unsigned long mime_data_length
;
2676 cairo_image_info_t info
;
2677 const unsigned char *global_id
;
2678 unsigned long global_id_length
;
2679 const unsigned char *global_data
;
2680 unsigned long global_data_length
;
2681 cairo_pdf_jbig2_global_t
*global_entry
= NULL
; /* hide compiler warning */
2683 char decode_parms_buf
[100];
2685 cairo_surface_get_mime_data (source
, CAIRO_MIME_TYPE_JBIG2
,
2686 &mime_data
, &mime_data_length
);
2687 if (mime_data
== NULL
)
2688 return CAIRO_INT_STATUS_UNSUPPORTED
;
2690 status
= _cairo_image_info_get_jbig2_info (&info
, mime_data
, mime_data_length
);
2694 cairo_surface_get_mime_data (source
, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID
,
2695 &global_id
, &global_id_length
);
2696 if (global_id
&& global_id_length
> 0) {
2697 status
= _cairo_pdf_surface_lookup_jbig2_global (surface
, global_id
, global_id_length
, &global_entry
);
2698 if (unlikely(status
))
2701 if (!global_entry
->emitted
) {
2702 cairo_surface_get_mime_data (source
, CAIRO_MIME_TYPE_JBIG2_GLOBAL
,
2703 &global_data
, &global_data_length
);
2705 status
= _cairo_pdf_surface_open_stream (surface
, &global_entry
->res
, FALSE
, NULL
);
2706 if (unlikely(status
))
2709 _cairo_output_stream_write (surface
->output
, global_data
, global_data_length
);
2710 status
= _cairo_pdf_surface_close_stream (surface
);
2711 if (unlikely(status
))
2714 global_entry
->emitted
= TRUE
;
2718 snprintf(decode_parms_buf
, sizeof(decode_parms_buf
),
2719 " /DecodeParms << /JBIG2Globals %d 0 R >>\n", global_entry
->res
.id
);
2721 decode_parms_buf
[0] = 0;
2724 if (surface_entry
->smask_res
.id
)
2725 snprintf(smask_buf
, sizeof(smask_buf
), " /SMask %d 0 R\n", surface_entry
->smask_res
.id
);
2729 if (surface_entry
->stencil_mask
) {
2730 status
= _cairo_pdf_surface_open_stream (surface
,
2731 &surface_entry
->surface_res
,
2734 " /Subtype /Image\n"
2735 " /ImageMask true\n"
2738 " /Interpolate %s\n"
2739 " /BitsPerComponent 1\n"
2741 " /Filter /JPXDecode\n"
2745 surface_entry
->interpolate
? "true" : "false",
2748 status
= _cairo_pdf_surface_open_stream (surface
,
2749 &surface_entry
->surface_res
,
2752 " /Subtype /Image\n"
2755 " /ColorSpace /DeviceGray\n"
2756 " /BitsPerComponent 1\n"
2757 " /Interpolate %s\n"
2759 " /Filter /JBIG2Decode\n"
2763 surface_entry
->interpolate
? "true" : "false",
2767 if (unlikely(status
))
2770 _cairo_output_stream_write (surface
->output
, mime_data
, mime_data_length
);
2771 status
= _cairo_pdf_surface_close_stream (surface
);
2776 static cairo_int_status_t
2777 _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t
*surface
,
2778 cairo_surface_t
*source
,
2779 cairo_pdf_source_surface_entry_t
*surface_entry
)
2781 cairo_int_status_t status
;
2782 const unsigned char *mime_data
;
2783 unsigned long mime_data_length
;
2784 cairo_image_info_t info
;
2787 if (surface
->pdf_version
< CAIRO_PDF_VERSION_1_5
)
2788 return CAIRO_INT_STATUS_UNSUPPORTED
;
2790 cairo_surface_get_mime_data (source
, CAIRO_MIME_TYPE_JP2
,
2791 &mime_data
, &mime_data_length
);
2792 if (mime_data
== NULL
)
2793 return CAIRO_INT_STATUS_UNSUPPORTED
;
2795 status
= _cairo_image_info_get_jpx_info (&info
, mime_data
, mime_data_length
);
2799 if ((surface_entry
->smask
|| surface_entry
->stencil_mask
) && info
.num_components
!= 1)
2800 return CAIRO_INT_STATUS_UNSUPPORTED
;
2802 if ((surface_entry
->stencil_mask
) && info
.bits_per_component
!= 1)
2803 return CAIRO_INT_STATUS_UNSUPPORTED
;
2805 if (surface_entry
->smask_res
.id
)
2806 snprintf(smask_buf
, sizeof(smask_buf
), " /SMask %d 0 R\n", surface_entry
->smask_res
.id
);
2810 if (surface_entry
->stencil_mask
) {
2811 status
= _cairo_pdf_surface_open_stream (surface
,
2812 &surface_entry
->surface_res
,
2815 " /Subtype /Image\n"
2816 " /ImageMask true\n"
2819 " /Interpolate %s\n"
2820 " /BitsPerComponent 1\n"
2822 " /Filter /JPXDecode\n",
2825 surface_entry
->interpolate
? "true" : "false");
2827 status
= _cairo_pdf_surface_open_stream (surface
,
2828 &surface_entry
->surface_res
,
2831 " /Subtype /Image\n"
2834 " /Interpolate %s\n"
2836 " /Filter /JPXDecode\n",
2839 surface_entry
->interpolate
? "true" : "false",
2845 _cairo_output_stream_write (surface
->output
, mime_data
, mime_data_length
);
2846 status
= _cairo_pdf_surface_close_stream (surface
);
2851 static cairo_int_status_t
2852 _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t
*surface
,
2853 cairo_surface_t
*source
,
2854 cairo_pdf_source_surface_entry_t
*surface_entry
)
2856 cairo_int_status_t status
;
2857 const unsigned char *mime_data
;
2858 unsigned long mime_data_length
;
2859 cairo_image_info_t info
;
2860 const char *colorspace
;
2863 cairo_surface_get_mime_data (source
, CAIRO_MIME_TYPE_JPEG
,
2864 &mime_data
, &mime_data_length
);
2865 if (unlikely (source
->status
))
2866 return source
->status
;
2867 if (mime_data
== NULL
)
2868 return CAIRO_INT_STATUS_UNSUPPORTED
;
2870 status
= _cairo_image_info_get_jpeg_info (&info
, mime_data
, mime_data_length
);
2871 if (unlikely (status
))
2874 if ((surface_entry
->smask
|| surface_entry
->stencil_mask
) && info
.num_components
!= 1)
2875 return CAIRO_INT_STATUS_UNSUPPORTED
;
2877 if ((surface_entry
->stencil_mask
) && info
.bits_per_component
!= 1)
2878 return CAIRO_INT_STATUS_UNSUPPORTED
;
2880 switch (info
.num_components
) {
2882 colorspace
= "/DeviceGray";
2885 colorspace
= "/DeviceRGB";
2888 colorspace
= "/DeviceCMYK";
2891 return CAIRO_INT_STATUS_UNSUPPORTED
;
2894 if (surface_entry
->smask_res
.id
)
2895 snprintf(smask_buf
, sizeof(smask_buf
), " /SMask %d 0 R\n", surface_entry
->smask_res
.id
);
2899 if (surface_entry
->stencil_mask
) {
2900 status
= _cairo_pdf_surface_open_stream (surface
,
2901 &surface_entry
->surface_res
,
2904 " /Subtype /Image\n"
2905 " /ImageMask true\n"
2908 " /Interpolate %s\n"
2909 " /BitsPerComponent 1\n"
2911 " /Filter /DCTDecode\n",
2914 surface_entry
->interpolate
? "true" : "false");
2916 status
= _cairo_pdf_surface_open_stream (surface
,
2917 &surface_entry
->surface_res
,
2920 " /Subtype /Image\n"
2924 " /Interpolate %s\n"
2925 " /BitsPerComponent %d\n"
2927 " /Filter /DCTDecode\n",
2931 surface_entry
->interpolate
? "true" : "false",
2932 info
.bits_per_component
,
2935 if (unlikely (status
))
2938 _cairo_output_stream_write (surface
->output
, mime_data
, mime_data_length
);
2939 status
= _cairo_pdf_surface_close_stream (surface
);
2944 static cairo_int_status_t
2945 _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t
*surface
,
2946 cairo_pdf_source_surface_t
*source
)
2948 cairo_image_surface_t
*image
;
2950 cairo_int_status_t status
;
2952 if (source
->type
== CAIRO_PATTERN_TYPE_SURFACE
) {
2953 status
= _cairo_pdf_surface_emit_jbig2_image (surface
, source
->surface
, source
->hash_entry
);
2954 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
2957 status
= _cairo_pdf_surface_emit_jpx_image (surface
, source
->surface
, source
->hash_entry
);
2958 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
2961 status
= _cairo_pdf_surface_emit_jpeg_image (surface
, source
->surface
, source
->hash_entry
);
2962 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
2966 if (source
->type
== CAIRO_PATTERN_TYPE_SURFACE
) {
2967 status
= _cairo_surface_acquire_source_image (source
->surface
, &image
, &image_extra
);
2969 status
= _cairo_pdf_surface_acquire_source_image_from_pattern (surface
, source
->raster_pattern
,
2970 &image
, &image_extra
);
2972 if (unlikely (status
))
2975 status
= _cairo_pdf_surface_emit_image (surface
,
2977 source
->hash_entry
);
2979 if (source
->type
== CAIRO_PATTERN_TYPE_SURFACE
)
2980 _cairo_surface_release_source_image (source
->surface
, image
, image_extra
);
2982 _cairo_pdf_surface_release_source_image_from_pattern (surface
, source
->raster_pattern
,
2983 image
, image_extra
);
2988 static cairo_int_status_t
2989 _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t
*surface
,
2990 cairo_pdf_source_surface_t
*pdf_source
)
2992 double old_width
, old_height
;
2993 cairo_paginated_mode_t old_paginated_mode
;
2994 cairo_surface_clipper_t old_clipper
;
2995 cairo_box_double_t bbox
;
2996 cairo_int_status_t status
;
2998 cairo_surface_t
*free_me
= NULL
;
2999 cairo_surface_t
*source
;
3000 const cairo_rectangle_int_t
*extents
;
3003 cairo_bool_t is_subsurface
;
3004 cairo_bool_t transparency_group
;
3005 cairo_recording_surface_t
*recording
;
3007 assert (pdf_source
->type
== CAIRO_PATTERN_TYPE_SURFACE
);
3008 extents
= &pdf_source
->hash_entry
->extents
;
3009 width
= pdf_source
->hash_entry
->width
;
3010 height
= pdf_source
->hash_entry
->height
;
3011 is_subsurface
= FALSE
;
3012 source
= pdf_source
->surface
;
3013 if (_cairo_surface_is_snapshot (source
)) {
3014 free_me
= source
= _cairo_surface_snapshot_get_target (source
);
3015 } else if (source
->backend
->type
== CAIRO_SURFACE_TYPE_SUBSURFACE
) {
3016 cairo_surface_subsurface_t
*sub
= (cairo_surface_subsurface_t
*) source
;
3018 source
= sub
->target
;
3019 extents
= &sub
->extents
;
3020 width
= extents
->width
;
3021 height
= extents
->height
;
3022 is_subsurface
= TRUE
;
3025 assert (source
->type
== CAIRO_SURFACE_TYPE_RECORDING
);
3026 recording
= (cairo_recording_surface_t
*) source
;
3028 old_width
= surface
->width
;
3029 old_height
= surface
->height
;
3030 old_paginated_mode
= surface
->paginated_mode
;
3031 old_clipper
= surface
->clipper
;
3032 _cairo_surface_clipper_init (&surface
->clipper
,
3033 _cairo_pdf_surface_clipper_intersect_clip_path
);
3035 _cairo_pdf_surface_set_size_internal (surface
, width
, height
);
3037 /* Patterns are emitted after fallback images. The paginated mode
3038 * needs to be set to _RENDER while the recording surface is replayed
3039 * back to this surface.
3041 surface
->paginated_mode
= CAIRO_PAGINATED_MODE_RENDER
;
3042 _cairo_pdf_group_resources_clear (&surface
->resources
);
3043 _get_bbox_from_extents (height
, extents
, &bbox
);
3045 /* We can optimize away the transparency group allowing the viewer
3046 * to replay the group in place when all operators are OVER and the
3047 * recording contains only opaque and/or clear alpha.
3049 transparency_group
= !(pdf_source
->hash_entry
->operator == CAIRO_OPERATOR_OVER
&&
3050 _cairo_recording_surface_has_only_bilevel_alpha (recording
) &&
3051 _cairo_recording_surface_has_only_op_over (recording
));
3052 status
= _cairo_pdf_surface_open_content_stream (surface
, &bbox
, &pdf_source
->hash_entry
->surface_res
,
3053 TRUE
, transparency_group
);
3054 if (unlikely (status
))
3057 if (source
->content
== CAIRO_CONTENT_COLOR
) {
3058 status
= _cairo_pdf_surface_add_alpha (surface
, 1.0, &alpha
);
3059 if (unlikely (status
))
3062 _cairo_output_stream_printf (surface
->output
,
3063 "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
3069 status
= _cairo_recording_surface_replay_region (source
,
3070 is_subsurface
? extents
: NULL
,
3072 CAIRO_RECORDING_REGION_NATIVE
);
3073 assert (status
!= CAIRO_INT_STATUS_UNSUPPORTED
);
3074 if (unlikely (status
))
3077 status
= _cairo_pdf_surface_close_content_stream (surface
);
3079 _cairo_surface_clipper_reset (&surface
->clipper
);
3080 surface
->clipper
= old_clipper
;
3081 _cairo_pdf_surface_set_size_internal (surface
,
3084 surface
->paginated_mode
= old_paginated_mode
;
3087 cairo_surface_destroy (free_me
);
3091 static cairo_int_status_t
3092 _cairo_pdf_surface_emit_surface (cairo_pdf_surface_t
*surface
,
3093 cairo_pdf_source_surface_t
*src_surface
)
3095 if (src_surface
->type
== CAIRO_PATTERN_TYPE_SURFACE
&&
3096 src_surface
->surface
->type
== CAIRO_SURFACE_TYPE_RECORDING
)
3097 return _cairo_pdf_surface_emit_recording_surface (surface
, src_surface
);
3099 return _cairo_pdf_surface_emit_image_surface (surface
, src_surface
);
3102 static cairo_int_status_t
3103 _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t
*surface
,
3104 cairo_pdf_pattern_t
*pdf_pattern
)
3106 cairo_pattern_t
*pattern
= pdf_pattern
->pattern
;
3107 cairo_int_status_t status
;
3108 cairo_pdf_resource_t pattern_resource
= {0};
3109 cairo_matrix_t cairo_p2d
, pdf_p2d
;
3110 cairo_extend_t extend
= cairo_pattern_get_extend (pattern
);
3111 double xstep
, ystep
;
3112 cairo_rectangle_int_t pattern_extents
;
3113 int pattern_width
= 0; /* squelch bogus compiler warning */
3114 int pattern_height
= 0; /* squelch bogus compiler warning */
3117 char draw_surface
[200];
3118 cairo_box_double_t bbox
;
3120 if (pattern
->extend
== CAIRO_EXTEND_PAD
) {
3121 status
= _cairo_pdf_surface_add_padded_image_surface (surface
,
3123 &pdf_pattern
->extents
,
3129 pattern_extents
.x
= 0;
3130 pattern_extents
.y
= 0;
3131 pattern_extents
.width
= pattern_width
;
3132 pattern_extents
.height
= pattern_height
;
3134 status
= _cairo_pdf_surface_add_source_surface (surface
,
3137 pdf_pattern
->operator,
3141 &pdf_pattern
->extents
,
3150 if (unlikely (status
))
3154 case CAIRO_EXTEND_PAD
:
3155 case CAIRO_EXTEND_NONE
:
3157 /* In PS/PDF, (as far as I can tell), all patterns are
3158 * repeating. So we support cairo's EXTEND_NONE semantics
3159 * by setting the repeat step size to a size large enough
3160 * to guarantee that no more than a single occurrence will
3163 * First, map the surface extents into pattern space (since
3164 * xstep and ystep are in pattern space). Then use an upper
3165 * bound on the length of the diagonal of the pattern image
3166 * and the surface as repeat size. This guarantees to never
3169 double x1
= 0.0, y1
= 0.0;
3170 double x2
= surface
->width
, y2
= surface
->height
;
3171 _cairo_matrix_transform_bounding_box (&pattern
->matrix
,
3175 /* Rather than computing precise bounds of the union, just
3176 * add the surface extents unconditionally. We only
3177 * required an answer that's large enough, we don't really
3178 * care if it's not as tight as possible.*/
3179 xstep
= ystep
= ceil ((x2
- x1
) + (y2
- y1
) +
3180 pattern_width
+ pattern_height
);
3183 case CAIRO_EXTEND_REPEAT
:
3184 xstep
= pattern_width
;
3185 ystep
= pattern_height
;
3187 case CAIRO_EXTEND_REFLECT
:
3188 pattern_extents
.x
= 0;
3189 pattern_extents
.y
= 0;
3190 pattern_extents
.width
= pattern_width
*2;
3191 pattern_extents
.height
= pattern_height
*2;
3192 xstep
= pattern_width
*2;
3193 ystep
= pattern_height
*2;
3195 /* All the rest (if any) should have been analyzed away, so this
3196 * case should be unreachable. */
3203 /* At this point, (that is, within the surface backend interface),
3204 * the pattern's matrix maps from cairo's device space to cairo's
3205 * pattern space, (both with their origin at the upper-left, and
3206 * cairo's pattern space of size width,height).
3208 * Then, we must emit a PDF pattern object that maps from its own
3209 * pattern space, (which has a size that we establish in the BBox
3210 * dictionary entry), to the PDF page's *initial* space, (which
3211 * does not benefit from the Y-axis flipping matrix that we emit
3212 * on each page). So the PDF patterns matrix maps from a
3213 * (width,height) pattern space to a device space with the origin
3214 * in the lower-left corner.
3216 * So to handle all of that, we start with an identity matrix for
3217 * the PDF pattern to device matrix. We translate it up by the
3218 * image height then flip it in the Y direction, (moving us from
3219 * the PDF origin to cairo's origin). We then multiply in the
3220 * inverse of the cairo pattern matrix, (since it maps from device
3221 * to pattern, while we're setting up pattern to device). Finally,
3222 * we translate back down by the image height and flip again to
3223 * end up at the lower-left origin that PDF expects.
3225 * Additionally, within the stream that paints the pattern itself,
3226 * we are using a PDF image object that has a size of (1,1) so we
3227 * have to scale it up by the image width and height to fill our
3230 cairo_p2d
= pattern
->matrix
;
3231 status
= cairo_matrix_invert (&cairo_p2d
);
3232 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3233 assert (status
== CAIRO_INT_STATUS_SUCCESS
);
3235 cairo_matrix_multiply (&pdf_p2d
, &cairo_p2d
, &surface
->cairo_to_pdf
);
3236 cairo_matrix_translate (&pdf_p2d
, -x_offset
, -y_offset
);
3237 cairo_matrix_translate (&pdf_p2d
, 0.0, pattern_height
);
3238 cairo_matrix_scale (&pdf_p2d
, 1.0, -1.0);
3240 _get_bbox_from_extents (pattern_height
, &pattern_extents
, &bbox
);
3241 _cairo_pdf_surface_update_object (surface
, pdf_pattern
->pattern_res
);
3242 status
= _cairo_pdf_surface_open_stream (surface
,
3243 &pdf_pattern
->pattern_res
,
3246 " /BBox [ %f %f %f %f ]\n"
3251 " /Matrix [ %f %f %f %f %f %f ]\n"
3252 " /Resources << /XObject << /x%d %d 0 R >> >>\n",
3253 bbox
.p1
.x
, bbox
.p1
.y
, bbox
.p2
.x
, bbox
.p2
.y
,
3255 pdf_p2d
.xx
, pdf_p2d
.yx
,
3256 pdf_p2d
.xy
, pdf_p2d
.yy
,
3257 pdf_p2d
.x0
, pdf_p2d
.y0
,
3258 pattern_resource
.id
,
3259 pattern_resource
.id
);
3260 if (unlikely (status
))
3263 if (pattern
->type
== CAIRO_PATTERN_TYPE_SURFACE
&&
3264 ((cairo_surface_pattern_t
*) pattern
)->surface
->type
== CAIRO_SURFACE_TYPE_RECORDING
) {
3265 snprintf(draw_surface
,
3266 sizeof (draw_surface
),
3268 pattern_resource
.id
);
3270 snprintf(draw_surface
,
3271 sizeof (draw_surface
),
3272 "q %d 0 0 %d 0 0 cm /x%d Do Q",
3275 pattern_resource
.id
);
3278 if (extend
== CAIRO_EXTEND_REFLECT
) {
3279 _cairo_output_stream_printf (surface
->output
,
3280 "q 0 0 %d %d re W n %s Q\n"
3281 "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n %s Q\n"
3282 "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n %s Q\n"
3283 "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n %s Q\n",
3284 pattern_width
, pattern_height
,
3286 pattern_width
*2, pattern_width
, pattern_height
,
3288 pattern_height
*2, pattern_width
, pattern_height
,
3290 pattern_width
*2, pattern_height
*2, pattern_width
, pattern_height
,
3293 _cairo_output_stream_printf (surface
->output
,
3298 status
= _cairo_pdf_surface_close_stream (surface
);
3299 if (unlikely (status
))
3302 return _cairo_output_stream_get_status (surface
->output
);
3305 typedef struct _cairo_pdf_color_stop
{
3308 cairo_pdf_resource_t resource
;
3309 } cairo_pdf_color_stop_t
;
3311 static cairo_int_status_t
3312 cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t
*surface
,
3313 cairo_pdf_color_stop_t
*stop1
,
3314 cairo_pdf_color_stop_t
*stop2
,
3315 cairo_pdf_resource_t
*function
)
3318 cairo_pdf_rgb_linear_function_t elem
;
3319 cairo_pdf_resource_t res
;
3320 cairo_int_status_t status
;
3322 num_elems
= _cairo_array_num_elements (&surface
->rgb_linear_functions
);
3323 for (i
= 0; i
< num_elems
; i
++) {
3324 _cairo_array_copy_element (&surface
->rgb_linear_functions
, i
, &elem
);
3325 if (memcmp (&elem
.color1
[0], &stop1
->color
[0], sizeof (double)*3) != 0)
3327 if (memcmp (&elem
.color2
[0], &stop2
->color
[0], sizeof (double)*3) != 0)
3329 *function
= elem
.resource
;
3330 return CAIRO_STATUS_SUCCESS
;
3333 res
= _cairo_pdf_surface_new_object (surface
);
3335 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
3337 _cairo_output_stream_printf (surface
->output
,
3339 "<< /FunctionType 2\n"
3340 " /Domain [ 0 1 ]\n"
3341 " /C0 [ %f %f %f ]\n"
3342 " /C1 [ %f %f %f ]\n"
3354 elem
.resource
= res
;
3355 memcpy (&elem
.color1
[0], &stop1
->color
[0], sizeof (double)*3);
3356 memcpy (&elem
.color2
[0], &stop2
->color
[0], sizeof (double)*3);
3358 status
= _cairo_array_append (&surface
->rgb_linear_functions
, &elem
);
3364 static cairo_int_status_t
3365 cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t
*surface
,
3366 cairo_pdf_color_stop_t
*stop1
,
3367 cairo_pdf_color_stop_t
*stop2
,
3368 cairo_pdf_resource_t
*function
)
3371 cairo_pdf_alpha_linear_function_t elem
;
3372 cairo_pdf_resource_t res
;
3373 cairo_int_status_t status
;
3375 num_elems
= _cairo_array_num_elements (&surface
->alpha_linear_functions
);
3376 for (i
= 0; i
< num_elems
; i
++) {
3377 _cairo_array_copy_element (&surface
->alpha_linear_functions
, i
, &elem
);
3378 if (elem
.alpha1
!= stop1
->color
[3])
3380 if (elem
.alpha2
!= stop2
->color
[3])
3382 *function
= elem
.resource
;
3383 return CAIRO_STATUS_SUCCESS
;
3386 res
= _cairo_pdf_surface_new_object (surface
);
3388 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
3390 _cairo_output_stream_printf (surface
->output
,
3392 "<< /FunctionType 2\n"
3393 " /Domain [ 0 1 ]\n"
3403 elem
.resource
= res
;
3404 elem
.alpha1
= stop1
->color
[3];
3405 elem
.alpha2
= stop2
->color
[3];
3407 status
= _cairo_array_append (&surface
->alpha_linear_functions
, &elem
);
3413 static cairo_int_status_t
3414 _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t
*surface
,
3415 unsigned int n_stops
,
3416 cairo_pdf_color_stop_t
*stops
,
3417 cairo_bool_t is_alpha
,
3418 cairo_pdf_resource_t
*function
)
3420 cairo_pdf_resource_t res
;
3422 cairo_int_status_t status
;
3424 /* emit linear gradients between pairs of subsequent stops... */
3425 for (i
= 0; i
< n_stops
-1; i
++) {
3427 status
= cairo_pdf_surface_emit_alpha_linear_function (surface
,
3430 &stops
[i
].resource
);
3431 if (unlikely (status
))
3434 status
= cairo_pdf_surface_emit_rgb_linear_function (surface
,
3437 &stops
[i
].resource
);
3438 if (unlikely (status
))
3443 /* ... and stitch them together */
3444 res
= _cairo_pdf_surface_new_object (surface
);
3446 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
3448 _cairo_output_stream_printf (surface
->output
,
3450 "<< /FunctionType 3\n"
3451 " /Domain [ %f %f ]\n",
3454 stops
[n_stops
- 1].offset
);
3456 _cairo_output_stream_printf (surface
->output
,
3458 for (i
= 0; i
< n_stops
-1; i
++)
3459 _cairo_output_stream_printf (surface
->output
,
3460 "%d 0 R ", stops
[i
].resource
.id
);
3461 _cairo_output_stream_printf (surface
->output
,
3464 _cairo_output_stream_printf (surface
->output
,
3466 for (i
= 1; i
< n_stops
-1; i
++)
3467 _cairo_output_stream_printf (surface
->output
,
3468 "%f ", stops
[i
].offset
);
3469 _cairo_output_stream_printf (surface
->output
,
3472 _cairo_output_stream_printf (surface
->output
,
3474 for (i
= 1; i
< n_stops
; i
++)
3475 _cairo_output_stream_printf (surface
->output
,
3477 _cairo_output_stream_printf (surface
->output
,
3480 _cairo_output_stream_printf (surface
->output
,
3486 return _cairo_output_stream_get_status (surface
->output
);
3491 calc_gradient_color (cairo_pdf_color_stop_t
*new_stop
,
3492 cairo_pdf_color_stop_t
*stop1
,
3493 cairo_pdf_color_stop_t
*stop2
)
3496 double offset
= stop1
->offset
/ (stop1
->offset
+ 1.0 - stop2
->offset
);
3498 for (i
= 0; i
< 4; i
++)
3499 new_stop
->color
[i
] = stop1
->color
[i
] + offset
*(stop2
->color
[i
] - stop1
->color
[i
]);
3502 #define COLOR_STOP_EPSILON 1e-6
3504 static cairo_int_status_t
3505 _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t
*surface
,
3506 cairo_gradient_pattern_t
*pattern
,
3507 cairo_pdf_resource_t
*color_function
,
3508 cairo_pdf_resource_t
*alpha_function
)
3510 cairo_pdf_color_stop_t
*allstops
, *stops
;
3511 unsigned int n_stops
;
3513 cairo_bool_t emit_alpha
= FALSE
;
3514 cairo_int_status_t status
;
3516 color_function
->id
= 0;
3517 alpha_function
->id
= 0;
3519 allstops
= _cairo_malloc_ab ((pattern
->n_stops
+ 2), sizeof (cairo_pdf_color_stop_t
));
3520 if (unlikely (allstops
== NULL
))
3521 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
3523 stops
= &allstops
[1];
3524 n_stops
= pattern
->n_stops
;
3526 for (i
= 0; i
< n_stops
; i
++) {
3527 stops
[i
].color
[0] = pattern
->stops
[i
].color
.red
;
3528 stops
[i
].color
[1] = pattern
->stops
[i
].color
.green
;
3529 stops
[i
].color
[2] = pattern
->stops
[i
].color
.blue
;
3530 stops
[i
].color
[3] = pattern
->stops
[i
].color
.alpha
;
3531 if (!CAIRO_ALPHA_IS_OPAQUE (stops
[i
].color
[3]))
3533 stops
[i
].offset
= pattern
->stops
[i
].offset
;
3536 if (pattern
->base
.extend
== CAIRO_EXTEND_REPEAT
||
3537 pattern
->base
.extend
== CAIRO_EXTEND_REFLECT
) {
3538 if (stops
[0].offset
> COLOR_STOP_EPSILON
) {
3539 if (pattern
->base
.extend
== CAIRO_EXTEND_REFLECT
)
3540 memcpy (allstops
, stops
, sizeof (cairo_pdf_color_stop_t
));
3542 calc_gradient_color (&allstops
[0], &stops
[0], &stops
[n_stops
-1]);
3546 stops
[0].offset
= 0.0;
3548 if (stops
[n_stops
-1].offset
< 1.0 - COLOR_STOP_EPSILON
) {
3549 if (pattern
->base
.extend
== CAIRO_EXTEND_REFLECT
) {
3550 memcpy (&stops
[n_stops
],
3551 &stops
[n_stops
- 1],
3552 sizeof (cairo_pdf_color_stop_t
));
3554 calc_gradient_color (&stops
[n_stops
], &stops
[0], &stops
[n_stops
-1]);
3558 stops
[n_stops
-1].offset
= 1.0;
3561 if (stops
[0].offset
== stops
[n_stops
- 1].offset
) {
3563 * The first and the last stops have the same offset, but we
3564 * don't want a function with an empty domain, because that
3565 * would provoke underdefined behaviour from rasterisers.
3566 * This can only happen with EXTEND_PAD, because EXTEND_NONE
3567 * is optimised into a clear pattern in cairo-gstate, and
3568 * REFLECT/REPEAT are always transformed to have the first
3569 * stop at t=0 and the last stop at t=1. Thus we want a step
3570 * function going from the first color to the last one.
3572 * This can be accomplished by stitching three functions:
3573 * - a constant first color function,
3574 * - a step from the first color to the last color (with empty domain)
3575 * - a constant last color function
3577 cairo_pdf_color_stop_t pad_stops
[4];
3579 assert (pattern
->base
.extend
== CAIRO_EXTEND_PAD
);
3581 pad_stops
[0] = pad_stops
[1] = stops
[0];
3582 pad_stops
[2] = pad_stops
[3] = stops
[n_stops
- 1];
3584 pad_stops
[0].offset
= 0;
3585 pad_stops
[3].offset
= 1;
3587 status
= _cairo_pdf_surface_emit_stitched_colorgradient (surface
,
3592 if (unlikely (status
))
3596 status
= _cairo_pdf_surface_emit_stitched_colorgradient (surface
,
3601 if (unlikely (status
))
3604 } else if (n_stops
== 2) {
3605 /* no need for stitched function */
3606 status
= cairo_pdf_surface_emit_rgb_linear_function (surface
,
3608 &stops
[n_stops
- 1],
3610 if (unlikely (status
))
3614 status
= cairo_pdf_surface_emit_alpha_linear_function (surface
,
3616 &stops
[n_stops
- 1],
3618 if (unlikely (status
))
3622 /* multiple stops: stitch. XXX possible optimization: regularly spaced
3623 * stops do not require stitching. XXX */
3624 status
= _cairo_pdf_surface_emit_stitched_colorgradient (surface
,
3629 if (unlikely (status
))
3633 status
= _cairo_pdf_surface_emit_stitched_colorgradient (surface
,
3638 if (unlikely (status
))
3648 static cairo_int_status_t
3649 _cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t
*surface
,
3650 cairo_gradient_pattern_t
*pattern
,
3651 cairo_pdf_resource_t
*function
,
3655 cairo_pdf_resource_t res
;
3658 res
= _cairo_pdf_surface_new_object (surface
);
3660 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
3662 _cairo_output_stream_printf (surface
->output
,
3664 "<< /FunctionType 3\n"
3665 " /Domain [ %d %d ]\n",
3670 _cairo_output_stream_printf (surface
->output
,
3672 for (i
= begin
; i
< end
; i
++)
3673 _cairo_output_stream_printf (surface
->output
,
3674 "%d 0 R ", function
->id
);
3675 _cairo_output_stream_printf (surface
->output
,
3678 _cairo_output_stream_printf (surface
->output
,
3680 for (i
= begin
+ 1; i
< end
; i
++)
3681 _cairo_output_stream_printf (surface
->output
,
3683 _cairo_output_stream_printf (surface
->output
,
3686 _cairo_output_stream_printf (surface
->output
,
3688 for (i
= begin
; i
< end
; i
++) {
3689 if ((i
% 2) && pattern
->base
.extend
== CAIRO_EXTEND_REFLECT
) {
3690 _cairo_output_stream_printf (surface
->output
,
3693 _cairo_output_stream_printf (surface
->output
,
3697 _cairo_output_stream_printf (surface
->output
,
3700 _cairo_output_stream_printf (surface
->output
,
3706 return _cairo_output_stream_get_status (surface
->output
);
3709 static cairo_int_status_t
3710 cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t
*surface
,
3711 cairo_pdf_pattern_t
*pdf_pattern
,
3712 cairo_pdf_resource_t gstate_resource
,
3713 cairo_pdf_resource_t gradient_mask
)
3715 cairo_pdf_resource_t smask_resource
;
3716 cairo_int_status_t status
;
3718 double x1
, y1
, x2
, y2
;
3720 if (pdf_pattern
->is_shading
) {
3721 snprintf(buf
, sizeof(buf
),
3723 " << /sh%d %d 0 R >>\n",
3727 snprintf(buf
, sizeof(buf
),
3729 " << /p%d %d 0 R >>\n",
3734 if (pdf_pattern
->is_shading
) {
3737 /* When emitting a shading operator we are in cairo pattern
3738 * coordinates. _cairo_pdf_surface_paint_gradient has set the
3739 * ctm to the pattern matrix (including the convertion from
3740 * pdf to cairo coordinates) */
3741 _cairo_box_from_rectangle (&box
, &pdf_pattern
->extents
);
3742 _cairo_box_to_doubles (&box
, &x1
, &y1
, &x2
, &y2
);
3743 _cairo_matrix_transform_bounding_box (&pdf_pattern
->pattern
->matrix
, &x1
, &y1
, &x2
, &y2
, NULL
);
3745 cairo_box_double_t box
;
3747 /* When emitting a shading pattern we are in pdf page
3748 * coordinates. The color and alpha shading patterns painted
3749 * in the XObject below contain the cairo pattern to pdf page
3750 * matrix in the /Matrix entry of the pattern. */
3751 _get_bbox_from_extents (pdf_pattern
->height
, &pdf_pattern
->extents
, &box
);
3757 status
= _cairo_pdf_surface_open_stream (surface
,
3759 surface
->compress_content
,
3763 " /BBox [ %f %f %f %f ]\n"
3766 " << /a0 << /ca 1 /CA 1 >>"
3771 " << /Type /Group\n"
3772 " /S /Transparency\n"
3774 " /CS /DeviceGray\n"
3778 if (unlikely (status
))
3781 if (pdf_pattern
->is_shading
) {
3782 _cairo_output_stream_printf (surface
->output
,
3783 "/a0 gs /sh%d sh\n",
3786 _cairo_output_stream_printf (surface
->output
,
3789 "/Pattern cs /p%d scn\n"
3798 status
= _cairo_pdf_surface_close_stream (surface
);
3799 if (unlikely (status
))
3802 smask_resource
= _cairo_pdf_surface_new_object (surface
);
3803 if (smask_resource
.id
== 0)
3804 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
3806 _cairo_output_stream_printf (surface
->output
,
3814 surface
->pdf_stream
.self
.id
);
3816 /* Create GState which uses the transparency group as an SMask. */
3817 _cairo_pdf_surface_update_object (surface
, gstate_resource
);
3819 _cairo_output_stream_printf (surface
->output
,
3821 "<< /Type /ExtGState\n"
3831 return _cairo_output_stream_get_status (surface
->output
);
3835 _cairo_pdf_surface_output_gradient (cairo_pdf_surface_t
*surface
,
3836 const cairo_pdf_pattern_t
*pdf_pattern
,
3837 cairo_pdf_resource_t pattern_resource
,
3838 const cairo_matrix_t
*pat_to_pdf
,
3839 const cairo_circle_double_t
*start
,
3840 const cairo_circle_double_t
*end
,
3841 const double *domain
,
3842 const char *colorspace
,
3843 cairo_pdf_resource_t color_function
)
3845 _cairo_output_stream_printf (surface
->output
,
3847 pattern_resource
.id
);
3849 if (!pdf_pattern
->is_shading
) {
3850 _cairo_output_stream_printf (surface
->output
,
3851 "<< /Type /Pattern\n"
3854 _cairo_output_stream_print_matrix (surface
->output
, pat_to_pdf
);
3855 _cairo_output_stream_printf (surface
->output
,
3860 if (pdf_pattern
->pattern
->type
== CAIRO_PATTERN_TYPE_LINEAR
) {
3861 _cairo_output_stream_printf (surface
->output
,
3862 " << /ShadingType 2\n"
3864 " /Coords [ %f %f %f %f ]\n",
3866 start
->center
.x
, start
->center
.y
,
3867 end
->center
.x
, end
->center
.y
);
3869 _cairo_output_stream_printf (surface
->output
,
3870 " << /ShadingType 3\n"
3872 " /Coords [ %f %f %f %f %f %f ]\n",
3874 start
->center
.x
, start
->center
.y
,
3875 MAX (start
->radius
, 0),
3876 end
->center
.x
, end
->center
.y
,
3877 MAX (end
->radius
, 0));
3880 _cairo_output_stream_printf (surface
->output
,
3881 " /Domain [ %f %f ]\n",
3882 domain
[0], domain
[1]);
3884 if (pdf_pattern
->pattern
->extend
!= CAIRO_EXTEND_NONE
) {
3885 _cairo_output_stream_printf (surface
->output
,
3886 " /Extend [ true true ]\n");
3888 _cairo_output_stream_printf (surface
->output
,
3889 " /Extend [ false false ]\n");
3892 _cairo_output_stream_printf (surface
->output
,
3893 " /Function %d 0 R\n"
3897 if (!pdf_pattern
->is_shading
) {
3898 _cairo_output_stream_printf (surface
->output
,
3902 _cairo_output_stream_printf (surface
->output
,
3906 static cairo_int_status_t
3907 _cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t
*surface
,
3908 cairo_pdf_pattern_t
*pdf_pattern
)
3910 cairo_gradient_pattern_t
*pattern
= (cairo_gradient_pattern_t
*) pdf_pattern
->pattern
;
3911 cairo_pdf_resource_t color_function
, alpha_function
;
3912 cairo_matrix_t pat_to_pdf
;
3913 cairo_circle_double_t start
, end
;
3915 cairo_int_status_t status
;
3917 assert (pattern
->n_stops
!= 0);
3919 status
= _cairo_pdf_surface_emit_pattern_stops (surface
,
3923 if (unlikely (status
))
3926 pat_to_pdf
= pattern
->base
.matrix
;
3927 status
= cairo_matrix_invert (&pat_to_pdf
);
3928 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3929 assert (status
== CAIRO_INT_STATUS_SUCCESS
);
3930 cairo_matrix_multiply (&pat_to_pdf
, &pat_to_pdf
, &surface
->cairo_to_pdf
);
3932 if (pattern
->base
.extend
== CAIRO_EXTEND_REPEAT
||
3933 pattern
->base
.extend
== CAIRO_EXTEND_REFLECT
)
3935 double bounds_x1
, bounds_x2
, bounds_y1
, bounds_y2
;
3936 double x_scale
, y_scale
, tolerance
;
3938 /* TODO: use tighter extents */
3941 bounds_x2
= surface
->width
;
3942 bounds_y2
= surface
->height
;
3943 _cairo_matrix_transform_bounding_box (&pattern
->base
.matrix
,
3944 &bounds_x1
, &bounds_y1
,
3945 &bounds_x2
, &bounds_y2
,
3948 x_scale
= surface
->base
.x_resolution
/ surface
->base
.x_fallback_resolution
;
3949 y_scale
= surface
->base
.y_resolution
/ surface
->base
.y_fallback_resolution
;
3951 tolerance
= fabs (_cairo_matrix_compute_determinant (&pattern
->base
.matrix
));
3952 tolerance
/= _cairo_matrix_transformed_circle_major_axis (&pattern
->base
.matrix
, 1);
3953 tolerance
*= MIN (x_scale
, y_scale
);
3955 _cairo_gradient_pattern_box_to_parameter (pattern
,
3956 bounds_x1
, bounds_y1
,
3957 bounds_x2
, bounds_y2
,
3959 } else if (pattern
->stops
[0].offset
== pattern
->stops
[pattern
->n_stops
- 1].offset
) {
3961 * If the first and the last stop offset are the same, then
3962 * the color function is a step function.
3963 * _cairo_ps_surface_emit_pattern_stops emits it as a stitched
3964 * function no matter how many stops the pattern has. The
3965 * domain of the stitched function will be [0 1] in this case.
3967 * This is done to avoid emitting degenerate gradients for
3968 * EXTEND_PAD patterns having a step color function.
3973 assert (pattern
->base
.extend
== CAIRO_EXTEND_PAD
);
3975 domain
[0] = pattern
->stops
[0].offset
;
3976 domain
[1] = pattern
->stops
[pattern
->n_stops
- 1].offset
;
3979 /* PDF requires the first and last stop to be the same as the
3980 * extreme coordinates. For repeating patterns this moves the
3981 * extreme coordinates out to the begin/end of the repeating
3982 * function. For non repeating patterns this may move the extreme
3983 * coordinates in if there are not stops at offset 0 and 1. */
3984 _cairo_gradient_pattern_interpolate (pattern
, domain
[0], &start
);
3985 _cairo_gradient_pattern_interpolate (pattern
, domain
[1], &end
);
3987 if (pattern
->base
.extend
== CAIRO_EXTEND_REPEAT
||
3988 pattern
->base
.extend
== CAIRO_EXTEND_REFLECT
)
3990 int repeat_begin
, repeat_end
;
3992 repeat_begin
= floor (domain
[0]);
3993 repeat_end
= ceil (domain
[1]);
3995 status
= _cairo_pdf_surface_emit_repeating_function (surface
,
4000 if (unlikely (status
))
4003 if (alpha_function
.id
!= 0) {
4004 status
= _cairo_pdf_surface_emit_repeating_function (surface
,
4009 if (unlikely (status
))
4012 } else if (pattern
->n_stops
<= 2) {
4013 /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
4014 * Type 2 function is used by itself without a stitching
4015 * function. Type 2 functions always have the domain [0 1] */
4020 _cairo_pdf_surface_update_object (surface
, pdf_pattern
->pattern_res
);
4021 _cairo_pdf_surface_output_gradient (surface
, pdf_pattern
,
4022 pdf_pattern
->pattern_res
,
4023 &pat_to_pdf
, &start
, &end
, domain
,
4024 "/DeviceRGB", color_function
);
4026 if (alpha_function
.id
!= 0) {
4027 cairo_pdf_resource_t mask_resource
;
4029 assert (pdf_pattern
->gstate_res
.id
!= 0);
4031 /* Create pattern for SMask. */
4032 mask_resource
= _cairo_pdf_surface_new_object (surface
);
4033 if (mask_resource
.id
== 0)
4034 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
4036 _cairo_pdf_surface_output_gradient (surface
, pdf_pattern
,
4038 &pat_to_pdf
, &start
, &end
, domain
,
4039 "/DeviceGray", alpha_function
);
4041 status
= cairo_pdf_surface_emit_transparency_group (surface
,
4043 pdf_pattern
->gstate_res
,
4045 if (unlikely (status
))
4049 return _cairo_output_stream_get_status (surface
->output
);
4052 static cairo_int_status_t
4053 _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t
*surface
,
4054 cairo_pdf_pattern_t
*pdf_pattern
)
4056 cairo_matrix_t pat_to_pdf
;
4057 cairo_int_status_t status
;
4058 cairo_pattern_t
*pattern
= pdf_pattern
->pattern
;
4059 cairo_pdf_shading_t shading
;
4061 cairo_pdf_resource_t res
;
4063 pat_to_pdf
= pattern
->matrix
;
4064 status
= cairo_matrix_invert (&pat_to_pdf
);
4065 /* cairo_pattern_set_matrix ensures the matrix is invertible */
4066 assert (status
== CAIRO_INT_STATUS_SUCCESS
);
4068 cairo_matrix_multiply (&pat_to_pdf
, &pat_to_pdf
, &surface
->cairo_to_pdf
);
4070 status
= _cairo_pdf_shading_init_color (&shading
, (cairo_mesh_pattern_t
*) pattern
);
4071 if (unlikely (status
))
4074 res
= _cairo_pdf_surface_new_object (surface
);
4075 if (unlikely (res
.id
== 0))
4076 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
4078 _cairo_output_stream_printf (surface
->output
,
4080 "<< /ShadingType %d\n"
4081 " /ColorSpace /DeviceRGB\n"
4082 " /BitsPerCoordinate %d\n"
4083 " /BitsPerComponent %d\n"
4084 " /BitsPerFlag %d\n"
4087 shading
.shading_type
,
4088 shading
.bits_per_coordinate
,
4089 shading
.bits_per_component
,
4090 shading
.bits_per_flag
);
4092 for (i
= 0; i
< shading
.decode_array_length
; i
++)
4093 _cairo_output_stream_printf (surface
->output
, "%f ", shading
.decode_array
[i
]);
4095 _cairo_output_stream_printf (surface
->output
,
4100 shading
.data_length
);
4102 _cairo_output_stream_write (surface
->output
, shading
.data
, shading
.data_length
);
4104 _cairo_output_stream_printf (surface
->output
,
4108 _cairo_pdf_shading_fini (&shading
);
4110 _cairo_pdf_surface_update_object (surface
, pdf_pattern
->pattern_res
);
4111 _cairo_output_stream_printf (surface
->output
,
4113 "<< /Type /Pattern\n"
4116 pdf_pattern
->pattern_res
.id
);
4117 _cairo_output_stream_print_matrix (surface
->output
, &pat_to_pdf
);
4118 _cairo_output_stream_printf (surface
->output
,
4120 " /Shading %d 0 R\n"
4125 if (pdf_pattern
->gstate_res
.id
!= 0) {
4126 cairo_pdf_resource_t mask_resource
;
4128 /* Create pattern for SMask. */
4129 res
= _cairo_pdf_surface_new_object (surface
);
4130 if (unlikely (res
.id
== 0))
4131 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
4133 status
= _cairo_pdf_shading_init_alpha (&shading
, (cairo_mesh_pattern_t
*) pattern
);
4134 if (unlikely (status
))
4137 _cairo_output_stream_printf (surface
->output
,
4139 "<< /ShadingType %d\n"
4140 " /ColorSpace /DeviceGray\n"
4141 " /BitsPerCoordinate %d\n"
4142 " /BitsPerComponent %d\n"
4143 " /BitsPerFlag %d\n"
4146 shading
.shading_type
,
4147 shading
.bits_per_coordinate
,
4148 shading
.bits_per_component
,
4149 shading
.bits_per_flag
);
4151 for (i
= 0; i
< shading
.decode_array_length
; i
++)
4152 _cairo_output_stream_printf (surface
->output
, "%f ", shading
.decode_array
[i
]);
4154 _cairo_output_stream_printf (surface
->output
,
4159 shading
.data_length
);
4161 _cairo_output_stream_write (surface
->output
, shading
.data
, shading
.data_length
);
4163 _cairo_output_stream_printf (surface
->output
,
4166 _cairo_pdf_shading_fini (&shading
);
4168 mask_resource
= _cairo_pdf_surface_new_object (surface
);
4169 if (unlikely (mask_resource
.id
== 0))
4170 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
4172 _cairo_output_stream_printf (surface
->output
,
4174 "<< /Type /Pattern\n"
4178 _cairo_output_stream_print_matrix (surface
->output
, &pat_to_pdf
);
4179 _cairo_output_stream_printf (surface
->output
,
4181 " /Shading %d 0 R\n"
4186 status
= cairo_pdf_surface_emit_transparency_group (surface
,
4188 pdf_pattern
->gstate_res
,
4190 if (unlikely (status
))
4194 return _cairo_output_stream_get_status (surface
->output
);
4197 static cairo_int_status_t
4198 _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t
*surface
, cairo_pdf_pattern_t
*pdf_pattern
)
4200 double old_width
, old_height
;
4201 cairo_int_status_t status
;
4203 old_width
= surface
->width
;
4204 old_height
= surface
->height
;
4205 _cairo_pdf_surface_set_size_internal (surface
,
4207 pdf_pattern
->height
);
4209 switch (pdf_pattern
->pattern
->type
) {
4210 case CAIRO_PATTERN_TYPE_SOLID
:
4212 status
= _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
4215 case CAIRO_PATTERN_TYPE_SURFACE
:
4216 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
4217 status
= _cairo_pdf_surface_emit_surface_pattern (surface
, pdf_pattern
);
4220 case CAIRO_PATTERN_TYPE_LINEAR
:
4221 case CAIRO_PATTERN_TYPE_RADIAL
:
4222 status
= _cairo_pdf_surface_emit_gradient (surface
, pdf_pattern
);
4225 case CAIRO_PATTERN_TYPE_MESH
:
4226 status
= _cairo_pdf_surface_emit_mesh_pattern (surface
, pdf_pattern
);
4231 status
= _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
4235 _cairo_pdf_surface_set_size_internal (surface
,
4242 static cairo_int_status_t
4243 _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t
*surface
,
4244 cairo_operator_t op
,
4245 const cairo_pattern_t
*source
,
4246 const cairo_rectangle_int_t
*extents
,
4247 cairo_pdf_resource_t
*smask_res
,
4248 cairo_bool_t stencil_mask
)
4250 cairo_pdf_resource_t surface_res
;
4252 cairo_matrix_t cairo_p2d
, pdf_p2d
;
4253 cairo_int_status_t status
;
4255 cairo_rectangle_int_t extents2
;
4259 if (source
->extend
== CAIRO_EXTEND_PAD
&&
4260 !(source
->type
== CAIRO_PATTERN_TYPE_SURFACE
&&
4261 ((cairo_surface_pattern_t
*)source
)->surface
->type
== CAIRO_SURFACE_TYPE_RECORDING
))
4263 status
= _cairo_pdf_surface_add_padded_image_surface (surface
,
4272 status
= _cairo_pdf_surface_add_source_surface (surface
,
4288 if (unlikely (status
))
4291 cairo_p2d
= source
->matrix
;
4292 status
= cairo_matrix_invert (&cairo_p2d
);
4293 /* cairo_pattern_set_matrix ensures the matrix is invertible */
4294 assert (status
== CAIRO_INT_STATUS_SUCCESS
);
4296 pdf_p2d
= surface
->cairo_to_pdf
;
4297 cairo_matrix_multiply (&pdf_p2d
, &cairo_p2d
, &pdf_p2d
);
4298 cairo_matrix_translate (&pdf_p2d
, x_offset
, y_offset
);
4299 cairo_matrix_translate (&pdf_p2d
, 0.0, height
);
4300 cairo_matrix_scale (&pdf_p2d
, 1.0, -1.0);
4301 if (!(source
->type
== CAIRO_PATTERN_TYPE_SURFACE
&&
4302 ((cairo_surface_pattern_t
*)source
)->surface
->type
== CAIRO_SURFACE_TYPE_RECORDING
))
4304 cairo_matrix_scale (&pdf_p2d
, width
, height
);
4307 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
4308 if (unlikely (status
))
4311 if (! _cairo_matrix_is_identity (&pdf_p2d
)) {
4312 _cairo_output_stream_print_matrix (surface
->output
, &pdf_p2d
);
4313 _cairo_output_stream_printf (surface
->output
, " cm\n");
4316 status
= _cairo_pdf_surface_add_alpha (surface
, 1.0, &alpha
);
4317 if (unlikely (status
))
4321 _cairo_output_stream_printf (surface
->output
,
4325 _cairo_output_stream_printf (surface
->output
,
4326 "/a%d gs /x%d Do\n",
4331 return _cairo_pdf_surface_add_xobject (surface
, surface_res
);
4334 static cairo_int_status_t
4335 _cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t
*surface
,
4336 cairo_operator_t op
,
4337 const cairo_pattern_t
*source
,
4338 const cairo_rectangle_int_t
*extents
)
4340 cairo_pdf_resource_t shading_res
, gstate_res
;
4341 cairo_matrix_t pat_to_pdf
;
4342 cairo_int_status_t status
;
4345 status
= _cairo_pdf_surface_add_pdf_shading (surface
, source
,
4347 &shading_res
, &gstate_res
);
4348 if (unlikely (status
== CAIRO_INT_STATUS_NOTHING_TO_DO
))
4349 return CAIRO_INT_STATUS_SUCCESS
;
4350 if (unlikely (status
))
4353 pat_to_pdf
= source
->matrix
;
4354 status
= cairo_matrix_invert (&pat_to_pdf
);
4355 /* cairo_pattern_set_matrix ensures the matrix is invertible */
4356 assert (status
== CAIRO_INT_STATUS_SUCCESS
);
4357 cairo_matrix_multiply (&pat_to_pdf
, &pat_to_pdf
, &surface
->cairo_to_pdf
);
4359 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
4360 if (unlikely (status
))
4363 if (! _cairo_matrix_is_identity (&pat_to_pdf
)) {
4364 _cairo_output_stream_print_matrix (surface
->output
, &pat_to_pdf
);
4365 _cairo_output_stream_printf (surface
->output
, " cm\n");
4368 status
= _cairo_pdf_surface_add_shading (surface
, shading_res
);
4369 if (unlikely (status
))
4372 if (gstate_res
.id
!= 0) {
4373 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
4374 if (unlikely (status
))
4377 _cairo_output_stream_printf (surface
->output
,
4378 "/s%d gs /sh%d sh\n",
4382 status
= _cairo_pdf_surface_add_alpha (surface
, 1.0, &alpha
);
4383 if (unlikely (status
))
4386 _cairo_output_stream_printf (surface
->output
,
4387 "/a%d gs /sh%d sh\n",
4395 static cairo_int_status_t
4396 _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t
*surface
,
4397 cairo_operator_t op
,
4398 const cairo_pattern_t
*source
,
4399 const cairo_rectangle_int_t
*extents
,
4402 switch (source
->type
) {
4403 case CAIRO_PATTERN_TYPE_SURFACE
:
4404 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
4405 return _cairo_pdf_surface_paint_surface_pattern (surface
,
4411 case CAIRO_PATTERN_TYPE_LINEAR
:
4412 case CAIRO_PATTERN_TYPE_RADIAL
:
4413 case CAIRO_PATTERN_TYPE_MESH
:
4414 return _cairo_pdf_surface_paint_gradient (surface
,
4419 case CAIRO_PATTERN_TYPE_SOLID
:
4422 return CAIRO_STATUS_SUCCESS
;
4427 _can_paint_pattern (const cairo_pattern_t
*pattern
)
4429 switch (pattern
->type
) {
4430 case CAIRO_PATTERN_TYPE_SOLID
:
4433 case CAIRO_PATTERN_TYPE_SURFACE
:
4434 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
4435 return (pattern
->extend
== CAIRO_EXTEND_NONE
||
4436 pattern
->extend
== CAIRO_EXTEND_PAD
);
4438 case CAIRO_PATTERN_TYPE_LINEAR
:
4439 case CAIRO_PATTERN_TYPE_RADIAL
:
4442 case CAIRO_PATTERN_TYPE_MESH
:
4451 static cairo_int_status_t
4452 _cairo_pdf_surface_select_operator (cairo_pdf_surface_t
*surface
,
4453 cairo_operator_t op
)
4455 cairo_int_status_t status
;
4457 if (op
== surface
->current_operator
)
4458 return CAIRO_STATUS_SUCCESS
;
4460 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
4461 if (unlikely (status
))
4464 _cairo_output_stream_printf (surface
->output
,
4466 surface
->current_operator
= op
;
4467 _cairo_pdf_surface_add_operator (surface
, op
);
4469 return CAIRO_STATUS_SUCCESS
;
4472 static cairo_int_status_t
4473 _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t
*surface
,
4474 const cairo_pattern_t
*pattern
,
4475 cairo_pdf_resource_t pattern_res
,
4476 cairo_bool_t is_stroke
)
4478 cairo_int_status_t status
;
4480 const cairo_color_t
*solid_color
= NULL
;
4482 if (pattern
->type
== CAIRO_PATTERN_TYPE_SOLID
) {
4483 const cairo_solid_pattern_t
*solid
= (const cairo_solid_pattern_t
*) pattern
;
4485 solid_color
= &solid
->color
;
4488 if (solid_color
!= NULL
) {
4489 if (surface
->current_pattern_is_solid_color
== FALSE
||
4490 surface
->current_color_red
!= solid_color
->red
||
4491 surface
->current_color_green
!= solid_color
->green
||
4492 surface
->current_color_blue
!= solid_color
->blue
||
4493 surface
->current_color_is_stroke
!= is_stroke
)
4495 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
4496 if (unlikely (status
))
4499 _cairo_output_stream_printf (surface
->output
,
4506 _cairo_output_stream_printf (surface
->output
, "RG ");
4508 _cairo_output_stream_printf (surface
->output
, "rg ");
4510 surface
->current_color_red
= solid_color
->red
;
4511 surface
->current_color_green
= solid_color
->green
;
4512 surface
->current_color_blue
= solid_color
->blue
;
4513 surface
->current_color_is_stroke
= is_stroke
;
4516 if (surface
->current_pattern_is_solid_color
== FALSE
||
4517 surface
->current_color_alpha
!= solid_color
->alpha
)
4519 status
= _cairo_pdf_surface_add_alpha (surface
, solid_color
->alpha
, &alpha
);
4520 if (unlikely (status
))
4523 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
4524 if (unlikely (status
))
4527 _cairo_output_stream_printf (surface
->output
,
4530 surface
->current_color_alpha
= solid_color
->alpha
;
4533 surface
->current_pattern_is_solid_color
= TRUE
;
4535 status
= _cairo_pdf_surface_add_alpha (surface
, 1.0, &alpha
);
4536 if (unlikely (status
))
4539 status
= _cairo_pdf_surface_add_pattern (surface
, pattern_res
);
4540 if (unlikely (status
))
4543 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
4544 if (unlikely (status
))
4547 /* fill-stroke calls select_pattern twice. Don't save if the
4548 * gstate is already saved. */
4549 if (!surface
->select_pattern_gstate_saved
)
4550 _cairo_output_stream_printf (surface
->output
, "q ");
4553 _cairo_output_stream_printf (surface
->output
,
4554 "/Pattern CS /p%d SCN ",
4557 _cairo_output_stream_printf (surface
->output
,
4558 "/Pattern cs /p%d scn ",
4561 _cairo_output_stream_printf (surface
->output
,
4564 surface
->select_pattern_gstate_saved
= TRUE
;
4565 surface
->current_pattern_is_solid_color
= FALSE
;
4568 return _cairo_output_stream_get_status (surface
->output
);
4571 static cairo_int_status_t
4572 _cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t
*surface
)
4574 cairo_int_status_t status
;
4576 if (surface
->select_pattern_gstate_saved
) {
4577 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
4578 if (unlikely (status
))
4581 _cairo_output_stream_printf (surface
->output
, "Q\n");
4582 _cairo_pdf_operators_reset (&surface
->pdf_operators
);
4583 surface
->current_pattern_is_solid_color
= FALSE
;
4585 surface
->select_pattern_gstate_saved
= FALSE
;
4587 return CAIRO_STATUS_SUCCESS
;
4590 static cairo_int_status_t
4591 _cairo_pdf_surface_show_page (void *abstract_surface
)
4593 cairo_pdf_surface_t
*surface
= abstract_surface
;
4594 cairo_int_status_t status
;
4596 status
= _cairo_pdf_surface_close_content_stream (surface
);
4597 if (unlikely (status
))
4600 _cairo_surface_clipper_reset (&surface
->clipper
);
4602 status
= _cairo_pdf_surface_write_page (surface
);
4603 if (unlikely (status
))
4606 _cairo_pdf_surface_clear (surface
);
4608 return CAIRO_STATUS_SUCCESS
;
4612 _cairo_pdf_surface_get_extents (void *abstract_surface
,
4613 cairo_rectangle_int_t
*rectangle
)
4615 cairo_pdf_surface_t
*surface
= abstract_surface
;
4620 /* XXX: The conversion to integers here is pretty bogus, (not to
4621 * mention the arbitrary limitation of width to a short(!). We
4622 * may need to come up with a better interface for get_size.
4624 rectangle
->width
= ceil (surface
->width
);
4625 rectangle
->height
= ceil (surface
->height
);
4631 _cairo_pdf_surface_get_font_options (void *abstract_surface
,
4632 cairo_font_options_t
*options
)
4634 _cairo_font_options_init_default (options
);
4636 cairo_font_options_set_hint_style (options
, CAIRO_HINT_STYLE_NONE
);
4637 cairo_font_options_set_hint_metrics (options
, CAIRO_HINT_METRICS_OFF
);
4638 cairo_font_options_set_antialias (options
, CAIRO_ANTIALIAS_GRAY
);
4639 _cairo_font_options_set_round_glyph_positions (options
, CAIRO_ROUND_GLYPH_POS_OFF
);
4642 static cairo_pdf_resource_t
4643 _cairo_pdf_surface_write_info (cairo_pdf_surface_t
*surface
)
4645 cairo_pdf_resource_t info
;
4647 info
= _cairo_pdf_surface_new_object (surface
);
4651 _cairo_output_stream_printf (surface
->output
,
4653 "<< /Creator (cairo %s (http://cairographics.org))\n"
4654 " /Producer (cairo %s (http://cairographics.org))\n"
4658 cairo_version_string (),
4659 cairo_version_string ());
4665 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t
*surface
)
4667 cairo_pdf_resource_t page
;
4670 _cairo_pdf_surface_update_object (surface
, surface
->pages_resource
);
4671 _cairo_output_stream_printf (surface
->output
,
4675 surface
->pages_resource
.id
);
4677 num_pages
= _cairo_array_num_elements (&surface
->pages
);
4678 for (i
= 0; i
< num_pages
; i
++) {
4679 _cairo_array_copy_element (&surface
->pages
, i
, &page
);
4680 _cairo_output_stream_printf (surface
->output
, "%d 0 R ", page
.id
);
4683 _cairo_output_stream_printf (surface
->output
, "]\n");
4684 _cairo_output_stream_printf (surface
->output
, " /Count %d\n", num_pages
);
4687 /* TODO: Figure out which other defaults to be inherited by /Page
4689 _cairo_output_stream_printf (surface
->output
,
4694 static cairo_int_status_t
4695 _utf8_to_pdf_string (const char *utf8
, char **str_out
)
4701 cairo_int_status_t status
= CAIRO_STATUS_SUCCESS
;
4704 len
= strlen (utf8
);
4705 for (i
= 0; i
< len
; i
++) {
4706 unsigned c
= utf8
[i
];
4707 if (c
< 32 || c
> 126 || c
== '(' || c
== ')' || c
== '\\') {
4714 str
= malloc (len
+ 3);
4716 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
4719 for (i
= 0; i
< len
; i
++)
4724 uint16_t *utf16
= NULL
;
4727 status
= _cairo_utf8_to_utf16 (utf8
, -1, &utf16
, &utf16_len
);
4728 if (unlikely (status
))
4731 str
= malloc (utf16_len
*4 + 7);
4734 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
4737 strcpy (str
, "<FEFF");
4738 for (i
= 0; i
< utf16_len
; i
++)
4739 snprintf (str
+ 4*i
+ 5, 5, "%04X", utf16
[i
]);
4749 static cairo_int_status_t
4750 _cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t
*surface
,
4753 uint16_t *utf16
= NULL
;
4755 cairo_int_status_t status
;
4758 if (utf8
&& *utf8
) {
4759 status
= _cairo_utf8_to_utf16 (utf8
, -1, &utf16
, &utf16_len
);
4760 if (unlikely (status
))
4764 _cairo_output_stream_printf (surface
->output
, "<");
4765 if (utf16
== NULL
|| utf16_len
== 0) {
4766 /* According to the "ToUnicode Mapping File Tutorial"
4767 * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
4769 * Glyphs that do not map to a Unicode code point must be
4770 * mapped to 0xfffd "REPLACEMENT CHARACTER".
4772 _cairo_output_stream_printf (surface
->output
,
4775 for (i
= 0; i
< utf16_len
; i
++)
4776 _cairo_output_stream_printf (surface
->output
,
4777 "%04x", (int) (utf16
[i
]));
4779 _cairo_output_stream_printf (surface
->output
, ">");
4783 return CAIRO_STATUS_SUCCESS
;
4788 * Public domain code from:
4789 * http://burtleburtle.net/bob/hash/doobs.html
4792 #define HASH_MIX(a,b,c) \
4794 a -= b; a -= c; a ^= (c>>13); \
4795 b -= c; b -= a; b ^= (a<<8); \
4796 c -= a; c -= b; c ^= (b>>13); \
4797 a -= b; a -= c; a ^= (c>>12); \
4798 b -= c; b -= a; b ^= (a<<16); \
4799 c -= a; c -= b; c ^= (b>>5); \
4800 a -= b; a -= c; a ^= (c>>3); \
4801 b -= c; b -= a; b ^= (a<<10); \
4802 c -= a; c -= b; c ^= (b>>15); \
4806 _hash_data (const unsigned char *data
, int length
, uint32_t initval
)
4808 uint32_t a
, b
, c
, len
;
4811 a
= b
= 0x9e3779b9; /* the golden ratio; an arbitrary value */
4812 c
= initval
; /* the previous hash value */
4815 a
+= (data
[0] + ((uint32_t)data
[1]<<8) + ((uint32_t)data
[2]<<16) + ((uint32_t)data
[3]<<24));
4816 b
+= (data
[4] + ((uint32_t)data
[5]<<8) + ((uint32_t)data
[6]<<16) + ((uint32_t)data
[7]<<24));
4817 c
+= (data
[8] + ((uint32_t)data
[9]<<8) + ((uint32_t)data
[10]<<16)+ ((uint32_t)data
[11]<<24));
4825 case 11: c
+= ((uint32_t) data
[10] << 24);
4826 case 10: c
+= ((uint32_t) data
[9] << 16);
4827 case 9 : c
+= ((uint32_t) data
[8] << 8);
4828 case 8 : b
+= ((uint32_t) data
[7] << 24);
4829 case 7 : b
+= ((uint32_t) data
[6] << 16);
4830 case 6 : b
+= ((uint32_t) data
[5] << 8);
4831 case 5 : b
+= data
[4];
4832 case 4 : a
+= ((uint32_t) data
[3] << 24);
4833 case 3 : a
+= ((uint32_t) data
[2] << 16);
4834 case 2 : a
+= ((uint32_t) data
[1] << 8);
4835 case 1 : a
+= data
[0];
4843 _create_font_subset_tag (cairo_scaled_font_subset_t
*font_subset
,
4844 const char *font_name
,
4852 hash
= _hash_data ((unsigned char *) font_name
, strlen(font_name
), 0);
4853 hash
= _hash_data ((unsigned char *) (font_subset
->glyphs
),
4854 font_subset
->num_glyphs
* sizeof(unsigned long), hash
);
4856 numerator
= abs (hash
);
4857 for (i
= 0; i
< 6; i
++) {
4858 d
= ldiv (numerator
, 26);
4860 tag
[i
] = 'A' + d
.rem
;
4865 static cairo_int_status_t
4866 _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t
*surface
,
4867 cairo_scaled_font_subset_t
*font_subset
,
4868 cairo_pdf_resource_t
*stream
)
4870 unsigned int i
, num_bfchar
;
4871 cairo_int_status_t status
;
4875 status
= _cairo_pdf_surface_open_stream (surface
,
4877 surface
->compress_content
,
4879 if (unlikely (status
))
4882 _cairo_output_stream_printf (surface
->output
,
4883 "/CIDInit /ProcSet findresource begin\n"
4887 "<< /Registry (Adobe)\n"
4888 " /Ordering (UCS)\n"
4891 "/CMapName /Adobe-Identity-UCS def\n"
4893 "1 begincodespacerange\n");
4895 if (font_subset
->is_composite
&& !font_subset
->is_latin
) {
4896 _cairo_output_stream_printf (surface
->output
,
4899 _cairo_output_stream_printf (surface
->output
,
4903 _cairo_output_stream_printf (surface
->output
,
4904 "endcodespacerange\n");
4906 if (font_subset
->is_scaled
) {
4907 /* Type 3 fonts include glyph 0 in the subset */
4908 num_bfchar
= font_subset
->num_glyphs
;
4910 /* The CMap specification has a limit of 100 characters per beginbfchar operator */
4911 _cairo_output_stream_printf (surface
->output
,
4913 num_bfchar
> 100 ? 100 : num_bfchar
);
4915 for (i
= 0; i
< num_bfchar
; i
++) {
4916 if (i
!= 0 && i
% 100 == 0) {
4917 _cairo_output_stream_printf (surface
->output
,
4920 num_bfchar
- i
> 100 ? 100 : num_bfchar
- i
);
4922 _cairo_output_stream_printf (surface
->output
, "<%02x> ", i
);
4923 status
= _cairo_pdf_surface_emit_unicode_for_glyph (surface
,
4924 font_subset
->utf8
[i
]);
4925 if (unlikely (status
))
4928 _cairo_output_stream_printf (surface
->output
,
4932 /* Other fonts reserve glyph 0 for .notdef. Omit glyph 0 from the /ToUnicode map */
4933 num_bfchar
= font_subset
->num_glyphs
- 1;
4935 /* The CMap specification has a limit of 100 characters per beginbfchar operator */
4936 _cairo_output_stream_printf (surface
->output
,
4938 num_bfchar
> 100 ? 100 : num_bfchar
);
4940 for (i
= 0; i
< num_bfchar
; i
++) {
4941 if (i
!= 0 && i
% 100 == 0) {
4942 _cairo_output_stream_printf (surface
->output
,
4945 num_bfchar
- i
> 100 ? 100 : num_bfchar
- i
);
4947 if (font_subset
->is_latin
)
4948 _cairo_output_stream_printf (surface
->output
, "<%02x> ", font_subset
->to_latin_char
[i
+ 1]);
4949 else if (font_subset
->is_composite
)
4950 _cairo_output_stream_printf (surface
->output
, "<%04x> ", i
+ 1);
4952 _cairo_output_stream_printf (surface
->output
, "<%02x> ", i
+ 1);
4954 status
= _cairo_pdf_surface_emit_unicode_for_glyph (surface
,
4955 font_subset
->utf8
[i
+ 1]);
4956 if (unlikely (status
))
4959 _cairo_output_stream_printf (surface
->output
,
4964 _cairo_output_stream_printf (surface
->output
,
4967 _cairo_output_stream_printf (surface
->output
,
4969 "CMapName currentdict /CMap defineresource pop\n"
4973 *stream
= surface
->pdf_stream
.self
;
4974 return _cairo_pdf_surface_close_stream (surface
);
4977 #define PDF_UNITS_PER_EM 1000
4979 static cairo_int_status_t
4980 _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t
*surface
,
4981 cairo_scaled_font_subset_t
*font_subset
,
4982 cairo_cff_subset_t
*subset
)
4984 cairo_pdf_resource_t stream
, descriptor
, cidfont_dict
;
4985 cairo_pdf_resource_t subset_resource
, to_unicode_stream
;
4986 cairo_pdf_font_t font
;
4987 unsigned int i
, last_glyph
;
4988 cairo_int_status_t status
;
4991 _create_font_subset_tag (font_subset
, subset
->ps_name
, tag
);
4993 subset_resource
= _cairo_pdf_surface_get_font_resource (surface
,
4994 font_subset
->font_id
,
4995 font_subset
->subset_id
);
4996 if (subset_resource
.id
== 0)
4997 return CAIRO_STATUS_SUCCESS
;
4999 status
= _cairo_pdf_surface_open_stream (surface
,
5002 font_subset
->is_latin
?
5003 " /Subtype /Type1C\n" :
5004 " /Subtype /CIDFontType0C\n");
5005 if (unlikely (status
))
5008 stream
= surface
->pdf_stream
.self
;
5009 _cairo_output_stream_write (surface
->output
,
5010 subset
->data
, subset
->data_length
);
5011 status
= _cairo_pdf_surface_close_stream (surface
);
5012 if (unlikely (status
))
5015 status
= _cairo_pdf_surface_emit_to_unicode_stream (surface
,
5017 &to_unicode_stream
);
5018 if (_cairo_int_status_is_error (status
))
5021 descriptor
= _cairo_pdf_surface_new_object (surface
);
5022 if (descriptor
.id
== 0)
5023 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
5025 _cairo_output_stream_printf (surface
->output
,
5027 "<< /Type /FontDescriptor\n"
5028 " /FontName /%s+%s\n",
5033 if (subset
->family_name_utf8
) {
5036 status
= _utf8_to_pdf_string (subset
->family_name_utf8
, &pdf_str
);
5037 if (unlikely (status
))
5040 _cairo_output_stream_printf (surface
->output
,
5041 " /FontFamily %s\n",
5046 _cairo_output_stream_printf (surface
->output
,
5048 " /FontBBox [ %ld %ld %ld %ld ]\n"
5055 " /FontFile3 %u 0 R\n"
5058 (long)(subset
->x_min
*PDF_UNITS_PER_EM
),
5059 (long)(subset
->y_min
*PDF_UNITS_PER_EM
),
5060 (long)(subset
->x_max
*PDF_UNITS_PER_EM
),
5061 (long)(subset
->y_max
*PDF_UNITS_PER_EM
),
5062 (long)(subset
->ascent
*PDF_UNITS_PER_EM
),
5063 (long)(subset
->descent
*PDF_UNITS_PER_EM
),
5064 (long)(subset
->y_max
*PDF_UNITS_PER_EM
),
5067 if (font_subset
->is_latin
) {
5068 /* find last glyph used */
5069 for (i
= 255; i
>= 32; i
--)
5070 if (font_subset
->latin_to_subset_glyph_index
[i
] > 0)
5074 _cairo_pdf_surface_update_object (surface
, subset_resource
);
5075 _cairo_output_stream_printf (surface
->output
,
5078 " /Subtype /Type1\n"
5079 " /BaseFont /%s+%s\n"
5082 " /FontDescriptor %d 0 R\n"
5083 " /Encoding /WinAnsiEncoding\n"
5091 for (i
= 32; i
< last_glyph
+ 1; i
++) {
5092 int glyph
= font_subset
->latin_to_subset_glyph_index
[i
];
5094 _cairo_output_stream_printf (surface
->output
,
5096 (long)(subset
->widths
[glyph
]*PDF_UNITS_PER_EM
));
5098 _cairo_output_stream_printf (surface
->output
, " 0");
5102 _cairo_output_stream_printf (surface
->output
,
5105 if (to_unicode_stream
.id
!= 0)
5106 _cairo_output_stream_printf (surface
->output
,
5107 " /ToUnicode %d 0 R\n",
5108 to_unicode_stream
.id
);
5110 _cairo_output_stream_printf (surface
->output
,
5114 cidfont_dict
= _cairo_pdf_surface_new_object (surface
);
5115 if (cidfont_dict
.id
== 0)
5116 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
5118 _cairo_output_stream_printf (surface
->output
,
5121 " /Subtype /CIDFontType0\n"
5122 " /BaseFont /%s+%s\n"
5124 " << /Registry (Adobe)\n"
5125 " /Ordering (Identity)\n"
5128 " /FontDescriptor %d 0 R\n"
5135 for (i
= 0; i
< font_subset
->num_glyphs
; i
++)
5136 _cairo_output_stream_printf (surface
->output
,
5138 (long)(subset
->widths
[i
]*PDF_UNITS_PER_EM
));
5140 _cairo_output_stream_printf (surface
->output
,
5145 _cairo_pdf_surface_update_object (surface
, subset_resource
);
5146 _cairo_output_stream_printf (surface
->output
,
5149 " /Subtype /Type0\n"
5150 " /BaseFont /%s+%s\n"
5151 " /Encoding /Identity-H\n"
5152 " /DescendantFonts [ %d 0 R]\n",
5158 if (to_unicode_stream
.id
!= 0)
5159 _cairo_output_stream_printf (surface
->output
,
5160 " /ToUnicode %d 0 R\n",
5161 to_unicode_stream
.id
);
5163 _cairo_output_stream_printf (surface
->output
,
5168 font
.font_id
= font_subset
->font_id
;
5169 font
.subset_id
= font_subset
->subset_id
;
5170 font
.subset_resource
= subset_resource
;
5171 status
= _cairo_array_append (&surface
->fonts
, &font
);
5176 static cairo_int_status_t
5177 _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t
*surface
,
5178 cairo_scaled_font_subset_t
*font_subset
)
5180 cairo_int_status_t status
;
5181 cairo_cff_subset_t subset
;
5184 snprintf (name
, sizeof name
, "CairoFont-%d-%d",
5185 font_subset
->font_id
, font_subset
->subset_id
);
5186 status
= _cairo_cff_subset_init (&subset
, name
, font_subset
);
5187 if (unlikely (status
))
5190 status
= _cairo_pdf_surface_emit_cff_font (surface
, font_subset
, &subset
);
5192 _cairo_cff_subset_fini (&subset
);
5197 static cairo_int_status_t
5198 _cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t
*surface
,
5199 cairo_scaled_font_subset_t
*font_subset
)
5201 cairo_int_status_t status
;
5202 cairo_cff_subset_t subset
;
5205 /* CFF fallback subsetting does not work with 8-bit glyphs unless
5206 * they are a latin subset */
5207 if (!font_subset
->is_composite
&& !font_subset
->is_latin
)
5208 return CAIRO_INT_STATUS_UNSUPPORTED
;
5210 snprintf (name
, sizeof name
, "CairoFont-%d-%d",
5211 font_subset
->font_id
, font_subset
->subset_id
);
5212 status
= _cairo_cff_fallback_init (&subset
, name
, font_subset
);
5213 if (unlikely (status
))
5216 status
= _cairo_pdf_surface_emit_cff_font (surface
, font_subset
, &subset
);
5218 _cairo_cff_fallback_fini (&subset
);
5223 static cairo_int_status_t
5224 _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t
*surface
,
5225 cairo_scaled_font_subset_t
*font_subset
,
5226 cairo_type1_subset_t
*subset
)
5228 cairo_pdf_resource_t stream
, descriptor
, subset_resource
, to_unicode_stream
;
5229 cairo_pdf_font_t font
;
5230 cairo_int_status_t status
;
5231 unsigned long length
;
5232 unsigned int i
, last_glyph
;
5235 _create_font_subset_tag (font_subset
, subset
->base_font
, tag
);
5237 subset_resource
= _cairo_pdf_surface_get_font_resource (surface
,
5238 font_subset
->font_id
,
5239 font_subset
->subset_id
);
5240 if (subset_resource
.id
== 0)
5241 return CAIRO_STATUS_SUCCESS
;
5243 length
= subset
->header_length
+ subset
->data_length
+ subset
->trailer_length
;
5244 status
= _cairo_pdf_surface_open_stream (surface
,
5250 subset
->header_length
,
5251 subset
->data_length
,
5252 subset
->trailer_length
);
5253 if (unlikely (status
))
5256 stream
= surface
->pdf_stream
.self
;
5257 _cairo_output_stream_write (surface
->output
, subset
->data
, length
);
5258 status
= _cairo_pdf_surface_close_stream (surface
);
5259 if (unlikely (status
))
5262 status
= _cairo_pdf_surface_emit_to_unicode_stream (surface
,
5264 &to_unicode_stream
);
5265 if (_cairo_int_status_is_error (status
))
5268 last_glyph
= font_subset
->num_glyphs
- 1;
5269 if (font_subset
->is_latin
) {
5270 /* find last glyph used */
5271 for (i
= 255; i
>= 32; i
--)
5272 if (font_subset
->latin_to_subset_glyph_index
[i
] > 0)
5278 descriptor
= _cairo_pdf_surface_new_object (surface
);
5279 if (descriptor
.id
== 0)
5280 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
5282 _cairo_output_stream_printf (surface
->output
,
5284 "<< /Type /FontDescriptor\n"
5285 " /FontName /%s+%s\n"
5287 " /FontBBox [ %ld %ld %ld %ld ]\n"
5294 " /FontFile %u 0 R\n"
5300 (long)(subset
->x_min
*PDF_UNITS_PER_EM
),
5301 (long)(subset
->y_min
*PDF_UNITS_PER_EM
),
5302 (long)(subset
->x_max
*PDF_UNITS_PER_EM
),
5303 (long)(subset
->y_max
*PDF_UNITS_PER_EM
),
5304 (long)(subset
->ascent
*PDF_UNITS_PER_EM
),
5305 (long)(subset
->descent
*PDF_UNITS_PER_EM
),
5306 (long)(subset
->y_max
*PDF_UNITS_PER_EM
),
5309 _cairo_pdf_surface_update_object (surface
, subset_resource
);
5310 _cairo_output_stream_printf (surface
->output
,
5313 " /Subtype /Type1\n"
5314 " /BaseFont /%s+%s\n"
5317 " /FontDescriptor %d 0 R\n",
5321 font_subset
->is_latin
? 32 : 0,
5325 if (font_subset
->is_latin
)
5326 _cairo_output_stream_printf (surface
->output
, " /Encoding /WinAnsiEncoding\n");
5328 _cairo_output_stream_printf (surface
->output
, " /Widths [");
5329 if (font_subset
->is_latin
) {
5330 for (i
= 32; i
< last_glyph
+ 1; i
++) {
5331 int glyph
= font_subset
->latin_to_subset_glyph_index
[i
];
5333 _cairo_output_stream_printf (surface
->output
,
5335 (long)(subset
->widths
[glyph
]*PDF_UNITS_PER_EM
));
5337 _cairo_output_stream_printf (surface
->output
, " 0");
5341 for (i
= 0; i
< font_subset
->num_glyphs
; i
++)
5342 _cairo_output_stream_printf (surface
->output
,
5344 (long)(subset
->widths
[i
]*PDF_UNITS_PER_EM
));
5347 _cairo_output_stream_printf (surface
->output
,
5350 if (to_unicode_stream
.id
!= 0)
5351 _cairo_output_stream_printf (surface
->output
,
5352 " /ToUnicode %d 0 R\n",
5353 to_unicode_stream
.id
);
5355 _cairo_output_stream_printf (surface
->output
,
5359 font
.font_id
= font_subset
->font_id
;
5360 font
.subset_id
= font_subset
->subset_id
;
5361 font
.subset_resource
= subset_resource
;
5362 return _cairo_array_append (&surface
->fonts
, &font
);
5365 static cairo_int_status_t
5366 _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t
*surface
,
5367 cairo_scaled_font_subset_t
*font_subset
)
5369 cairo_int_status_t status
;
5370 cairo_type1_subset_t subset
;
5373 /* 16-bit glyphs not compatible with Type 1 fonts */
5374 if (font_subset
->is_composite
&& !font_subset
->is_latin
)
5375 return CAIRO_INT_STATUS_UNSUPPORTED
;
5377 snprintf (name
, sizeof name
, "CairoFont-%d-%d",
5378 font_subset
->font_id
, font_subset
->subset_id
);
5379 status
= _cairo_type1_subset_init (&subset
, name
, font_subset
, FALSE
);
5380 if (unlikely (status
))
5383 status
= _cairo_pdf_surface_emit_type1_font (surface
, font_subset
, &subset
);
5385 _cairo_type1_subset_fini (&subset
);
5389 static cairo_int_status_t
5390 _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t
*surface
,
5391 cairo_scaled_font_subset_t
*font_subset
)
5393 cairo_int_status_t status
;
5394 cairo_type1_subset_t subset
;
5397 /* 16-bit glyphs not compatible with Type 1 fonts */
5398 if (font_subset
->is_composite
&& !font_subset
->is_latin
)
5399 return CAIRO_INT_STATUS_UNSUPPORTED
;
5401 snprintf (name
, sizeof name
, "CairoFont-%d-%d",
5402 font_subset
->font_id
, font_subset
->subset_id
);
5403 status
= _cairo_type1_fallback_init_binary (&subset
, name
, font_subset
);
5404 if (unlikely (status
))
5407 status
= _cairo_pdf_surface_emit_type1_font (surface
, font_subset
, &subset
);
5409 _cairo_type1_fallback_fini (&subset
);
5413 static cairo_int_status_t
5414 _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t
*surface
,
5415 cairo_scaled_font_subset_t
*font_subset
)
5417 cairo_pdf_resource_t stream
, descriptor
, cidfont_dict
;
5418 cairo_pdf_resource_t subset_resource
, to_unicode_stream
;
5419 cairo_int_status_t status
;
5420 cairo_pdf_font_t font
;
5421 cairo_truetype_subset_t subset
;
5422 unsigned int i
, last_glyph
;
5425 subset_resource
= _cairo_pdf_surface_get_font_resource (surface
,
5426 font_subset
->font_id
,
5427 font_subset
->subset_id
);
5428 if (subset_resource
.id
== 0)
5429 return CAIRO_STATUS_SUCCESS
;
5431 status
= _cairo_truetype_subset_init_pdf (&subset
, font_subset
);
5432 if (unlikely (status
))
5435 _create_font_subset_tag (font_subset
, subset
.ps_name
, tag
);
5437 status
= _cairo_pdf_surface_open_stream (surface
,
5441 subset
.data_length
);
5442 if (unlikely (status
)) {
5443 _cairo_truetype_subset_fini (&subset
);
5447 stream
= surface
->pdf_stream
.self
;
5448 _cairo_output_stream_write (surface
->output
,
5449 subset
.data
, subset
.data_length
);
5450 status
= _cairo_pdf_surface_close_stream (surface
);
5451 if (unlikely (status
)) {
5452 _cairo_truetype_subset_fini (&subset
);
5456 status
= _cairo_pdf_surface_emit_to_unicode_stream (surface
,
5458 &to_unicode_stream
);
5459 if (_cairo_int_status_is_error (status
)) {
5460 _cairo_truetype_subset_fini (&subset
);
5464 descriptor
= _cairo_pdf_surface_new_object (surface
);
5465 if (descriptor
.id
== 0) {
5466 _cairo_truetype_subset_fini (&subset
);
5467 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
5470 _cairo_output_stream_printf (surface
->output
,
5472 "<< /Type /FontDescriptor\n"
5473 " /FontName /%s+%s\n",
5478 if (subset
.family_name_utf8
) {
5481 status
= _utf8_to_pdf_string (subset
.family_name_utf8
, &pdf_str
);
5482 if (unlikely (status
))
5485 _cairo_output_stream_printf (surface
->output
,
5486 " /FontFamily %s\n",
5491 _cairo_output_stream_printf (surface
->output
,
5493 " /FontBBox [ %ld %ld %ld %ld ]\n"
5500 " /FontFile2 %u 0 R\n"
5503 font_subset
->is_latin
? 32 : 4,
5504 (long)(subset
.x_min
*PDF_UNITS_PER_EM
),
5505 (long)(subset
.y_min
*PDF_UNITS_PER_EM
),
5506 (long)(subset
.x_max
*PDF_UNITS_PER_EM
),
5507 (long)(subset
.y_max
*PDF_UNITS_PER_EM
),
5508 (long)(subset
.ascent
*PDF_UNITS_PER_EM
),
5509 (long)(subset
.descent
*PDF_UNITS_PER_EM
),
5510 (long)(subset
.y_max
*PDF_UNITS_PER_EM
),
5513 if (font_subset
->is_latin
) {
5514 /* find last glyph used */
5515 for (i
= 255; i
>= 32; i
--)
5516 if (font_subset
->latin_to_subset_glyph_index
[i
] > 0)
5520 _cairo_pdf_surface_update_object (surface
, subset_resource
);
5521 _cairo_output_stream_printf (surface
->output
,
5524 " /Subtype /TrueType\n"
5525 " /BaseFont /%s+%s\n"
5528 " /FontDescriptor %d 0 R\n"
5529 " /Encoding /WinAnsiEncoding\n"
5537 for (i
= 32; i
< last_glyph
+ 1; i
++) {
5538 int glyph
= font_subset
->latin_to_subset_glyph_index
[i
];
5540 _cairo_output_stream_printf (surface
->output
,
5542 (long)(subset
.widths
[glyph
]*PDF_UNITS_PER_EM
));
5544 _cairo_output_stream_printf (surface
->output
, " 0");
5548 _cairo_output_stream_printf (surface
->output
,
5551 if (to_unicode_stream
.id
!= 0)
5552 _cairo_output_stream_printf (surface
->output
,
5553 " /ToUnicode %d 0 R\n",
5554 to_unicode_stream
.id
);
5556 _cairo_output_stream_printf (surface
->output
,
5560 cidfont_dict
= _cairo_pdf_surface_new_object (surface
);
5561 if (cidfont_dict
.id
== 0) {
5562 _cairo_truetype_subset_fini (&subset
);
5563 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
5566 _cairo_output_stream_printf (surface
->output
,
5569 " /Subtype /CIDFontType2\n"
5570 " /BaseFont /%s+%s\n"
5572 " << /Registry (Adobe)\n"
5573 " /Ordering (Identity)\n"
5576 " /FontDescriptor %d 0 R\n"
5583 for (i
= 0; i
< font_subset
->num_glyphs
; i
++)
5584 _cairo_output_stream_printf (surface
->output
,
5586 (long)(subset
.widths
[i
]*PDF_UNITS_PER_EM
));
5588 _cairo_output_stream_printf (surface
->output
,
5593 _cairo_pdf_surface_update_object (surface
, subset_resource
);
5594 _cairo_output_stream_printf (surface
->output
,
5597 " /Subtype /Type0\n"
5598 " /BaseFont /%s+%s\n"
5599 " /Encoding /Identity-H\n"
5600 " /DescendantFonts [ %d 0 R]\n",
5606 if (to_unicode_stream
.id
!= 0)
5607 _cairo_output_stream_printf (surface
->output
,
5608 " /ToUnicode %d 0 R\n",
5609 to_unicode_stream
.id
);
5611 _cairo_output_stream_printf (surface
->output
,
5616 font
.font_id
= font_subset
->font_id
;
5617 font
.subset_id
= font_subset
->subset_id
;
5618 font
.subset_resource
= subset_resource
;
5619 status
= _cairo_array_append (&surface
->fonts
, &font
);
5621 _cairo_truetype_subset_fini (&subset
);
5626 static cairo_int_status_t
5627 _cairo_pdf_emit_imagemask (cairo_image_surface_t
*image
,
5628 cairo_output_stream_t
*stream
)
5630 uint8_t *byte
, output_byte
;
5631 int row
, col
, num_cols
;
5633 /* The only image type supported by Type 3 fonts are 1-bit image
5635 assert (image
->format
== CAIRO_FORMAT_A1
);
5637 _cairo_output_stream_printf (stream
,
5647 _cairo_output_stream_printf (stream
,
5650 num_cols
= (image
->width
+ 7) / 8;
5651 for (row
= 0; row
< image
->height
; row
++) {
5652 byte
= image
->data
+ row
* image
->stride
;
5653 for (col
= 0; col
< num_cols
; col
++) {
5654 output_byte
= CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte
);
5655 _cairo_output_stream_write (stream
, &output_byte
, 1);
5660 _cairo_output_stream_printf (stream
,
5663 return _cairo_output_stream_get_status (stream
);
5666 static cairo_int_status_t
5667 _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t
*font_subset
,
5670 cairo_pdf_surface_t
*surface
= closure
;
5671 cairo_int_status_t status
= CAIRO_INT_STATUS_SUCCESS
;
5672 cairo_int_status_t status2
;
5674 cairo_surface_t
*type3_surface
;
5675 cairo_output_stream_t
*null_stream
;
5677 null_stream
= _cairo_null_stream_create ();
5678 type3_surface
= _cairo_type3_glyph_surface_create (font_subset
->scaled_font
,
5680 _cairo_pdf_emit_imagemask
,
5681 surface
->font_subsets
,
5683 if (unlikely (type3_surface
->status
)) {
5684 status2
= _cairo_output_stream_destroy (null_stream
);
5685 return type3_surface
->status
;
5688 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface
,
5689 _cairo_pdf_surface_add_font
,
5692 for (i
= 0; i
< font_subset
->num_glyphs
; i
++) {
5693 status
= _cairo_type3_glyph_surface_analyze_glyph (type3_surface
,
5694 font_subset
->glyphs
[i
]);
5695 if (unlikely (status
))
5699 cairo_surface_destroy (type3_surface
);
5700 status2
= _cairo_output_stream_destroy (null_stream
);
5701 if (status
== CAIRO_INT_STATUS_SUCCESS
)
5707 static cairo_int_status_t
5708 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t
*surface
,
5709 cairo_scaled_font_subset_t
*font_subset
)
5711 cairo_int_status_t status
= CAIRO_STATUS_SUCCESS
;
5712 cairo_pdf_resource_t
*glyphs
, encoding
, char_procs
, subset_resource
, to_unicode_stream
;
5713 cairo_pdf_font_t font
;
5716 cairo_box_t font_bbox
= {{0,0},{0,0}};
5717 cairo_box_t bbox
= {{0,0},{0,0}};
5718 cairo_surface_t
*type3_surface
;
5720 if (font_subset
->num_glyphs
== 0)
5721 return CAIRO_STATUS_SUCCESS
;
5723 subset_resource
= _cairo_pdf_surface_get_font_resource (surface
,
5724 font_subset
->font_id
,
5725 font_subset
->subset_id
);
5726 if (subset_resource
.id
== 0)
5727 return CAIRO_STATUS_SUCCESS
;
5729 glyphs
= _cairo_malloc_ab (font_subset
->num_glyphs
, sizeof (cairo_pdf_resource_t
));
5730 if (unlikely (glyphs
== NULL
))
5731 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
5733 widths
= _cairo_malloc_ab (font_subset
->num_glyphs
, sizeof (double));
5734 if (unlikely (widths
== NULL
)) {
5736 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
5739 _cairo_pdf_group_resources_clear (&surface
->resources
);
5740 type3_surface
= _cairo_type3_glyph_surface_create (font_subset
->scaled_font
,
5742 _cairo_pdf_emit_imagemask
,
5743 surface
->font_subsets
,
5745 if (unlikely (type3_surface
->status
)) {
5748 return type3_surface
->status
;
5751 _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface
,
5752 _cairo_pdf_surface_add_font
,
5755 for (i
= 0; i
< font_subset
->num_glyphs
; i
++) {
5756 status
= _cairo_pdf_surface_open_stream (surface
,
5758 surface
->compress_content
,
5760 if (unlikely (status
))
5763 glyphs
[i
] = surface
->pdf_stream
.self
;
5764 status
= _cairo_type3_glyph_surface_emit_glyph (type3_surface
,
5766 font_subset
->glyphs
[i
],
5769 if (unlikely (status
))
5772 status
= _cairo_pdf_surface_close_stream (surface
);
5773 if (unlikely (status
))
5777 font_bbox
.p1
.x
= bbox
.p1
.x
;
5778 font_bbox
.p1
.y
= bbox
.p1
.y
;
5779 font_bbox
.p2
.x
= bbox
.p2
.x
;
5780 font_bbox
.p2
.y
= bbox
.p2
.y
;
5782 if (bbox
.p1
.x
< font_bbox
.p1
.x
)
5783 font_bbox
.p1
.x
= bbox
.p1
.x
;
5784 if (bbox
.p1
.y
< font_bbox
.p1
.y
)
5785 font_bbox
.p1
.y
= bbox
.p1
.y
;
5786 if (bbox
.p2
.x
> font_bbox
.p2
.x
)
5787 font_bbox
.p2
.x
= bbox
.p2
.x
;
5788 if (bbox
.p2
.y
> font_bbox
.p2
.y
)
5789 font_bbox
.p2
.y
= bbox
.p2
.y
;
5792 cairo_surface_destroy (type3_surface
);
5793 if (unlikely (status
)) {
5799 encoding
= _cairo_pdf_surface_new_object (surface
);
5800 if (encoding
.id
== 0) {
5803 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
5806 _cairo_output_stream_printf (surface
->output
,
5808 "<< /Type /Encoding\n"
5809 " /Differences [0", encoding
.id
);
5810 for (i
= 0; i
< font_subset
->num_glyphs
; i
++)
5811 _cairo_output_stream_printf (surface
->output
,
5813 _cairo_output_stream_printf (surface
->output
,
5818 char_procs
= _cairo_pdf_surface_new_object (surface
);
5819 if (char_procs
.id
== 0) {
5822 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
5825 _cairo_output_stream_printf (surface
->output
,
5827 "<<\n", char_procs
.id
);
5828 for (i
= 0; i
< font_subset
->num_glyphs
; i
++)
5829 _cairo_output_stream_printf (surface
->output
,
5832 _cairo_output_stream_printf (surface
->output
,
5838 status
= _cairo_pdf_surface_emit_to_unicode_stream (surface
,
5840 &to_unicode_stream
);
5841 if (_cairo_int_status_is_error (status
)) {
5846 _cairo_pdf_surface_update_object (surface
, subset_resource
);
5847 _cairo_output_stream_printf (surface
->output
,
5850 " /Subtype /Type3\n"
5851 " /FontBBox [%f %f %f %f]\n"
5852 " /FontMatrix [ 1 0 0 1 0 0 ]\n"
5853 " /Encoding %d 0 R\n"
5854 " /CharProcs %d 0 R\n"
5858 _cairo_fixed_to_double (font_bbox
.p1
.x
),
5859 - _cairo_fixed_to_double (font_bbox
.p2
.y
),
5860 _cairo_fixed_to_double (font_bbox
.p2
.x
),
5861 - _cairo_fixed_to_double (font_bbox
.p1
.y
),
5864 font_subset
->num_glyphs
- 1);
5866 _cairo_output_stream_printf (surface
->output
,
5868 for (i
= 0; i
< font_subset
->num_glyphs
; i
++)
5869 _cairo_output_stream_printf (surface
->output
, " %f", widths
[i
]);
5870 _cairo_output_stream_printf (surface
->output
,
5874 _cairo_output_stream_printf (surface
->output
,
5876 _cairo_pdf_surface_emit_group_resources (surface
, &surface
->resources
);
5878 if (to_unicode_stream
.id
!= 0)
5879 _cairo_output_stream_printf (surface
->output
,
5880 " /ToUnicode %d 0 R\n",
5881 to_unicode_stream
.id
);
5883 _cairo_output_stream_printf (surface
->output
,
5887 font
.font_id
= font_subset
->font_id
;
5888 font
.subset_id
= font_subset
->subset_id
;
5889 font
.subset_resource
= subset_resource
;
5890 return _cairo_array_append (&surface
->fonts
, &font
);
5893 static cairo_int_status_t
5894 _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t
*font_subset
,
5897 cairo_pdf_surface_t
*surface
= closure
;
5898 cairo_int_status_t status
;
5900 status
= _cairo_pdf_surface_emit_cff_font_subset (surface
, font_subset
);
5901 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
5904 status
= _cairo_pdf_surface_emit_truetype_font_subset (surface
, font_subset
);
5905 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
5908 status
= _cairo_pdf_surface_emit_type1_font_subset (surface
, font_subset
);
5909 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
5912 status
= _cairo_pdf_surface_emit_cff_fallback_font (surface
, font_subset
);
5913 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
5916 status
= _cairo_pdf_surface_emit_type1_fallback_font (surface
, font_subset
);
5917 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
5921 return CAIRO_INT_STATUS_SUCCESS
;
5924 static cairo_int_status_t
5925 _cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t
*font_subset
,
5928 cairo_pdf_surface_t
*surface
= closure
;
5929 cairo_int_status_t status
;
5931 status
= _cairo_pdf_surface_emit_type3_font_subset (surface
, font_subset
);
5932 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
5936 return CAIRO_INT_STATUS_SUCCESS
;
5939 static cairo_int_status_t
5940 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t
*surface
)
5942 cairo_int_status_t status
;
5944 status
= _cairo_scaled_font_subsets_foreach_user (surface
->font_subsets
,
5945 _cairo_pdf_surface_analyze_user_font_subset
,
5947 if (unlikely (status
))
5950 status
= _cairo_scaled_font_subsets_foreach_unscaled (surface
->font_subsets
,
5951 _cairo_pdf_surface_emit_unscaled_font_subset
,
5953 if (unlikely (status
))
5956 status
= _cairo_scaled_font_subsets_foreach_scaled (surface
->font_subsets
,
5957 _cairo_pdf_surface_emit_scaled_font_subset
,
5959 if (unlikely (status
))
5962 status
= _cairo_scaled_font_subsets_foreach_user (surface
->font_subsets
,
5963 _cairo_pdf_surface_emit_scaled_font_subset
,
5967 _cairo_scaled_font_subsets_destroy (surface
->font_subsets
);
5968 surface
->font_subsets
= NULL
;
5973 static cairo_pdf_resource_t
5974 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t
*surface
)
5976 cairo_pdf_resource_t catalog
;
5978 catalog
= _cairo_pdf_surface_new_object (surface
);
5979 if (catalog
.id
== 0)
5982 _cairo_output_stream_printf (surface
->output
,
5984 "<< /Type /Catalog\n"
5989 surface
->pages_resource
.id
);
5995 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t
*surface
)
5997 cairo_pdf_object_t
*object
;
6002 num_objects
= _cairo_array_num_elements (&surface
->objects
);
6004 offset
= _cairo_output_stream_get_position (surface
->output
);
6005 _cairo_output_stream_printf (surface
->output
,
6008 0, num_objects
+ 1);
6010 _cairo_output_stream_printf (surface
->output
,
6011 "0000000000 65535 f \n");
6012 for (i
= 0; i
< num_objects
; i
++) {
6013 object
= _cairo_array_index (&surface
->objects
, i
);
6014 snprintf (buffer
, sizeof buffer
, "%010ld", object
->offset
);
6015 _cairo_output_stream_printf (surface
->output
,
6016 "%s 00000 n \n", buffer
);
6022 static cairo_int_status_t
6023 _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t
*surface
,
6024 cairo_pdf_smask_group_t
*group
)
6026 cairo_pdf_resource_t mask_group
;
6027 cairo_pdf_resource_t smask
;
6028 cairo_pdf_smask_group_t
*smask_group
;
6029 cairo_pdf_resource_t pattern_res
, gstate_res
;
6030 cairo_int_status_t status
;
6031 cairo_box_double_t bbox
;
6033 /* Create mask group */
6034 _get_bbox_from_extents (group
->height
, &group
->extents
, &bbox
);
6035 status
= _cairo_pdf_surface_open_group (surface
, &bbox
, NULL
);
6036 if (unlikely (status
))
6039 if (_can_paint_pattern (group
->mask
)) {
6040 _cairo_output_stream_printf (surface
->output
, "q\n");
6041 status
= _cairo_pdf_surface_paint_pattern (surface
,
6042 CAIRO_OPERATOR_OVER
,
6046 if (unlikely (status
))
6049 _cairo_output_stream_printf (surface
->output
, "Q\n");
6053 status
= _cairo_pdf_surface_add_pdf_pattern (surface
, group
->mask
,
6054 CAIRO_OPERATOR_OVER
,
6056 &pattern_res
, &gstate_res
);
6057 if (unlikely (status
))
6060 if (gstate_res
.id
!= 0) {
6061 smask_group
= _cairo_pdf_surface_create_smask_group (surface
, &group
->extents
);
6062 if (unlikely (smask_group
== NULL
))
6063 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
6065 smask_group
->width
= group
->width
;
6066 smask_group
->height
= group
->height
;
6067 smask_group
->operation
= PDF_PAINT
;
6068 smask_group
->source
= cairo_pattern_reference (group
->mask
);
6069 smask_group
->source_res
= pattern_res
;
6070 status
= _cairo_pdf_surface_add_smask_group (surface
, smask_group
);
6071 if (unlikely (status
)) {
6072 _cairo_pdf_smask_group_destroy (smask_group
);
6076 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
6077 if (unlikely (status
))
6080 status
= _cairo_pdf_surface_add_xobject (surface
, smask_group
->group_res
);
6081 if (unlikely (status
))
6084 _cairo_output_stream_printf (surface
->output
,
6085 "q /s%d gs /x%d Do Q\n",
6087 smask_group
->group_res
.id
);
6089 status
= _cairo_pdf_surface_select_pattern (surface
, group
->mask
, pattern_res
, FALSE
);
6090 if (unlikely (status
))
6093 _cairo_output_stream_printf (surface
->output
,
6094 "%f %f %f %f re f\n",
6097 bbox
.p2
.x
- bbox
.p1
.x
,
6098 bbox
.p2
.y
- bbox
.p1
.y
);
6100 status
= _cairo_pdf_surface_unselect_pattern (surface
);
6101 if (unlikely (status
))
6106 status
= _cairo_pdf_surface_close_group (surface
, &mask_group
);
6107 if (unlikely (status
))
6110 /* Create source group */
6111 status
= _cairo_pdf_surface_open_group (surface
, &bbox
, &group
->source_res
);
6112 if (unlikely (status
))
6115 if (_can_paint_pattern (group
->source
)) {
6116 _cairo_output_stream_printf (surface
->output
, "q\n");
6117 status
= _cairo_pdf_surface_paint_pattern (surface
,
6118 CAIRO_OPERATOR_OVER
,
6122 if (unlikely (status
))
6125 _cairo_output_stream_printf (surface
->output
, "Q\n");
6129 status
= _cairo_pdf_surface_add_pdf_pattern (surface
, group
->source
,
6130 CAIRO_OPERATOR_OVER
,
6132 &pattern_res
, &gstate_res
);
6133 if (unlikely (status
))
6136 if (gstate_res
.id
!= 0) {
6137 smask_group
= _cairo_pdf_surface_create_smask_group (surface
, &group
->extents
);
6138 if (unlikely (smask_group
== NULL
))
6139 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
6141 smask_group
->operation
= PDF_PAINT
;
6142 smask_group
->source
= cairo_pattern_reference (group
->source
);
6143 smask_group
->source_res
= pattern_res
;
6144 status
= _cairo_pdf_surface_add_smask_group (surface
, smask_group
);
6145 if (unlikely (status
)) {
6146 _cairo_pdf_smask_group_destroy (smask_group
);
6150 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
6151 if (unlikely (status
))
6154 status
= _cairo_pdf_surface_add_xobject (surface
, smask_group
->group_res
);
6155 if (unlikely (status
))
6158 _cairo_output_stream_printf (surface
->output
,
6159 "q /s%d gs /x%d Do Q\n",
6161 smask_group
->group_res
.id
);
6163 status
= _cairo_pdf_surface_select_pattern (surface
, group
->source
, pattern_res
, FALSE
);
6164 if (unlikely (status
))
6167 _cairo_output_stream_printf (surface
->output
,
6168 "%f %f %f %f re f\n",
6171 bbox
.p2
.x
- bbox
.p1
.x
,
6172 bbox
.p2
.y
- bbox
.p1
.y
);
6174 status
= _cairo_pdf_surface_unselect_pattern (surface
);
6175 if (unlikely (status
))
6180 status
= _cairo_pdf_surface_close_group (surface
, NULL
);
6181 if (unlikely (status
))
6184 /* Create an smask based on the alpha component of mask_group */
6185 smask
= _cairo_pdf_surface_new_object (surface
);
6187 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
6189 _cairo_output_stream_printf (surface
->output
,
6199 /* Create a GState that uses the smask */
6200 _cairo_pdf_surface_update_object (surface
, group
->group_res
);
6201 _cairo_output_stream_printf (surface
->output
,
6203 "<< /Type /ExtGState\n"
6210 group
->group_res
.id
,
6213 return _cairo_output_stream_get_status (surface
->output
);
6216 static cairo_int_status_t
6217 _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t
*surface
,
6218 cairo_pdf_smask_group_t
*group
)
6220 double old_width
, old_height
;
6221 cairo_int_status_t status
;
6222 cairo_box_double_t bbox
;
6224 old_width
= surface
->width
;
6225 old_height
= surface
->height
;
6226 _cairo_pdf_surface_set_size_internal (surface
,
6229 /* _mask is a special case that requires two groups - source
6230 * and mask as well as a smask and gstate dictionary */
6231 if (group
->operation
== PDF_MASK
) {
6232 status
= _cairo_pdf_surface_write_mask_group (surface
, group
);
6236 _get_bbox_from_extents (group
->height
, &group
->extents
, &bbox
);
6237 status
= _cairo_pdf_surface_open_group (surface
, &bbox
, &group
->group_res
);
6238 if (unlikely (status
))
6241 status
= _cairo_pdf_surface_select_pattern (surface
,
6244 group
->operation
== PDF_STROKE
);
6245 if (unlikely (status
))
6248 switch (group
->operation
) {
6250 _cairo_output_stream_printf (surface
->output
,
6252 surface
->width
, surface
->height
);
6258 status
= _cairo_pdf_operators_fill (&surface
->pdf_operators
,
6263 status
= _cairo_pdf_operators_stroke (&surface
->pdf_operators
,
6267 &group
->ctm_inverse
);
6269 case PDF_SHOW_GLYPHS
:
6270 status
= _cairo_pdf_operators_show_text_glyphs (&surface
->pdf_operators
,
6271 group
->utf8
, group
->utf8_len
,
6272 group
->glyphs
, group
->num_glyphs
,
6273 group
->clusters
, group
->num_clusters
,
6274 group
->cluster_flags
,
6275 group
->scaled_font
);
6278 if (unlikely (status
))
6281 status
= _cairo_pdf_surface_unselect_pattern (surface
);
6282 if (unlikely (status
))
6285 status
= _cairo_pdf_surface_close_group (surface
, NULL
);
6288 _cairo_pdf_surface_set_size_internal (surface
,
6295 static cairo_int_status_t
6296 _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t
*surface
)
6298 cairo_pdf_pattern_t pattern
;
6299 cairo_pdf_smask_group_t
*group
;
6300 cairo_pdf_source_surface_t src_surface
;
6301 unsigned int pattern_index
, group_index
, surface_index
;
6302 cairo_int_status_t status
;
6304 /* Writing out PDF_MASK groups will cause additional smask groups
6305 * to be appended to surface->smask_groups. Additional patterns
6306 * may also be appended to surface->patterns.
6308 * Writing recording surface patterns will cause additional patterns
6309 * and groups to be appended.
6314 while ((pattern_index
< _cairo_array_num_elements (&surface
->page_patterns
)) ||
6315 (group_index
< _cairo_array_num_elements (&surface
->smask_groups
)) ||
6316 (surface_index
< _cairo_array_num_elements (&surface
->page_surfaces
)))
6318 for (; group_index
< _cairo_array_num_elements (&surface
->smask_groups
); group_index
++) {
6319 _cairo_array_copy_element (&surface
->smask_groups
, group_index
, &group
);
6320 status
= _cairo_pdf_surface_write_smask_group (surface
, group
);
6321 if (unlikely (status
))
6325 for (; pattern_index
< _cairo_array_num_elements (&surface
->page_patterns
); pattern_index
++) {
6326 _cairo_array_copy_element (&surface
->page_patterns
, pattern_index
, &pattern
);
6327 status
= _cairo_pdf_surface_emit_pattern (surface
, &pattern
);
6328 if (unlikely (status
))
6332 for (; surface_index
< _cairo_array_num_elements (&surface
->page_surfaces
); surface_index
++) {
6333 _cairo_array_copy_element (&surface
->page_surfaces
, surface_index
, &src_surface
);
6334 status
= _cairo_pdf_surface_emit_surface (surface
, &src_surface
);
6335 if (unlikely (status
))
6340 return CAIRO_STATUS_SUCCESS
;
6343 static cairo_int_status_t
6344 _cairo_pdf_surface_write_page (cairo_pdf_surface_t
*surface
)
6346 cairo_pdf_resource_t page
, knockout
, res
;
6347 cairo_int_status_t status
;
6348 unsigned int i
, len
;
6350 _cairo_pdf_group_resources_clear (&surface
->resources
);
6351 if (surface
->has_fallback_images
) {
6352 cairo_rectangle_int_t extents
;
6353 cairo_box_double_t bbox
;
6357 extents
.width
= ceil (surface
->width
);
6358 extents
.height
= ceil (surface
->height
);
6359 _get_bbox_from_extents (surface
->height
, &extents
, &bbox
);
6360 status
= _cairo_pdf_surface_open_knockout_group (surface
, &bbox
);
6361 if (unlikely (status
))
6364 len
= _cairo_array_num_elements (&surface
->knockout_group
);
6365 for (i
= 0; i
< len
; i
++) {
6366 _cairo_array_copy_element (&surface
->knockout_group
, i
, &res
);
6367 _cairo_output_stream_printf (surface
->output
,
6370 status
= _cairo_pdf_surface_add_xobject (surface
, res
);
6371 if (unlikely (status
))
6374 _cairo_output_stream_printf (surface
->output
,
6376 surface
->content
.id
);
6377 status
= _cairo_pdf_surface_add_xobject (surface
, surface
->content
);
6378 if (unlikely (status
))
6381 status
= _cairo_pdf_surface_close_group (surface
, &knockout
);
6382 if (unlikely (status
))
6385 _cairo_pdf_group_resources_clear (&surface
->resources
);
6386 status
= _cairo_pdf_surface_open_content_stream (surface
, NULL
, NULL
, FALSE
, FALSE
);
6387 if (unlikely (status
))
6390 _cairo_output_stream_printf (surface
->output
,
6393 status
= _cairo_pdf_surface_add_xobject (surface
, knockout
);
6394 if (unlikely (status
))
6397 status
= _cairo_pdf_surface_close_content_stream (surface
);
6398 if (unlikely (status
))
6402 page
= _cairo_pdf_surface_new_object (surface
);
6404 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
6406 _cairo_output_stream_printf (surface
->output
,
6410 " /MediaBox [ 0 0 %f %f ]\n"
6411 " /Contents %d 0 R\n"
6414 " /S /Transparency\n"
6418 " /Resources %d 0 R\n"
6422 surface
->pages_resource
.id
,
6425 surface
->content
.id
,
6426 surface
->content_resources
.id
);
6428 status
= _cairo_array_append (&surface
->pages
, &page
);
6429 if (unlikely (status
))
6432 status
= _cairo_pdf_surface_write_patterns_and_smask_groups (surface
);
6433 if (unlikely (status
))
6436 return CAIRO_STATUS_SUCCESS
;
6439 static cairo_int_status_t
6440 _cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t
*surface
,
6441 cairo_surface_pattern_t
*pattern
)
6443 cairo_image_surface_t
*image
;
6445 cairo_int_status_t status
;
6446 cairo_image_transparency_t transparency
;
6448 status
= _cairo_surface_acquire_source_image (pattern
->surface
,
6451 if (unlikely (status
))
6454 if (image
->base
.status
)
6455 return image
->base
.status
;
6457 transparency
= _cairo_image_analyze_transparency (image
);
6458 if (transparency
== CAIRO_IMAGE_IS_OPAQUE
)
6459 status
= CAIRO_STATUS_SUCCESS
;
6461 status
= CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY
;
6463 _cairo_surface_release_source_image (pattern
->surface
, image
, image_extra
);
6469 _surface_pattern_supported (cairo_surface_pattern_t
*pattern
)
6471 cairo_extend_t extend
;
6473 if (pattern
->surface
->type
== CAIRO_SURFACE_TYPE_RECORDING
)
6476 if (pattern
->surface
->backend
->acquire_source_image
== NULL
)
6479 /* Does an ALPHA-only source surface even make sense? Maybe, but I
6480 * don't think it's worth the extra code to support it. */
6482 /* XXX: Need to write this function here...
6483 if (pattern->surface->content == CAIRO_CONTENT_ALPHA)
6487 extend
= cairo_pattern_get_extend (&pattern
->base
);
6489 case CAIRO_EXTEND_NONE
:
6490 case CAIRO_EXTEND_REPEAT
:
6491 case CAIRO_EXTEND_REFLECT
:
6492 /* There's no point returning FALSE for EXTEND_PAD, as the image
6493 * surface does not currently implement it either */
6494 case CAIRO_EXTEND_PAD
:
6503 _pattern_supported (const cairo_pattern_t
*pattern
)
6505 switch (pattern
->type
) {
6506 case CAIRO_PATTERN_TYPE_SOLID
:
6507 case CAIRO_PATTERN_TYPE_LINEAR
:
6508 case CAIRO_PATTERN_TYPE_RADIAL
:
6509 case CAIRO_PATTERN_TYPE_MESH
:
6510 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
6513 case CAIRO_PATTERN_TYPE_SURFACE
:
6514 return _surface_pattern_supported ((cairo_surface_pattern_t
*) pattern
);
6523 _pdf_operator_supported (cairo_operator_t op
)
6526 case CAIRO_OPERATOR_OVER
:
6527 case CAIRO_OPERATOR_MULTIPLY
:
6528 case CAIRO_OPERATOR_SCREEN
:
6529 case CAIRO_OPERATOR_OVERLAY
:
6530 case CAIRO_OPERATOR_DARKEN
:
6531 case CAIRO_OPERATOR_LIGHTEN
:
6532 case CAIRO_OPERATOR_COLOR_DODGE
:
6533 case CAIRO_OPERATOR_COLOR_BURN
:
6534 case CAIRO_OPERATOR_HARD_LIGHT
:
6535 case CAIRO_OPERATOR_SOFT_LIGHT
:
6536 case CAIRO_OPERATOR_DIFFERENCE
:
6537 case CAIRO_OPERATOR_EXCLUSION
:
6538 case CAIRO_OPERATOR_HSL_HUE
:
6539 case CAIRO_OPERATOR_HSL_SATURATION
:
6540 case CAIRO_OPERATOR_HSL_COLOR
:
6541 case CAIRO_OPERATOR_HSL_LUMINOSITY
:
6545 case CAIRO_OPERATOR_CLEAR
:
6546 case CAIRO_OPERATOR_SOURCE
:
6547 case CAIRO_OPERATOR_IN
:
6548 case CAIRO_OPERATOR_OUT
:
6549 case CAIRO_OPERATOR_ATOP
:
6550 case CAIRO_OPERATOR_DEST
:
6551 case CAIRO_OPERATOR_DEST_OVER
:
6552 case CAIRO_OPERATOR_DEST_IN
:
6553 case CAIRO_OPERATOR_DEST_OUT
:
6554 case CAIRO_OPERATOR_DEST_ATOP
:
6555 case CAIRO_OPERATOR_XOR
:
6556 case CAIRO_OPERATOR_ADD
:
6557 case CAIRO_OPERATOR_SATURATE
:
6562 static cairo_int_status_t
6563 _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t
*surface
,
6564 cairo_operator_t op
,
6565 const cairo_pattern_t
*pattern
,
6566 const cairo_rectangle_int_t
*extents
)
6568 if (surface
->force_fallbacks
&&
6569 surface
->paginated_mode
== CAIRO_PAGINATED_MODE_ANALYZE
)
6571 return CAIRO_INT_STATUS_UNSUPPORTED
;
6574 if (! _pattern_supported (pattern
))
6575 return CAIRO_INT_STATUS_UNSUPPORTED
;
6577 if (_pdf_operator_supported (op
)) {
6578 if (pattern
->type
== CAIRO_PATTERN_TYPE_SURFACE
) {
6579 cairo_surface_pattern_t
*surface_pattern
= (cairo_surface_pattern_t
*) pattern
;
6581 if (surface_pattern
->surface
->type
== CAIRO_SURFACE_TYPE_RECORDING
) {
6582 if (pattern
->extend
== CAIRO_EXTEND_PAD
) {
6584 cairo_rectangle_int_t rect
;
6585 cairo_rectangle_int_t rec_extents
;
6587 /* get the operation extents in pattern space */
6588 _cairo_box_from_rectangle (&box
, extents
);
6589 _cairo_matrix_transform_bounding_box_fixed (&pattern
->matrix
, &box
, NULL
);
6590 _cairo_box_round_to_rectangle (&box
, &rect
);
6592 /* Check if surface needs padding to fill extents */
6593 if (_cairo_surface_get_extents (surface_pattern
->surface
, &rec_extents
)) {
6594 if (_cairo_fixed_integer_ceil(box
.p1
.x
) < rec_extents
.x
||
6595 _cairo_fixed_integer_ceil(box
.p1
.y
) < rec_extents
.y
||
6596 _cairo_fixed_integer_floor(box
.p2
.y
) > rec_extents
.x
+ rec_extents
.width
||
6597 _cairo_fixed_integer_floor(box
.p2
.y
) > rec_extents
.y
+ rec_extents
.height
)
6599 return CAIRO_INT_STATUS_UNSUPPORTED
;
6603 return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN
;
6607 return CAIRO_STATUS_SUCCESS
;
6611 /* The SOURCE operator is supported if the pattern is opaque or if
6612 * there is nothing painted underneath. */
6613 if (op
== CAIRO_OPERATOR_SOURCE
) {
6614 if (pattern
->type
== CAIRO_PATTERN_TYPE_SURFACE
) {
6615 cairo_surface_pattern_t
*surface_pattern
= (cairo_surface_pattern_t
*) pattern
;
6617 if (surface_pattern
->surface
->type
== CAIRO_SURFACE_TYPE_RECORDING
) {
6618 if (_cairo_pattern_is_opaque (pattern
, extents
)) {
6619 return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN
;
6621 /* FIXME: The analysis surface does not yet have
6622 * the capability to analyze a non opaque recording
6623 * surface and mark it supported if there is
6624 * nothing underneath. For now recording surfaces of
6625 * type CONTENT_COLOR_ALPHA painted with
6626 * OPERATOR_SOURCE will result in a fallback
6629 return CAIRO_INT_STATUS_UNSUPPORTED
;
6632 return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface
,
6637 if (_cairo_pattern_is_opaque (pattern
, extents
))
6638 return CAIRO_STATUS_SUCCESS
;
6640 return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY
;
6643 return CAIRO_INT_STATUS_UNSUPPORTED
;
6647 _cairo_pdf_surface_operation_supported (cairo_pdf_surface_t
*surface
,
6648 cairo_operator_t op
,
6649 const cairo_pattern_t
*pattern
,
6650 const cairo_rectangle_int_t
*extents
)
6652 return _cairo_pdf_surface_analyze_operation (surface
, op
, pattern
, extents
) != CAIRO_INT_STATUS_UNSUPPORTED
;
6655 static cairo_int_status_t
6656 _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t
*surface
)
6658 cairo_box_double_t bbox
;
6659 cairo_int_status_t status
;
6661 status
= _cairo_pdf_surface_close_content_stream (surface
);
6662 if (unlikely (status
))
6665 status
= _cairo_array_append (&surface
->knockout_group
, &surface
->content
);
6666 if (unlikely (status
))
6669 _cairo_pdf_group_resources_clear (&surface
->resources
);
6672 bbox
.p2
.x
= surface
->width
;
6673 bbox
.p2
.y
= surface
->height
;
6674 return _cairo_pdf_surface_open_content_stream (surface
, &bbox
, NULL
, TRUE
, TRUE
);
6677 /* If source is an opaque image and mask is an image and both images
6678 * have the same bounding box we can emit them as a image/smask pair.
6680 static cairo_int_status_t
6681 _cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t
*surface
,
6682 cairo_operator_t op
,
6683 const cairo_pattern_t
*source
,
6684 const cairo_pattern_t
*mask
,
6685 const cairo_rectangle_int_t
*extents
)
6687 cairo_int_status_t status
;
6688 cairo_image_surface_t
*image
;
6690 cairo_image_transparency_t transparency
;
6691 cairo_pdf_resource_t smask_res
;
6692 int src_width
, src_height
;
6693 int mask_width
, mask_height
;
6694 double src_x_offset
, src_y_offset
;
6695 double mask_x_offset
, mask_y_offset
;
6696 double src_x1
, src_y1
, src_x2
, src_y2
;
6697 double mask_x1
, mask_y1
, mask_x2
, mask_y2
;
6699 double src_radius
, mask_radius
, e
;
6700 cairo_rectangle_int_t extents2
;
6701 cairo_bool_t need_smask
;
6703 /* Check that source and mask are images */
6705 if (!((source
->type
== CAIRO_PATTERN_TYPE_SURFACE
|| source
->type
== CAIRO_PATTERN_TYPE_RASTER_SOURCE
) &&
6706 (mask
->type
== CAIRO_PATTERN_TYPE_SURFACE
|| mask
->type
== CAIRO_PATTERN_TYPE_RASTER_SOURCE
)))
6707 return CAIRO_INT_STATUS_UNSUPPORTED
;
6709 if (source
->type
== CAIRO_PATTERN_TYPE_SURFACE
&&
6710 ((cairo_surface_pattern_t
*) source
)->surface
->type
== CAIRO_SURFACE_TYPE_RECORDING
)
6712 return CAIRO_INT_STATUS_UNSUPPORTED
;
6715 if (mask
->type
== CAIRO_PATTERN_TYPE_SURFACE
&&
6716 ((cairo_surface_pattern_t
*) mask
)->surface
->type
== CAIRO_SURFACE_TYPE_RECORDING
)
6718 return CAIRO_INT_STATUS_UNSUPPORTED
;
6721 if (source
->extend
!= CAIRO_EXTEND_NONE
|| mask
->extend
!= CAIRO_EXTEND_NONE
)
6722 return CAIRO_INT_STATUS_UNSUPPORTED
;
6724 /* Check that source is opaque and get image sizes */
6726 status
= _cairo_pdf_surface_acquire_source_image_from_pattern (surface
, source
,
6727 &image
, &image_extra
);
6728 if (unlikely (status
))
6731 if (image
->base
.status
)
6732 return image
->base
.status
;
6734 src_width
= image
->width
;
6735 src_height
= image
->height
;
6736 if (source
->type
== CAIRO_PATTERN_TYPE_RASTER_SOURCE
) {
6737 cairo_surface_get_device_offset (&image
->base
, &src_x_offset
, &src_y_offset
);
6743 transparency
= _cairo_image_analyze_transparency (image
);
6744 _cairo_pdf_surface_release_source_image_from_pattern (surface
, source
, image
, image_extra
);
6746 if (transparency
!= CAIRO_IMAGE_IS_OPAQUE
)
6747 return CAIRO_INT_STATUS_UNSUPPORTED
;
6749 status
= _cairo_pdf_surface_acquire_source_image_from_pattern (surface
, mask
,
6750 &image
, &image_extra
);
6751 if (unlikely (status
))
6754 if (image
->base
.status
)
6755 return image
->base
.status
;
6757 mask_width
= image
->width
;
6758 mask_height
= image
->height
;
6759 if (mask
->type
== CAIRO_PATTERN_TYPE_RASTER_SOURCE
) {
6760 cairo_surface_get_device_offset (&image
->base
, &mask_x_offset
, &mask_y_offset
);
6766 transparency
= _cairo_image_analyze_transparency (image
);
6767 need_smask
= transparency
!= CAIRO_IMAGE_IS_OPAQUE
;
6769 _cairo_pdf_surface_release_source_image_from_pattern (surface
, mask
, image
, image_extra
);
6771 /* Check that both images have the same extents with a tolerance
6772 * of half the smallest source pixel. */
6774 p2u
= source
->matrix
;
6775 status
= cairo_matrix_invert (&p2u
);
6776 /* cairo_pattern_set_matrix ensures the matrix is invertible */
6777 assert (status
== CAIRO_INT_STATUS_SUCCESS
);
6781 src_y2
= src_height
;
6782 cairo_matrix_transform_point (&p2u
, &src_x1
, &src_y1
);
6783 cairo_matrix_transform_point (&p2u
, &src_x2
, &src_y2
);
6784 src_radius
= _cairo_matrix_transformed_circle_major_axis (&p2u
, 0.5);
6787 status
= cairo_matrix_invert (&p2u
);
6788 /* cairo_pattern_set_matrix ensures the matrix is invertible */
6789 assert (status
== CAIRO_INT_STATUS_SUCCESS
);
6792 mask_x2
= mask_width
;
6793 mask_y2
= mask_height
;
6794 cairo_matrix_transform_point (&p2u
, &mask_x1
, &mask_y1
);
6795 cairo_matrix_transform_point (&p2u
, &mask_x2
, &mask_y2
);
6796 mask_radius
= _cairo_matrix_transformed_circle_major_axis (&p2u
, 0.5);
6798 if (src_radius
< mask_radius
)
6803 if (fabs(src_x1
- mask_x1
) > e
||
6804 fabs(src_x2
- mask_x2
) > e
||
6805 fabs(src_y1
- mask_y1
) > e
||
6806 fabs(src_y2
- mask_y2
) > e
)
6807 return CAIRO_INT_STATUS_UNSUPPORTED
;
6809 /* Check both images have same device offset */
6810 if (fabs(src_x_offset
- mask_x_offset
) > e
||
6811 fabs(src_y_offset
- mask_y_offset
) > e
)
6812 return CAIRO_INT_STATUS_UNSUPPORTED
;
6815 status
= _cairo_pdf_surface_add_source_surface (surface
,
6830 if (unlikely (status
))
6834 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
6835 if (unlikely (status
))
6838 _cairo_output_stream_printf (surface
->output
, "q\n");
6839 status
= _cairo_pdf_surface_paint_surface_pattern (surface
, op
, source
, extents
,
6840 need_smask
? &smask_res
: NULL
,
6842 if (unlikely (status
))
6845 _cairo_output_stream_printf (surface
->output
, "Q\n");
6847 status
= _cairo_output_stream_get_status (surface
->output
);
6853 /* A PDF stencil mask is an A1 mask used with the current color */
6854 static cairo_int_status_t
6855 _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t
*surface
,
6856 cairo_operator_t op
,
6857 const cairo_pattern_t
*source
,
6858 const cairo_pattern_t
*mask
,
6859 const cairo_rectangle_int_t
*extents
)
6861 cairo_int_status_t status
;
6862 cairo_image_surface_t
*image
;
6864 cairo_image_transparency_t transparency
;
6865 cairo_pdf_resource_t pattern_res
= {0};
6867 if (! (source
->type
== CAIRO_PATTERN_TYPE_SOLID
&&
6868 (mask
->type
== CAIRO_PATTERN_TYPE_SURFACE
|| mask
->type
== CAIRO_PATTERN_TYPE_RASTER_SOURCE
)))
6869 return CAIRO_INT_STATUS_UNSUPPORTED
;
6871 if (mask
->type
== CAIRO_PATTERN_TYPE_SURFACE
&&
6872 ((cairo_surface_pattern_t
*) mask
)->surface
->type
== CAIRO_SURFACE_TYPE_RECORDING
)
6874 return CAIRO_INT_STATUS_UNSUPPORTED
;
6877 status
= _cairo_pdf_surface_acquire_source_image_from_pattern (surface
, mask
,
6878 &image
, &image_extra
);
6879 if (unlikely (status
))
6882 if (image
->base
.status
)
6883 return image
->base
.status
;
6885 transparency
= _cairo_image_analyze_transparency (image
);
6886 if (transparency
!= CAIRO_IMAGE_IS_OPAQUE
&&
6887 transparency
!= CAIRO_IMAGE_HAS_BILEVEL_ALPHA
)
6889 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
6893 status
= _cairo_pdf_surface_select_pattern (surface
, source
,
6894 pattern_res
, FALSE
);
6895 if (unlikely (status
))
6898 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
6899 if (unlikely (status
))
6902 _cairo_output_stream_printf (surface
->output
, "q\n");
6903 status
= _cairo_pdf_surface_paint_surface_pattern (surface
, op
, mask
, extents
, NULL
, TRUE
);
6904 if (unlikely (status
))
6907 _cairo_output_stream_printf (surface
->output
, "Q\n");
6909 status
= _cairo_output_stream_get_status (surface
->output
);
6912 _cairo_pdf_surface_release_source_image_from_pattern (surface
, mask
, image
, image_extra
);
6917 static cairo_int_status_t
6918 _cairo_pdf_surface_set_clip (cairo_pdf_surface_t
*surface
,
6919 cairo_composite_rectangles_t
*composite
)
6921 cairo_clip_t
*clip
= composite
->clip
;
6923 if (_cairo_composite_rectangles_can_reduce_clip (composite
, clip
))
6927 if (_cairo_composite_rectangles_can_reduce_clip (composite
,
6928 surface
->clipper
.clip
))
6929 return CAIRO_STATUS_SUCCESS
;
6932 return _cairo_surface_clipper_set_clip (&surface
->clipper
, clip
);
6935 static cairo_int_status_t
6936 _cairo_pdf_surface_paint (void *abstract_surface
,
6937 cairo_operator_t op
,
6938 const cairo_pattern_t
*source
,
6939 const cairo_clip_t
*clip
)
6941 cairo_pdf_surface_t
*surface
= abstract_surface
;
6942 cairo_pdf_smask_group_t
*group
;
6943 cairo_pdf_resource_t pattern_res
, gstate_res
;
6944 cairo_composite_rectangles_t extents
;
6945 cairo_int_status_t status
;
6947 status
= _cairo_composite_rectangles_init_for_paint (&extents
,
6950 if (unlikely (status
))
6953 if (surface
->paginated_mode
== CAIRO_PAGINATED_MODE_ANALYZE
) {
6954 status
= _cairo_pdf_surface_analyze_operation (surface
, op
, source
, &extents
.bounded
);
6956 } else if (surface
->paginated_mode
== CAIRO_PAGINATED_MODE_FALLBACK
) {
6957 status
= _cairo_pdf_surface_start_fallback (surface
);
6958 if (unlikely (status
))
6962 assert (_cairo_pdf_surface_operation_supported (surface
, op
, source
, &extents
.bounded
));
6964 status
= _cairo_pdf_surface_set_clip (surface
, &extents
);
6965 if (unlikely (status
))
6968 status
= _cairo_pdf_surface_select_operator (surface
, op
);
6969 if (unlikely (status
))
6972 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
6973 if (unlikely (status
))
6976 if (_can_paint_pattern (source
)) {
6977 _cairo_output_stream_printf (surface
->output
, "q\n");
6978 status
= _cairo_pdf_surface_paint_pattern (surface
,
6983 if (unlikely (status
))
6986 _cairo_output_stream_printf (surface
->output
, "Q\n");
6987 _cairo_composite_rectangles_fini (&extents
);
6988 return _cairo_output_stream_get_status (surface
->output
);
6993 status
= _cairo_pdf_surface_add_pdf_pattern (surface
, source
, op
,
6995 &pattern_res
, &gstate_res
);
6996 if (unlikely (status
))
6999 if (gstate_res
.id
!= 0) {
7000 group
= _cairo_pdf_surface_create_smask_group (surface
, &extents
.bounded
);
7001 if (unlikely (group
== NULL
)) {
7002 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
7006 group
->operation
= PDF_PAINT
;
7007 status
= _cairo_pattern_create_copy (&group
->source
, source
);
7008 if (unlikely (status
)) {
7009 _cairo_pdf_smask_group_destroy (group
);
7012 group
->source_res
= pattern_res
;
7013 status
= _cairo_pdf_surface_add_smask_group (surface
, group
);
7014 if (unlikely (status
)) {
7015 _cairo_pdf_smask_group_destroy (group
);
7019 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
7020 if (unlikely (status
))
7023 status
= _cairo_pdf_surface_add_xobject (surface
, group
->group_res
);
7024 if (unlikely (status
))
7027 _cairo_output_stream_printf (surface
->output
,
7028 "q /s%d gs /x%d Do Q\n",
7030 group
->group_res
.id
);
7032 status
= _cairo_pdf_surface_select_pattern (surface
, source
,
7033 pattern_res
, FALSE
);
7034 if (unlikely (status
))
7037 _cairo_output_stream_printf (surface
->output
,
7039 surface
->width
, surface
->height
);
7041 status
= _cairo_pdf_surface_unselect_pattern (surface
);
7042 if (unlikely (status
))
7046 _cairo_composite_rectangles_fini (&extents
);
7047 return _cairo_output_stream_get_status (surface
->output
);
7050 _cairo_composite_rectangles_fini (&extents
);
7054 static cairo_int_status_t
7055 _cairo_pdf_surface_mask (void *abstract_surface
,
7056 cairo_operator_t op
,
7057 const cairo_pattern_t
*source
,
7058 const cairo_pattern_t
*mask
,
7059 const cairo_clip_t
*clip
)
7061 cairo_pdf_surface_t
*surface
= abstract_surface
;
7062 cairo_pdf_smask_group_t
*group
;
7063 cairo_composite_rectangles_t extents
;
7064 cairo_int_status_t status
;
7065 cairo_rectangle_int_t r
;
7068 status
= _cairo_composite_rectangles_init_for_mask (&extents
,
7070 op
, source
, mask
, clip
);
7071 if (unlikely (status
))
7074 if (surface
->paginated_mode
== CAIRO_PAGINATED_MODE_ANALYZE
) {
7075 cairo_int_status_t source_status
, mask_status
;
7077 status
= _cairo_pdf_surface_analyze_operation (surface
, op
, source
, &extents
.bounded
);
7078 if (_cairo_int_status_is_error (status
))
7080 source_status
= status
;
7082 if (mask
->has_component_alpha
) {
7083 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
7085 status
= _cairo_pdf_surface_analyze_operation (surface
, op
, mask
, &extents
.bounded
);
7086 if (_cairo_int_status_is_error (status
))
7089 mask_status
= status
;
7091 _cairo_composite_rectangles_fini (&extents
);
7092 return _cairo_analysis_surface_merge_status (source_status
,
7094 } else if (surface
->paginated_mode
== CAIRO_PAGINATED_MODE_FALLBACK
) {
7095 status
= _cairo_pdf_surface_start_fallback (surface
);
7096 if (unlikely (status
))
7100 assert (_cairo_pdf_surface_operation_supported (surface
, op
, source
, &extents
.bounded
));
7101 assert (_cairo_pdf_surface_operation_supported (surface
, op
, mask
, &extents
.bounded
));
7103 /* get the accurate extents */
7104 status
= _cairo_pattern_get_ink_extents (source
, &r
);
7105 if (unlikely (status
))
7108 /* XXX slight impedance mismatch */
7109 _cairo_box_from_rectangle (&box
, &r
);
7110 status
= _cairo_composite_rectangles_intersect_source_extents (&extents
,
7112 if (unlikely (status
))
7115 status
= _cairo_pattern_get_ink_extents (mask
, &r
);
7116 if (unlikely (status
))
7119 _cairo_box_from_rectangle (&box
, &r
);
7120 status
= _cairo_composite_rectangles_intersect_mask_extents (&extents
,
7122 if (unlikely (status
))
7125 status
= _cairo_pdf_surface_set_clip (surface
, &extents
);
7126 if (unlikely (status
))
7129 status
= _cairo_pdf_surface_select_operator (surface
, op
);
7130 if (unlikely (status
))
7133 /* Check if we can combine source and mask into a smask image */
7134 status
= _cairo_pdf_surface_emit_combined_smask (surface
, op
, source
, mask
, &extents
.bounded
);
7135 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
7138 /* Check if we can use a stencil mask */
7139 status
= _cairo_pdf_surface_emit_stencil_mask (surface
, op
, source
, mask
, &extents
.bounded
);
7140 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
7143 group
= _cairo_pdf_surface_create_smask_group (surface
, &extents
.bounded
);
7144 if (unlikely (group
== NULL
)) {
7145 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
7149 group
->operation
= PDF_MASK
;
7150 status
= _cairo_pattern_create_copy (&group
->source
, source
);
7151 if (unlikely (status
)) {
7152 _cairo_pdf_smask_group_destroy (group
);
7155 status
= _cairo_pattern_create_copy (&group
->mask
, mask
);
7156 if (unlikely (status
)) {
7157 _cairo_pdf_smask_group_destroy (group
);
7160 group
->source_res
= _cairo_pdf_surface_new_object (surface
);
7161 if (group
->source_res
.id
== 0) {
7162 _cairo_pdf_smask_group_destroy (group
);
7163 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
7167 status
= _cairo_pdf_surface_add_smask_group (surface
, group
);
7168 if (unlikely (status
)) {
7169 _cairo_pdf_smask_group_destroy (group
);
7173 status
= _cairo_pdf_surface_add_smask (surface
, group
->group_res
);
7174 if (unlikely (status
))
7177 status
= _cairo_pdf_surface_add_xobject (surface
, group
->source_res
);
7178 if (unlikely (status
))
7181 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
7182 if (unlikely (status
))
7185 _cairo_output_stream_printf (surface
->output
,
7186 "q /s%d gs /x%d Do Q\n",
7187 group
->group_res
.id
,
7188 group
->source_res
.id
);
7190 _cairo_composite_rectangles_fini (&extents
);
7191 return _cairo_output_stream_get_status (surface
->output
);
7194 _cairo_composite_rectangles_fini (&extents
);
7198 static cairo_int_status_t
7199 _cairo_pdf_surface_stroke (void *abstract_surface
,
7200 cairo_operator_t op
,
7201 const cairo_pattern_t
*source
,
7202 const cairo_path_fixed_t
*path
,
7203 const cairo_stroke_style_t
*style
,
7204 const cairo_matrix_t
*ctm
,
7205 const cairo_matrix_t
*ctm_inverse
,
7207 cairo_antialias_t antialias
,
7208 const cairo_clip_t
*clip
)
7210 cairo_pdf_surface_t
*surface
= abstract_surface
;
7211 cairo_pdf_smask_group_t
*group
;
7212 cairo_pdf_resource_t pattern_res
, gstate_res
;
7213 cairo_composite_rectangles_t extents
;
7214 cairo_int_status_t status
;
7216 status
= _cairo_composite_rectangles_init_for_stroke (&extents
,
7221 if (unlikely (status
))
7224 /* use the more accurate extents */
7225 if (extents
.is_bounded
) {
7226 cairo_rectangle_int_t mask
;
7229 status
= _cairo_path_fixed_stroke_extents (path
, style
,
7233 if (unlikely (status
))
7236 _cairo_box_from_rectangle (&box
, &mask
);
7237 status
= _cairo_composite_rectangles_intersect_mask_extents (&extents
,
7239 if (unlikely (status
))
7243 if (surface
->paginated_mode
== CAIRO_PAGINATED_MODE_ANALYZE
) {
7244 status
= _cairo_pdf_surface_analyze_operation (surface
, op
, source
, &extents
.bounded
);
7248 assert (_cairo_pdf_surface_operation_supported (surface
, op
, source
, &extents
.bounded
));
7250 status
= _cairo_pdf_surface_set_clip (surface
, &extents
);
7251 if (unlikely (status
))
7256 status
= _cairo_pdf_surface_add_pdf_pattern (surface
, source
, op
,
7258 &pattern_res
, &gstate_res
);
7259 if (unlikely (status
))
7262 status
= _cairo_pdf_surface_select_operator (surface
, op
);
7263 if (unlikely (status
))
7266 if (gstate_res
.id
!= 0) {
7267 group
= _cairo_pdf_surface_create_smask_group (surface
, &extents
.bounded
);
7268 if (unlikely (group
== NULL
)) {
7269 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
7273 group
->operation
= PDF_STROKE
;
7274 status
= _cairo_pattern_create_copy (&group
->source
, source
);
7275 if (unlikely (status
)) {
7276 _cairo_pdf_smask_group_destroy (group
);
7279 group
->source_res
= pattern_res
;
7280 status
= _cairo_path_fixed_init_copy (&group
->path
, path
);
7281 if (unlikely (status
)) {
7282 _cairo_pdf_smask_group_destroy (group
);
7286 group
->style
= *style
;
7288 group
->ctm_inverse
= *ctm_inverse
;
7289 status
= _cairo_pdf_surface_add_smask_group (surface
, group
);
7290 if (unlikely (status
)) {
7291 _cairo_pdf_smask_group_destroy (group
);
7295 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
7296 if (unlikely (status
))
7299 status
= _cairo_pdf_surface_add_xobject (surface
, group
->group_res
);
7300 if (unlikely (status
))
7303 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
7304 if (unlikely (status
))
7307 _cairo_output_stream_printf (surface
->output
,
7308 "q /s%d gs /x%d Do Q\n",
7310 group
->group_res
.id
);
7312 status
= _cairo_pdf_surface_select_pattern (surface
, source
, pattern_res
, TRUE
);
7313 if (unlikely (status
))
7316 status
= _cairo_pdf_operators_stroke (&surface
->pdf_operators
,
7321 if (unlikely (status
))
7324 status
= _cairo_pdf_surface_unselect_pattern (surface
);
7325 if (unlikely (status
))
7329 _cairo_composite_rectangles_fini (&extents
);
7330 return _cairo_output_stream_get_status (surface
->output
);
7333 _cairo_composite_rectangles_fini (&extents
);
7337 static cairo_int_status_t
7338 _cairo_pdf_surface_fill (void *abstract_surface
,
7339 cairo_operator_t op
,
7340 const cairo_pattern_t
*source
,
7341 const cairo_path_fixed_t
*path
,
7342 cairo_fill_rule_t fill_rule
,
7344 cairo_antialias_t antialias
,
7345 const cairo_clip_t
*clip
)
7347 cairo_pdf_surface_t
*surface
= abstract_surface
;
7348 cairo_int_status_t status
;
7349 cairo_pdf_smask_group_t
*group
;
7350 cairo_pdf_resource_t pattern_res
, gstate_res
;
7351 cairo_composite_rectangles_t extents
;
7353 status
= _cairo_composite_rectangles_init_for_fill (&extents
,
7357 if (unlikely (status
))
7360 /* use the more accurate extents */
7361 if (extents
.is_bounded
) {
7362 cairo_rectangle_int_t mask
;
7365 _cairo_path_fixed_fill_extents (path
,
7370 _cairo_box_from_rectangle (&box
, &mask
);
7371 status
= _cairo_composite_rectangles_intersect_mask_extents (&extents
,
7373 if (unlikely (status
))
7377 if (surface
->paginated_mode
== CAIRO_PAGINATED_MODE_ANALYZE
) {
7378 status
= _cairo_pdf_surface_analyze_operation (surface
, op
, source
, &extents
.bounded
);
7380 } else if (surface
->paginated_mode
== CAIRO_PAGINATED_MODE_FALLBACK
) {
7381 status
= _cairo_pdf_surface_start_fallback (surface
);
7382 if (unlikely (status
))
7386 assert (_cairo_pdf_surface_operation_supported (surface
, op
, source
, &extents
.bounded
));
7388 status
= _cairo_pdf_surface_set_clip (surface
, &extents
);
7389 if (unlikely (status
))
7392 status
= _cairo_pdf_surface_select_operator (surface
, op
);
7393 if (unlikely (status
))
7396 if (_can_paint_pattern (source
)) {
7397 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
7398 if (unlikely (status
))
7401 _cairo_output_stream_printf (surface
->output
, "q\n");
7402 status
= _cairo_pdf_operators_clip (&surface
->pdf_operators
,
7405 if (unlikely (status
))
7408 status
= _cairo_pdf_surface_paint_pattern (surface
,
7413 if (unlikely (status
))
7416 _cairo_output_stream_printf (surface
->output
, "Q\n");
7417 status
= _cairo_output_stream_get_status (surface
->output
);
7423 status
= _cairo_pdf_surface_add_pdf_pattern (surface
, source
, op
,
7425 &pattern_res
, &gstate_res
);
7426 if (unlikely (status
))
7429 if (gstate_res
.id
!= 0) {
7430 group
= _cairo_pdf_surface_create_smask_group (surface
, &extents
.bounded
);
7431 if (unlikely (group
== NULL
)) {
7432 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
7436 group
->operation
= PDF_FILL
;
7437 status
= _cairo_pattern_create_copy (&group
->source
, source
);
7438 if (unlikely (status
)) {
7439 _cairo_pdf_smask_group_destroy (group
);
7442 group
->source_res
= pattern_res
;
7443 status
= _cairo_path_fixed_init_copy (&group
->path
, path
);
7444 if (unlikely (status
)) {
7445 _cairo_pdf_smask_group_destroy (group
);
7449 group
->fill_rule
= fill_rule
;
7450 status
= _cairo_pdf_surface_add_smask_group (surface
, group
);
7451 if (unlikely (status
)) {
7452 _cairo_pdf_smask_group_destroy (group
);
7456 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
7457 if (unlikely (status
))
7460 status
= _cairo_pdf_surface_add_xobject (surface
, group
->group_res
);
7461 if (unlikely (status
))
7464 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
7465 if (unlikely (status
))
7468 _cairo_output_stream_printf (surface
->output
,
7469 "q /s%d gs /x%d Do Q\n",
7471 group
->group_res
.id
);
7473 status
= _cairo_pdf_surface_select_pattern (surface
, source
, pattern_res
, FALSE
);
7474 if (unlikely (status
))
7477 status
= _cairo_pdf_operators_fill (&surface
->pdf_operators
,
7480 if (unlikely (status
))
7483 status
= _cairo_pdf_surface_unselect_pattern (surface
);
7484 if (unlikely (status
))
7488 _cairo_composite_rectangles_fini (&extents
);
7489 return _cairo_output_stream_get_status (surface
->output
);
7492 _cairo_composite_rectangles_fini (&extents
);
7496 static cairo_int_status_t
7497 _cairo_pdf_surface_fill_stroke (void *abstract_surface
,
7498 cairo_operator_t fill_op
,
7499 const cairo_pattern_t
*fill_source
,
7500 cairo_fill_rule_t fill_rule
,
7501 double fill_tolerance
,
7502 cairo_antialias_t fill_antialias
,
7503 const cairo_path_fixed_t
*path
,
7504 cairo_operator_t stroke_op
,
7505 const cairo_pattern_t
*stroke_source
,
7506 const cairo_stroke_style_t
*stroke_style
,
7507 const cairo_matrix_t
*stroke_ctm
,
7508 const cairo_matrix_t
*stroke_ctm_inverse
,
7509 double stroke_tolerance
,
7510 cairo_antialias_t stroke_antialias
,
7511 const cairo_clip_t
*clip
)
7513 cairo_pdf_surface_t
*surface
= abstract_surface
;
7514 cairo_int_status_t status
;
7515 cairo_pdf_resource_t fill_pattern_res
, stroke_pattern_res
, gstate_res
;
7516 cairo_composite_rectangles_t extents
;
7518 /* During analysis we return unsupported and let the _fill and
7519 * _stroke functions that are on the fallback path do the analysis
7520 * for us. During render we may still encounter unsupported
7521 * combinations of fill/stroke patterns. However we can return
7522 * unsupported anytime to let the _fill and _stroke functions take
7525 if (surface
->paginated_mode
== CAIRO_PAGINATED_MODE_ANALYZE
)
7526 return CAIRO_INT_STATUS_UNSUPPORTED
;
7528 /* PDF rendering of fill-stroke is not the same as cairo when
7529 * either the fill or stroke is not opaque.
7531 if ( !_cairo_pattern_is_opaque (fill_source
, NULL
) ||
7532 !_cairo_pattern_is_opaque (stroke_source
, NULL
))
7534 return CAIRO_INT_STATUS_UNSUPPORTED
;
7537 if (fill_op
!= stroke_op
)
7538 return CAIRO_INT_STATUS_UNSUPPORTED
;
7540 /* Compute the operation extents using the stroke which will naturally
7541 * be larger than the fill extents.
7543 status
= _cairo_composite_rectangles_init_for_stroke (&extents
,
7545 stroke_op
, stroke_source
,
7546 path
, stroke_style
, stroke_ctm
,
7548 if (unlikely (status
))
7551 /* use the more accurate extents */
7552 if (extents
.is_bounded
) {
7553 cairo_rectangle_int_t mask
;
7556 status
= _cairo_path_fixed_stroke_extents (path
, stroke_style
,
7557 stroke_ctm
, stroke_ctm_inverse
,
7560 if (unlikely (status
))
7563 _cairo_box_from_rectangle (&box
, &mask
);
7564 status
= _cairo_composite_rectangles_intersect_mask_extents (&extents
,
7566 if (unlikely (status
))
7570 status
= _cairo_pdf_surface_set_clip (surface
, &extents
);
7571 if (unlikely (status
))
7574 status
= _cairo_pdf_surface_select_operator (surface
, fill_op
);
7575 if (unlikely (status
))
7578 /* use the more accurate extents */
7579 if (extents
.is_bounded
) {
7580 cairo_rectangle_int_t mask
;
7583 _cairo_path_fixed_fill_extents (path
,
7588 _cairo_box_from_rectangle (&box
, &mask
);
7589 status
= _cairo_composite_rectangles_intersect_mask_extents (&extents
,
7591 if (unlikely (status
))
7595 fill_pattern_res
.id
= 0;
7597 status
= _cairo_pdf_surface_add_pdf_pattern (surface
, fill_source
,
7602 if (unlikely (status
))
7605 assert (gstate_res
.id
== 0);
7607 stroke_pattern_res
.id
= 0;
7609 status
= _cairo_pdf_surface_add_pdf_pattern (surface
,
7613 &stroke_pattern_res
,
7615 if (unlikely (status
))
7618 assert (gstate_res
.id
== 0);
7620 /* As PDF has separate graphics state for fill and stroke we can
7621 * select both at the same time */
7622 status
= _cairo_pdf_surface_select_pattern (surface
, fill_source
,
7623 fill_pattern_res
, FALSE
);
7624 if (unlikely (status
))
7627 status
= _cairo_pdf_surface_select_pattern (surface
, stroke_source
,
7628 stroke_pattern_res
, TRUE
);
7629 if (unlikely (status
))
7632 status
= _cairo_pdf_operators_fill_stroke (&surface
->pdf_operators
,
7637 stroke_ctm_inverse
);
7638 if (unlikely (status
))
7641 status
= _cairo_pdf_surface_unselect_pattern (surface
);
7642 if (unlikely (status
))
7645 _cairo_composite_rectangles_fini (&extents
);
7646 return _cairo_output_stream_get_status (surface
->output
);
7649 _cairo_composite_rectangles_fini (&extents
);
7654 _cairo_pdf_surface_has_show_text_glyphs (void *abstract_surface
)
7659 static cairo_int_status_t
7660 _cairo_pdf_surface_show_text_glyphs (void *abstract_surface
,
7661 cairo_operator_t op
,
7662 const cairo_pattern_t
*source
,
7665 cairo_glyph_t
*glyphs
,
7667 const cairo_text_cluster_t
*clusters
,
7669 cairo_text_cluster_flags_t cluster_flags
,
7670 cairo_scaled_font_t
*scaled_font
,
7671 const cairo_clip_t
*clip
)
7673 cairo_pdf_surface_t
*surface
= abstract_surface
;
7674 cairo_pdf_smask_group_t
*group
;
7675 cairo_pdf_resource_t pattern_res
, gstate_res
;
7676 cairo_composite_rectangles_t extents
;
7677 cairo_bool_t overlap
;
7678 cairo_int_status_t status
;
7680 status
= _cairo_composite_rectangles_init_for_glyphs (&extents
,
7687 if (unlikely (status
))
7690 if (surface
->paginated_mode
== CAIRO_PAGINATED_MODE_ANALYZE
) {
7691 status
= _cairo_pdf_surface_analyze_operation (surface
, op
, source
, &extents
.bounded
);
7695 assert (_cairo_pdf_surface_operation_supported (surface
, op
, source
, &extents
.bounded
));
7697 status
= _cairo_pdf_surface_set_clip (surface
, &extents
);
7698 if (unlikely (status
))
7703 status
= _cairo_pdf_surface_add_pdf_pattern (surface
, source
, op
,
7705 &pattern_res
, &gstate_res
);
7706 if (unlikely (status
))
7709 status
= _cairo_pdf_surface_select_operator (surface
, op
);
7710 if (unlikely (status
))
7713 if (gstate_res
.id
!= 0) {
7714 group
= _cairo_pdf_surface_create_smask_group (surface
, &extents
.bounded
);
7715 if (unlikely (group
== NULL
)) {
7716 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
7720 group
->operation
= PDF_SHOW_GLYPHS
;
7721 status
= _cairo_pattern_create_copy (&group
->source
, source
);
7722 if (unlikely (status
)) {
7723 _cairo_pdf_smask_group_destroy (group
);
7726 group
->source_res
= pattern_res
;
7729 group
->utf8
= malloc (utf8_len
);
7730 if (unlikely (group
->utf8
== NULL
)) {
7731 _cairo_pdf_smask_group_destroy (group
);
7732 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
7735 memcpy (group
->utf8
, utf8
, utf8_len
);
7737 group
->utf8_len
= utf8_len
;
7740 group
->glyphs
= _cairo_malloc_ab (num_glyphs
, sizeof (cairo_glyph_t
));
7741 if (unlikely (group
->glyphs
== NULL
)) {
7742 _cairo_pdf_smask_group_destroy (group
);
7743 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
7746 memcpy (group
->glyphs
, glyphs
, sizeof (cairo_glyph_t
) * num_glyphs
);
7748 group
->num_glyphs
= num_glyphs
;
7751 group
->clusters
= _cairo_malloc_ab (num_clusters
, sizeof (cairo_text_cluster_t
));
7752 if (unlikely (group
->clusters
== NULL
)) {
7753 _cairo_pdf_smask_group_destroy (group
);
7754 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
7757 memcpy (group
->clusters
, clusters
, sizeof (cairo_text_cluster_t
) * num_clusters
);
7759 group
->num_clusters
= num_clusters
;
7761 group
->scaled_font
= cairo_scaled_font_reference (scaled_font
);
7762 status
= _cairo_pdf_surface_add_smask_group (surface
, group
);
7763 if (unlikely (status
)) {
7764 _cairo_pdf_smask_group_destroy (group
);
7768 status
= _cairo_pdf_surface_add_smask (surface
, gstate_res
);
7769 if (unlikely (status
))
7772 status
= _cairo_pdf_surface_add_xobject (surface
, group
->group_res
);
7773 if (unlikely (status
))
7776 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
7777 if (unlikely (status
))
7780 _cairo_output_stream_printf (surface
->output
,
7781 "q /s%d gs /x%d Do Q\n",
7783 group
->group_res
.id
);
7785 status
= _cairo_pdf_surface_select_pattern (surface
, source
, pattern_res
, FALSE
);
7786 if (unlikely (status
))
7789 /* Each call to show_glyphs() with a transclucent pattern must
7790 * be in a separate text object otherwise overlapping text
7791 * from separate calls to show_glyphs will not composite with
7793 if (! _cairo_pattern_is_opaque (source
, &extents
.bounded
)) {
7794 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
7795 if (unlikely (status
))
7799 status
= _cairo_pdf_operators_show_text_glyphs (&surface
->pdf_operators
,
7802 clusters
, num_clusters
,
7805 if (unlikely (status
))
7808 status
= _cairo_pdf_surface_unselect_pattern (surface
);
7809 if (unlikely (status
))
7813 _cairo_composite_rectangles_fini (&extents
);
7814 return _cairo_output_stream_get_status (surface
->output
);
7817 _cairo_composite_rectangles_fini (&extents
);
7821 static const char **
7822 _cairo_pdf_surface_get_supported_mime_types (void *abstract_surface
)
7824 return _cairo_pdf_supported_mime_types
;
7828 _cairo_pdf_surface_set_paginated_mode (void *abstract_surface
,
7829 cairo_paginated_mode_t paginated_mode
)
7831 cairo_pdf_surface_t
*surface
= abstract_surface
;
7833 surface
->paginated_mode
= paginated_mode
;
7836 static const cairo_surface_backend_t cairo_pdf_surface_backend
= {
7837 CAIRO_SURFACE_TYPE_PDF
,
7838 _cairo_pdf_surface_finish
,
7840 _cairo_default_context_create
,
7842 NULL
, /* create similar: handled by wrapper */
7843 NULL
, /* create similar image */
7844 NULL
, /* map to image */
7845 NULL
, /* unmap image */
7847 _cairo_surface_default_source
,
7848 NULL
, /* acquire_source_image */
7849 NULL
, /* release_source_image */
7850 NULL
, /* snapshot */
7852 NULL
, /* _cairo_pdf_surface_copy_page */
7853 _cairo_pdf_surface_show_page
,
7855 _cairo_pdf_surface_get_extents
,
7856 _cairo_pdf_surface_get_font_options
,
7859 NULL
, /* mark_dirty_rectangle */
7861 /* Here are the drawing functions */
7862 _cairo_pdf_surface_paint
,
7863 _cairo_pdf_surface_mask
,
7864 _cairo_pdf_surface_stroke
,
7865 _cairo_pdf_surface_fill
,
7866 _cairo_pdf_surface_fill_stroke
,
7867 NULL
, /* show_glyphs */
7868 _cairo_pdf_surface_has_show_text_glyphs
,
7869 _cairo_pdf_surface_show_text_glyphs
,
7870 _cairo_pdf_surface_get_supported_mime_types
,
7873 static const cairo_paginated_surface_backend_t
7874 cairo_pdf_surface_paginated_backend
= {
7875 _cairo_pdf_surface_start_page
,
7876 _cairo_pdf_surface_set_paginated_mode
,
7877 NULL
, /* set_bounding_box */
7878 _cairo_pdf_surface_has_fallback_images
,
7879 _cairo_pdf_surface_supports_fine_grained_fallbacks
,