cairo-pdf-surface.c 259 KB
Newer Older
1
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
Kristian Høgsberg's avatar
Kristian Høgsberg committed
2 3 4
/* cairo - a vector graphics library with display and print output
 *
 * Copyright © 2004 Red Hat, Inc
5
 * Copyright © 2006 Red Hat, Inc
6
 * Copyright © 2007, 2008 Adrian Johnson
Kristian Høgsberg's avatar
Kristian Høgsberg committed
7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it either under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * (the "LGPL") or, at your option, under the terms of the Mozilla
 * Public License Version 1.1 (the "MPL"). If you do not alter this
 * notice, a recipient may use your version of this file under either
 * the MPL or the LGPL.
 *
 * You should have received a copy of the LGPL along with this library
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
Andrea Canciani's avatar
Andrea Canciani committed
18
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
Kristian Høgsberg's avatar
Kristian Høgsberg committed
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
 * You should have received a copy of the MPL along with this library
 * in the file COPYING-MPL-1.1
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
 * the specific language governing rights and limitations.
 *
 * The Original Code is the cairo graphics library.
 *
 * The Initial Developer of the Original Code is University of Southern
 * California.
 *
 * Contributor(s):
 *	Kristian Høgsberg <krh@redhat.com>
38
 *	Carl Worth <cworth@cworth.org>
39
 *	Adrian Johnson <ajohnson@redneon.com>
Kristian Høgsberg's avatar
Kristian Høgsberg committed
40 41
 */

42
#define _DEFAULT_SOURCE /* for snprintf() */
Kristian Høgsberg's avatar
Kristian Høgsberg committed
43
#include "cairoint.h"
44

Carl Worth's avatar
Carl Worth committed
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"
49 50

#include "cairo-array-private.h"
51
#include "cairo-analysis-surface-private.h"
52
#include "cairo-composite-rectangles-private.h"
Chris Wilson's avatar
Chris Wilson committed
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 59 60
#include "cairo-output-stream-private.h"
#include "cairo-paginated-private.h"
#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"
Kristian Høgsberg's avatar
Kristian Høgsberg committed
65

66
#include <zlib.h>
Kristian Høgsberg's avatar
Kristian Høgsberg committed
67

68 69 70 71
/*
 * Page Structure of the Generated PDF:
 *
 * Each page requiring fallbacks images contains a knockout group at
Adrian Johnson's avatar
Adrian Johnson committed
72 73 74 75
 * the top level. The first operation of the knockout group paints a
 * group containing all the supported drawing operations. Fallback
 * images (if any) are painted in the knockout group. This ensures
 * that fallback images do not composite with any content under the
76 77 78 79 80 81 82 83 84 85 86
 * fallback images.
 *
 * Streams:
 *
 * This PDF surface has three types of streams:
 *  - PDF Stream
 *  - Content Stream
 *  - Group Stream
 *
 * Calling _cairo_output_stream_printf (surface->output, ...) will
 * write to the currently open stream.
Kristian Høgsberg's avatar
Kristian Høgsberg committed
87
 *
88 89
 * PDF Stream:
 *   A PDF Stream may be opened and closed with the following functions:
90
 *     _cairo_pdf_surface_open stream ()
91 92 93 94 95 96 97
 *     _cairo_pdf_surface_close_stream ()
 *
 *   PDF Streams are written directly to the PDF file. They are used for
 *   fonts, images and patterns.
 *
 * Content Stream:
 *   The Content Stream is opened and closed with the following functions:
98 99
 *     _cairo_pdf_surface_open_content_stream ()
 *     _cairo_pdf_surface_close_content_stream ()
100
 *
101
 *   The Content Stream contains the text and graphics operators.
102 103 104 105 106 107
 *
 * Group Stream:
 *   A Group Stream may be opened and closed with the following functions:
 *     _cairo_pdf_surface_open_group ()
 *     _cairo_pdf_surface_close_group ()
 *
108 109 110 111 112
 *   A Group Stream is a Form XObject. It is used for short sequences
 *   of operators. As the content is very short the group is stored in
 *   memory until it is closed. This allows some optimization such as
 *   including the Resource dictionary and stream length inside the
 *   XObject instead of using an indirect object.
Kristian Høgsberg's avatar
Kristian Høgsberg committed
113 114
 */

115 116 117 118 119 120 121 122
/**
 * SECTION:cairo-pdf
 * @Title: PDF Surfaces
 * @Short_Description: Rendering PDF documents
 * @See_Also: #cairo_surface_t
 *
 * The PDF surface is used to render cairo graphics to Adobe
 * PDF files and is a multi-page vector surface backend.
123 124 125 126
 *
 * The following mime types are supported: %CAIRO_MIME_TYPE_JPEG,
 * %CAIRO_MIME_TYPE_JP2, %CAIRO_MIME_TYPE_UNIQUE_ID,
 * %CAIRO_MIME_TYPE_JBIG2, %CAIRO_MIME_TYPE_JBIG2_GLOBAL,
127 128
 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
 * %CAIRO_MIME_TYPE_CCITT_FAX, %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS.
129
 *
130
 * # JBIG2 Images #
131
 * JBIG2 data in PDF must be in the embedded format as described in
132 133 134 135 136
 * ISO/IEC 11544. Image specific JBIG2 data must be in
 * %CAIRO_MIME_TYPE_JBIG2.  Any global segments in the JBIG2 data
 * (segments with page association field set to 0) must be in
 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data may be shared by
 * multiple images. All images sharing the same global data must set
137
 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID to a unique identifier. At least
138 139
 * one of the images must provide the global data using
 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data will only be
140
 * embedded once and shared by all JBIG2 images with the same
141
 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
 *
 * # CCITT Fax Images # {#ccitt}
 * The %CAIRO_MIME_TYPE_CCITT_FAX mime data requires a number of decoding
 * parameters These parameters are specified using %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS.
 *
 * %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS mime data must contain a string of the form
 * "param1=value1 param2=value2 ...".
 *
 * @Columns: [required] An integer specifying the width of the image in pixels.
 *
 * @Rows: [required] An integer specifying the height of the image in scan lines.
 *
 * @K: [optional] An integer identifying the encoding scheme used. < 0
 * is 2 dimensional Group 4, = 0 is Group3 1 dimensional, > 0 is mixed 1
 * and 2 dimensional encoding. Default is 0.
 *
 * @EndOfLine: [optional] If true end-of-line bit patterns are present. Default is false.
 *
 * @EncodedByteAlign: [optional] If true the end of line is padded
 * with 0 bits so the next line begins on a byte boundary. Default is false.
 *
 * @EndOfBlock: [optional] If true the data contains an end-of-block pattern. Default is true.
 *
 * @BlackIs1: [optional] If true 1 bits are black pixels. Default is false.
 *
 * @DamagedRowsBeforeError: [optional] An integer specifying the
 * number of damages rows tolerated before an error occurs. Default is 0.
 *
 * Boolean values may be "true" or "false", or 1 or 0.
 *
 * These parameters are the same as the CCITTFaxDecode parameters in the
 * [PostScript Language Reference](https://www.adobe.com/products/postscript/pdfs/PLRM.pdf)
 * and [Portable Document Format (PDF)](https://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf).
 * Refer to these documents for further details.
 *
 * An example %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS string is:
 *
 * <programlisting>
 * "Columns=10230 Rows=40000 K=1 EndOfLine=true EncodedByteAlign=1 BlackIs1=false"
 * </programlisting>
 *
183
 **/
184

185 186 187 188
static cairo_bool_t
_cairo_pdf_surface_get_extents (void		        *abstract_surface,
				cairo_rectangle_int_t   *rectangle);

189 190 191 192 193
/**
 * CAIRO_HAS_PDF_SURFACE:
 *
 * Defined if the PDF surface backend is available.
 * This macro can be used to conditionally compile backend-specific code.
194 195
 *
 * Since: 1.2
196
 **/
197

198 199 200 201 202 203 204 205 206 207 208 209 210 211
static const cairo_pdf_version_t _cairo_pdf_versions[] =
{
    CAIRO_PDF_VERSION_1_4,
    CAIRO_PDF_VERSION_1_5
};

#define CAIRO_PDF_VERSION_LAST ARRAY_LENGTH (_cairo_pdf_versions)

static const char * _cairo_pdf_version_strings[CAIRO_PDF_VERSION_LAST] =
{
    "PDF 1.4",
    "PDF 1.5"
};

212 213 214 215 216
static const char *_cairo_pdf_supported_mime_types[] =
{
    CAIRO_MIME_TYPE_JPEG,
    CAIRO_MIME_TYPE_JP2,
    CAIRO_MIME_TYPE_UNIQUE_ID,
217 218 219
    CAIRO_MIME_TYPE_JBIG2,
    CAIRO_MIME_TYPE_JBIG2_GLOBAL,
    CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
220 221
    CAIRO_MIME_TYPE_CCITT_FAX,
    CAIRO_MIME_TYPE_CCITT_FAX_PARAMS,
222 223 224
    NULL
};

225
typedef struct _cairo_pdf_object {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
226
    long offset;
227
} cairo_pdf_object_t;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
228

229 230 231 232 233 234
typedef struct _cairo_pdf_font {
    unsigned int font_id;
    unsigned int subset_id;
    cairo_pdf_resource_t subset_resource;
} cairo_pdf_font_t;

235 236 237 238 239 240 241 242 243 244 245 246
typedef struct _cairo_pdf_rgb_linear_function {
    cairo_pdf_resource_t resource;
    double               color1[3];
    double               color2[3];
} cairo_pdf_rgb_linear_function_t;

typedef struct _cairo_pdf_alpha_linear_function {
    cairo_pdf_resource_t resource;
    double               alpha1;
    double               alpha2;
} cairo_pdf_alpha_linear_function_t;

Kristian Høgsberg's avatar
Kristian Høgsberg committed
247 248 249
static void
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);

250 251 252
static void
_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);

253
static cairo_int_status_t
254 255
_cairo_pdf_surface_add_font (unsigned int        font_id,
			     unsigned int        subset_id,
256
			     void		*closure);
257

258 259 260
static void
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);

261
static cairo_int_status_t
262
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
263
				cairo_pdf_resource_t    *resource,
264
                                cairo_bool_t             compressed,
265
				const char		*fmt,
266
				...) CAIRO_PRINTF_FORMAT(4, 5);
267
static cairo_int_status_t
268
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t	*surface);
269

270 271 272 273 274 275
static cairo_int_status_t
_cairo_pdf_surface_emit_surface (cairo_pdf_surface_t        *surface,
				 cairo_pdf_source_surface_t *source,
				 cairo_bool_t                test,
				 cairo_bool_t               *is_image);

276
static cairo_int_status_t
277 278
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);

279 280 281 282 283 284 285 286 287
static void
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);

static cairo_pdf_resource_t
_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface);

static long
_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);

288 289 290 291
static cairo_int_status_t
_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface,
						    cairo_bool_t         finish);

292
static cairo_int_status_t
293 294
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);

295
static cairo_int_status_t
296 297
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);

298
static cairo_bool_t
Adrian Johnson's avatar
Adrian Johnson committed
299
_cairo_pdf_source_surface_equal (const void *key_a, const void *key_b);
300

Kristian Høgsberg's avatar
Kristian Høgsberg committed
301
static const cairo_surface_backend_t cairo_pdf_surface_backend;
302
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
303

304
cairo_pdf_resource_t
305
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
Kristian Høgsberg's avatar
Kristian Høgsberg committed
306
{
307
    cairo_pdf_resource_t resource;
308
    cairo_int_status_t status;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
309 310
    cairo_pdf_object_t object;

311
    object.offset = _cairo_output_stream_get_position (surface->output);
312

313
    status = _cairo_array_append (&surface->objects, &object);
314
    if (unlikely (status)) {
315 316 317
	resource.id = 0;
	return resource;
    }
Kristian Høgsberg's avatar
Kristian Høgsberg committed
318

319 320
    resource = surface->next_available_resource;
    surface->next_available_resource.id++;
321 322

    return resource;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
323 324
}

325
void
326 327
_cairo_pdf_surface_update_object (cairo_pdf_surface_t	*surface,
				  cairo_pdf_resource_t	 resource)
328 329 330
{
    cairo_pdf_object_t *object;

331 332
    object = _cairo_array_index (&surface->objects, resource.id - 1);
    object->offset = _cairo_output_stream_get_position (surface->output);
333 334
}

335
static void
336 337 338
_cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
				      double		  width,
				      double		  height)
339 340 341
{
    surface->width = width;
    surface->height = height;
342 343 344 345
    surface->surface_extents.x = 0;
    surface->surface_extents.y = 0;
    surface->surface_extents.width  = ceil (surface->width);
    surface->surface_extents.height = ceil (surface->height);
346 347
}

348 349 350 351 352 353
static cairo_bool_t
_path_covers_bbox (cairo_pdf_surface_t *surface,
		   cairo_path_fixed_t *path)
{
    cairo_box_t box;

354
    return _cairo_path_fixed_is_box (path, &box) &&
355 356 357 358 359 360
	   box.p1.x <= 0 &&
	   box.p1.y <= 0 &&
	   box.p2.x >= _cairo_fixed_from_double (surface->width) &&
	   box.p2.y >= _cairo_fixed_from_double (surface->height);
}

361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
static cairo_status_t
_cairo_pdf_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
						cairo_path_fixed_t	*path,
						cairo_fill_rule_t	fill_rule,
						double			tolerance,
						cairo_antialias_t	antialias)
{
    cairo_pdf_surface_t *surface = cairo_container_of (clipper,
						       cairo_pdf_surface_t,
						       clipper);
    cairo_int_status_t status;

    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
    if (unlikely (status))
	return status;

    if (path == NULL) {
	_cairo_output_stream_printf (surface->output, "Q q\n");

	surface->current_pattern_is_solid_color = FALSE;
	_cairo_pdf_operators_reset (&surface->pdf_operators);

	return CAIRO_STATUS_SUCCESS;
    }

386 387 388
    if (_path_covers_bbox (surface, path))
	return CAIRO_STATUS_SUCCESS;

389 390 391
    return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
}

392
static cairo_surface_t *
393
_cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
394 395
					       double			 width,
					       double			 height)
Kristian Høgsberg's avatar
Kristian Høgsberg committed
396
{
397
    cairo_pdf_surface_t *surface;
398
    cairo_status_t status, status_ignored;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
399

400
    surface = _cairo_malloc (sizeof (cairo_pdf_surface_t));
401
    if (unlikely (surface == NULL)) {
402 403
	/* destroy stream on behalf of caller */
	status = _cairo_output_stream_destroy (output);
404
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
405
    }
Kristian Høgsberg's avatar
Kristian Høgsberg committed
406

Chris Wilson's avatar
Chris Wilson committed
407 408 409
    _cairo_surface_init (&surface->base,
			 &cairo_pdf_surface_backend,
			 NULL, /* device */
410 411
			 CAIRO_CONTENT_COLOR_ALPHA,
			 TRUE); /* is_vector */
412 413 414 415

    surface->output = output;
    surface->width = width;
    surface->height = height;
416 417
    cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, 1, 0, 0);
    surface->in_xobject = FALSE;
418 419 420 421
    surface->surface_extents.x = 0;
    surface->surface_extents.y = 0;
    surface->surface_extents.width  = ceil (surface->width);
    surface->surface_extents.height = ceil (surface->height);
422
    surface->surface_bounded = TRUE;
423 424 425

    _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
    _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
426 427
    _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
    _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
428
    _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
429
    _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
430
    _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t));
431

432
    _cairo_array_init (&surface->page_patterns, sizeof (cairo_pdf_pattern_t));
Adrian Johnson's avatar
Adrian Johnson committed
433
    _cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t));
434
    _cairo_array_init (&surface->doc_surfaces, sizeof (cairo_pdf_source_surface_t));
435
    _cairo_array_init (&surface->jbig2_global, sizeof (cairo_pdf_jbig2_global_t));
Adrian Johnson's avatar
Adrian Johnson committed
436
    _cairo_array_init (&surface->page_heights, sizeof (double));
Adrian Johnson's avatar
Adrian Johnson committed
437 438
    surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal);
    if (unlikely (surface->all_surfaces == NULL)) {
439 440 441 442
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto BAIL0;
    }

443
    _cairo_pdf_group_resources_init (&surface->resources);
444

445
    surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
446
    if (! surface->font_subsets) {
447
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
448
	goto BAIL1;
449 450
    }

451 452
    _cairo_scaled_font_subsets_enable_latin_subset (surface->font_subsets, TRUE);

453 454
    surface->next_available_resource.id = 1;
    surface->pages_resource = _cairo_pdf_surface_new_object (surface);
455 456
    if (surface->pages_resource.id == 0) {
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
457
        goto BAIL2;
458
    }
459

460
    surface->struct_tree_root.id = 0;
461
    surface->pdf_version = CAIRO_PDF_VERSION_1_5;
462
    surface->compress_content = TRUE;
463
    surface->pdf_stream.active = FALSE;
464
    surface->pdf_stream.old_output = NULL;
465 466
    surface->group_stream.active = FALSE;
    surface->group_stream.stream = NULL;
467
    surface->group_stream.mem_stream = NULL;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
468

469 470
    surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;

471
    surface->force_fallbacks = FALSE;
472
    surface->select_pattern_gstate_saved = FALSE;
473
    surface->current_pattern_is_solid_color = FALSE;
474
    surface->current_operator = CAIRO_OPERATOR_OVER;
475
    surface->header_emitted = FALSE;
476

477 478 479
    _cairo_surface_clipper_init (&surface->clipper,
				 _cairo_pdf_surface_clipper_intersect_clip_path);

480 481
    _cairo_pdf_operators_init (&surface->pdf_operators,
			       surface->output,
482
			       &surface->cairo_to_pdf,
483 484
			       surface->font_subsets,
			       FALSE);
485 486 487
    _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
						    _cairo_pdf_surface_add_font,
						    surface);
488
    _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators, TRUE);
489

490 491 492 493 494 495 496
    status = _cairo_pdf_interchange_init (surface);
    if (unlikely (status))
	goto BAIL2;

    surface->page_parent_tree = -1;
    _cairo_array_init (&surface->page_annots, sizeof (cairo_pdf_resource_t));
    surface->tagged = FALSE;
Adrian Johnson's avatar
Adrian Johnson committed
497 498
    surface->current_page_label = NULL;
    _cairo_array_init (&surface->page_labels, sizeof (char *));
499
    surface->outlines_dict_res.id = 0;
500
    surface->names_dict_res.id = 0;
Adrian Johnson's avatar
Adrian Johnson committed
501 502
    surface->docinfo_res.id = 0;
    surface->page_labels_res.id = 0;
Adrian Johnson's avatar
Adrian Johnson committed
503 504 505
    surface->thumbnail_width = 0;
    surface->thumbnail_height = 0;
    surface->thumbnail_image = NULL;
506

507 508 509
    if (getenv ("CAIRO_DEBUG_PDF") != NULL)
	surface->compress_content = FALSE;

510 511 512 513
    surface->paginated_surface =  _cairo_paginated_surface_create (
	                                  &surface->base,
					  CAIRO_CONTENT_COLOR_ALPHA,
					  &cairo_pdf_surface_paginated_backend);
514

515
    status = surface->paginated_surface->status;
516 517 518
    if (status == CAIRO_STATUS_SUCCESS) {
	/* paginated keeps the only reference to surface now, drop ours */
	cairo_surface_destroy (&surface->base);
519
	return surface->paginated_surface;
520
    }
521

522
BAIL2:
523
    _cairo_scaled_font_subsets_destroy (surface->font_subsets);
524
BAIL1:
Adrian Johnson's avatar
Adrian Johnson committed
525
    _cairo_hash_table_destroy (surface->all_surfaces);
526 527
BAIL0:
    _cairo_array_fini (&surface->objects);
528
    free (surface);
529

530
    /* destroy stream on behalf of caller */
531
    status_ignored = _cairo_output_stream_destroy (output);
532

533
    return _cairo_surface_create_in_error (status);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
534 535
}

536 537
/**
 * cairo_pdf_surface_create_for_stream:
538 539 540 541
 * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
 *              to indicate a no-op @write_func. With a no-op @write_func,
 *              the surface may be queried or used as a source without
 *              generating any temporary files.
Behdad Esfahbod's avatar
Behdad Esfahbod committed
542
 * @closure: the closure argument for @write_func
543 544
 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
545
 *
546
 * Creates a PDF surface of the specified size in points to be written
Behdad Esfahbod's avatar
Behdad Esfahbod committed
547
 * incrementally to the stream represented by @write_func and @closure.
548 549
 *
 * Return value: a pointer to the newly created surface. The caller
550
 * owns the surface and should call cairo_surface_destroy() when done
551 552 553 554 555
 * with it.
 *
 * This function always returns a valid pointer, but it will return a
 * pointer to a "nil" surface if an error such as out of memory
 * occurs. You can use cairo_surface_status() to check for this.
556 557
 *
 * Since: 1.2
558
 **/
559
cairo_surface_t *
Behdad Esfahbod's avatar
Behdad Esfahbod committed
560
cairo_pdf_surface_create_for_stream (cairo_write_func_t		 write_func,
561
				     void			*closure,
562 563
				     double			 width_in_points,
				     double			 height_in_points)
564
{
565
    cairo_output_stream_t *output;
566

Behdad Esfahbod's avatar
Behdad Esfahbod committed
567
    output = _cairo_output_stream_create (write_func, NULL, closure);
568 569
    if (_cairo_output_stream_get_status (output))
	return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
570

571
    return _cairo_pdf_surface_create_for_stream_internal (output,
Carl Worth's avatar
Carl Worth committed
572 573
							  width_in_points,
							  height_in_points);
574 575
}

576 577
/**
 * cairo_pdf_surface_create:
578 579 580 581
 * @filename: a filename for the PDF output (must be writable), %NULL may be
 *            used to specify no output. This will generate a PDF surface that
 *            may be queried and used as a source, without generating a
 *            temporary file.
582 583
 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
584
 *
585 586
 * Creates a PDF surface of the specified size in points to be written
 * to @filename.
587
 *
588
 * Return value: a pointer to the newly created surface. The caller
589
 * owns the surface and should call cairo_surface_destroy() when done
590 591 592 593 594
 * with it.
 *
 * This function always returns a valid pointer, but it will return a
 * pointer to a "nil" surface if an error such as out of memory
 * occurs. You can use cairo_surface_status() to check for this.
595 596
 *
 * Since: 1.2
597
 **/
598
cairo_surface_t *
599
cairo_pdf_surface_create (const char		*filename,
600 601
			  double		 width_in_points,
			  double		 height_in_points)
602
{
603
    cairo_output_stream_t *output;
604

605
    output = _cairo_output_stream_create_for_filename (filename);
606 607
    if (_cairo_output_stream_get_status (output))
	return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
608

609
    return _cairo_pdf_surface_create_for_stream_internal (output,
Carl Worth's avatar
Carl Worth committed
610 611
							  width_in_points,
							  height_in_points);
612 613
}

614 615 616 617 618 619
static cairo_bool_t
_cairo_surface_is_pdf (cairo_surface_t *surface)
{
    return surface->backend == &cairo_pdf_surface_backend;
}

620 621
/* If the abstract_surface is a paginated surface, and that paginated
 * surface's target is a pdf_surface, then set pdf_surface to that
622
 * target. Otherwise return FALSE.
623
 */
624
static cairo_bool_t
625 626 627 628
_extract_pdf_surface (cairo_surface_t		 *surface,
		      cairo_pdf_surface_t	**pdf_surface)
{
    cairo_surface_t *target;
629
    cairo_status_t status_ignored;
630

631
    if (surface->status)
632
	return FALSE;
633 634 635 636 637
    if (surface->finished) {
	status_ignored = _cairo_surface_set_error (surface,
						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
        return FALSE;
    }
638

639 640 641 642 643
    if (! _cairo_surface_is_paginated (surface)) {
	status_ignored = _cairo_surface_set_error (surface,
						   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
	return FALSE;
    }
644 645

    target = _cairo_paginated_surface_get_target (surface);
646 647 648 649 650
    if (target->status) {
	status_ignored = _cairo_surface_set_error (surface,
						   target->status);
	return FALSE;
    }
651 652 653 654 655
    if (target->finished) {
	status_ignored = _cairo_surface_set_error (surface,
						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
	return FALSE;
    }
656

657 658 659 660 661
    if (! _cairo_surface_is_pdf (target)) {
	status_ignored = _cairo_surface_set_error (surface,
						   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
	return FALSE;
    }
662 663

    *pdf_surface = (cairo_pdf_surface_t *) target;
664
    return TRUE;
665 666
}

667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687
/**
 * cairo_pdf_surface_restrict_to_version:
 * @surface: a PDF #cairo_surface_t
 * @version: PDF version
 *
 * Restricts the generated PDF file to @version. See cairo_pdf_get_versions()
 * for a list of available version values that can be used here.
 *
 * This function should only be called before any drawing operations
 * have been performed on the given surface. The simplest way to do
 * this is to call this function immediately after creating the
 * surface.
 *
 * Since: 1.10
 **/
void
cairo_pdf_surface_restrict_to_version (cairo_surface_t 		*abstract_surface,
				       cairo_pdf_version_t  	 version)
{
    cairo_pdf_surface_t *surface = NULL; /* hide compiler warning */

688
    if (! _extract_pdf_surface (abstract_surface, &surface))
689 690 691 692
	return;

    if (version < CAIRO_PDF_VERSION_LAST)
	surface->pdf_version = version;
693 694 695

    _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators,
					    version >= CAIRO_PDF_VERSION_1_5);
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
}

/**
 * cairo_pdf_get_versions:
 * @versions: supported version list
 * @num_versions: list length
 *
 * Used to retrieve the list of supported versions. See
 * cairo_pdf_surface_restrict_to_version().
 *
 * Since: 1.10
 **/
void
cairo_pdf_get_versions (cairo_pdf_version_t const	**versions,
                        int                     	 *num_versions)
{
    if (versions != NULL)
	*versions = _cairo_pdf_versions;

    if (num_versions != NULL)
	*num_versions = CAIRO_PDF_VERSION_LAST;
}

/**
 * cairo_pdf_version_to_string:
 * @version: a version id
 *
 * Get the string representation of the given @version id. This function
 * will return %NULL if @version isn't valid. See cairo_pdf_get_versions()
 * for a way to get the list of valid version ids.
 *
 * Return value: the string associated to given version.
 *
 * Since: 1.10
 **/
const char *
cairo_pdf_version_to_string (cairo_pdf_version_t version)
{
    if (version >= CAIRO_PDF_VERSION_LAST)
	return NULL;

    return _cairo_pdf_version_strings[version];
}

740 741
/**
 * cairo_pdf_surface_set_size:
742
 * @surface: a PDF #cairo_surface_t
743 744
 * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
 * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
745
 *
746 747 748 749 750 751 752 753
 * Changes the size of a PDF surface for the current (and
 * subsequent) pages.
 *
 * This function should only be called before any drawing operations
 * have been performed on the current page. The simplest way to do
 * this is to call this function immediately after creating the
 * surface or immediately after completing a page with either
 * cairo_show_page() or cairo_copy_page().
754 755
 *
 * Since: 1.2
756 757 758 759 760 761
 **/
void
cairo_pdf_surface_set_size (cairo_surface_t	*surface,
			    double		 width_in_points,
			    double		 height_in_points)
{
762
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
763
    cairo_status_t status;
764

765
    if (! _extract_pdf_surface (surface, &pdf_surface))
766 767
	return;

768 769 770
    _cairo_pdf_surface_set_size_internal (pdf_surface,
					  width_in_points,
					  height_in_points);
771 772 773 774 775
    status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
						width_in_points,
						height_in_points);
    if (status)
	status = _cairo_surface_set_error (surface, status);
776 777
}

778 779 780 781 782 783 784 785 786 787 788 789 790
/**
 * CAIRO_PDF_OUTLINE_ROOT:
 *
 * The root outline item in cairo_pdf_surface_add_outline().
 *
 * Since: 1.16
 **/

/**
 * cairo_pdf_surface_add_outline:
 * @surface: a PDF #cairo_surface_t
 * @parent_id: the id of the parent item or %CAIRO_PDF_OUTLINE_ROOT if this is a top level item.
 * @utf8: the name of the outline
791
 * @link_attribs: the link attributes specifying where this outline links to
792 793
 * @flags: outline item flags
 *
794 795 796 797 798 799
 * Add an item to the document outline hierarchy with the name @utf8
 * that links to the location specified by @link_attribs. Link
 * attributes have the same keys and values as the [Link Tag][link],
 * excluding the "rect" attribute. The item will be a child of the
 * item with id @parent_id. Use %CAIRO_PDF_OUTLINE_ROOT as the parent
 * id of top level items.
800 801 802 803 804 805 806 807 808
 *
 * Return value: the id for the added item.
 *
 * Since: 1.16
 **/
int
cairo_pdf_surface_add_outline (cairo_surface_t	         *surface,
			       int                        parent_id,
			       const char                *utf8,
809
			       const char                *link_attribs,
810 811 812 813 814 815 816 817 818 819 820 821
			       cairo_pdf_outline_flags_t  flags)
{
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
    cairo_status_t status;
    int id = 0;

    if (! _extract_pdf_surface (surface, &pdf_surface))
	return 0;

    status = _cairo_pdf_interchange_add_outline (pdf_surface,
						 parent_id,
						 utf8,
822
						 link_attribs,
823 824 825 826 827 828 829 830
						 flags,
						 &id);
    if (status)
	status = _cairo_surface_set_error (surface, status);

    return id;
}

Adrian Johnson's avatar
Adrian Johnson committed
831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
/**
 * cairo_pdf_surface_set_metadata:
 * @surface: a PDF #cairo_surface_t
 * @metadata: The metadata item to set.
 * @utf8: metadata value
 *
 * Set document metadata. The %CAIRO_PDF_METADATA_CREATE_DATE and
 * %CAIRO_PDF_METADATA_MOD_DATE values must be in ISO-8601 format:
 * YYYY-MM-DDThh:mm:ss. An optional timezone of the form "[+/-]hh:mm"
 * or "Z" for UTC time can be appended. All other metadata values can be any UTF-8
 * string.
 *
 * For example:
 * <informalexample><programlisting>
 * cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_TITLE, "My Document");
 * cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_CREATE_DATE, "2015-12-31T23:59+02:00");
 * </programlisting></informalexample>
 *
 * Since: 1.16
 **/
void
cairo_pdf_surface_set_metadata (cairo_surface_t      *surface,
				cairo_pdf_metadata_t  metadata,
                                const char           *utf8)
{
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
    cairo_status_t status;

    if (! _extract_pdf_surface (surface, &pdf_surface))
	return;

    status = _cairo_pdf_interchange_set_metadata (pdf_surface, metadata, utf8);
    if (status)
	status = _cairo_surface_set_error (surface, status);
}

Adrian Johnson's avatar
Adrian Johnson committed
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
/**
 * cairo_pdf_surface_set_page_label:
 * @surface: a PDF #cairo_surface_t
 * @utf8: The page label.
 *
 * Set page label for the current page.
 *
 * Since: 1.16
 **/
void
cairo_pdf_surface_set_page_label (cairo_surface_t *surface,
                                  const char      *utf8)
{
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */

    if (! _extract_pdf_surface (surface, &pdf_surface))
	return;

    free (pdf_surface->current_page_label);
    pdf_surface->current_page_label = utf8 ? strdup (utf8) : NULL;
}

Adrian Johnson's avatar
Adrian Johnson committed
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914
/**
 * cairo_pdf_surface_set_thumbnail_size:
 * @surface: a PDF #cairo_surface_t
 * @width: Thumbnail width.
 * @height: Thumbnail height
 *
 * Set the thumbnail image size for the current and all subsequent
 * pages. Setting a width or height of 0 disables thumbnails for the
 * current and subsequent pages.
 *
 * Since: 1.16
 **/
void
cairo_pdf_surface_set_thumbnail_size (cairo_surface_t *surface,
				      int              width,
				      int              height)
{
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */

    if (! _extract_pdf_surface (surface, &pdf_surface))
	return;

    pdf_surface->thumbnail_width = width;
    pdf_surface->thumbnail_height = height;
}

Kristian Høgsberg's avatar
Kristian Høgsberg committed
915 916 917
static void
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
{
918 919
    int i, size;
    cairo_pdf_pattern_t *pattern;
Adrian Johnson's avatar
Adrian Johnson committed
920
    cairo_pdf_source_surface_t *src_surface;
921 922
    cairo_pdf_smask_group_t *group;

923
    size = _cairo_array_num_elements (&surface->page_patterns);
924
    for (i = 0; i < size; i++) {
925
	pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->page_patterns, i);
926 927
	cairo_pattern_destroy (pattern->pattern);
    }
928
    _cairo_array_truncate (&surface->page_patterns, 0);
929

Adrian Johnson's avatar
Adrian Johnson committed
930 931 932 933 934 935 936
    size = _cairo_array_num_elements (&surface->page_surfaces);
    for (i = 0; i < size; i++) {
	src_surface = (cairo_pdf_source_surface_t *) _cairo_array_index (&surface->page_surfaces, i);
	cairo_surface_destroy (src_surface->surface);
    }
    _cairo_array_truncate (&surface->page_surfaces, 0);

937 938 939 940 941 942
    size = _cairo_array_num_elements (&surface->smask_groups);
    for (i = 0; i < size; i++) {
	_cairo_array_copy_element (&surface->smask_groups, i, &group);
	_cairo_pdf_smask_group_destroy (group);
    }
    _cairo_array_truncate (&surface->smask_groups, 0);
943
    _cairo_array_truncate (&surface->knockout_group, 0);
944
    _cairo_array_truncate (&surface->page_annots, 0);
Adrian Johnson's avatar
Adrian Johnson committed
945 946 947

    cairo_surface_destroy (&surface->thumbnail_image->base);
    surface->thumbnail_image = NULL;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
948 949
}

950 951 952
static void
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
{
953 954 955 956 957
    int i;

    for (i = 0; i < CAIRO_NUM_OPERATORS; i++)
	res->operators[i] = FALSE;

958 959 960
    _cairo_array_init (&res->alphas, sizeof (double));
    _cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t));
    _cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t));
961
    _cairo_array_init (&res->shadings, sizeof (cairo_pdf_resource_t));
962 963 964 965 966 967 968 969 970 971
    _cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t));
    _cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t));
}

static void
_cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
{
    _cairo_array_fini (&res->alphas);
    _cairo_array_fini (&res->smasks);
    _cairo_array_fini (&res->patterns);
972
    _cairo_array_fini (&res->shadings);
973 974 975 976 977 978 979
    _cairo_array_fini (&res->xobjects);
    _cairo_array_fini (&res->fonts);
}

static void
_cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
{
980 981 982 983 984
    int i;

    for (i = 0; i < CAIRO_NUM_OPERATORS; i++)
	res->operators[i] = FALSE;

985 986 987
    _cairo_array_truncate (&res->alphas, 0);
    _cairo_array_truncate (&res->smasks, 0);
    _cairo_array_truncate (&res->patterns, 0);
988
    _cairo_array_truncate (&res->shadings, 0);
989 990 991 992
    _cairo_array_truncate (&res->xobjects, 0);
    _cairo_array_truncate (&res->fonts, 0);
}

993 994 995 996 997 998 999 1000 1001
static void
_cairo_pdf_surface_add_operator (cairo_pdf_surface_t *surface,
				 cairo_operator_t     op)
{
    cairo_pdf_group_resources_t *res = &surface->resources;

    res->operators[op] = TRUE;
}

1002
static cairo_int_status_t
1003 1004 1005 1006 1007 1008
_cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
			      double               alpha,
			      int                 *index)
{
    int num_alphas, i;
    double other;
1009
    cairo_int_status_t status;
1010
    cairo_pdf_group_resources_t *res = &surface->resources;
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021

    num_alphas = _cairo_array_num_elements (&res->alphas);
    for (i = 0; i < num_alphas; i++) {
	_cairo_array_copy_element (&res->alphas, i, &other);
	if (alpha == other) {
	    *index = i;
	    return CAIRO_STATUS_SUCCESS;
	}
    }

    status = _cairo_array_append (&res->alphas, &alpha);
1022
    if (unlikely (status))
1023 1024 1025 1026 1027 1028 1029
	return status;

    *index = _cairo_array_num_elements (&res->alphas) - 1;

    return CAIRO_STATUS_SUCCESS;
}

1030
static cairo_int_status_t
1031 1032 1033
_cairo_pdf_surface_add_smask (cairo_pdf_surface_t  *surface,
			      cairo_pdf_resource_t  smask)
{
1034
    return _cairo_array_append (&(surface->resources.smasks), &smask);
1035 1036
}

1037
static cairo_int_status_t
1038 1039 1040
_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t  *surface,
				cairo_pdf_resource_t  pattern)
{
1041
    return _cairo_array_append (&(surface->resources.patterns), &pattern);
1042 1043
}

1044
static cairo_int_status_t
1045 1046 1047 1048 1049 1050 1051
_cairo_pdf_surface_add_shading (cairo_pdf_surface_t  *surface,
				cairo_pdf_resource_t  shading)
{
    return _cairo_array_append (&(surface->resources.shadings), &shading);
}


1052
static cairo_int_status_t
1053 1054 1055
_cairo_pdf_surface_add_xobject (cairo_pdf_surface_t  *surface,
				cairo_pdf_resource_t  xobject)
{
1056
    return _cairo_array_append (&(surface->resources.xobjects), &xobject);
1057 1058
}

1059
static cairo_int_status_t
1060 1061
_cairo_pdf_surface_add_font (unsigned int        font_id,
			     unsigned int        subset_id,
1062
			     void		*closure)
1063
{
1064
    cairo_pdf_surface_t *surface = closure;
1065 1066
    cairo_pdf_font_t font;
    int num_fonts, i;
1067
    cairo_int_status_t status;
1068
    cairo_pdf_group_resources_t *res = &surface->resources;
1069

1070
    num_fonts = _cairo_array_num_elements (&res->fonts);
1071
    for (i = 0; i < num_fonts; i++) {
1072
	_cairo_array_copy_element (&res->fonts, i, &font);
1073
	if (font.font_id == font_id &&
1074
	    font.subset_id == subset_id)
1075 1076 1077
	    return CAIRO_STATUS_SUCCESS;
    }

1078 1079 1080 1081 1082 1083 1084 1085
    num_fonts = _cairo_array_num_elements (&surface->fonts);
    for (i = 0; i < num_fonts; i++) {
	_cairo_array_copy_element (&surface->fonts, i, &font);
	if (font.font_id == font_id &&
	    font.subset_id == subset_id)
	    return _cairo_array_append (&res->fonts, &font);
    }

1086 1087 1088
    font.font_id = font_id;
    font.subset_id = subset_id;
    font.subset_resource = _cairo_pdf_surface_new_object (surface);
1089 1090
    if (font.subset_resource.id == 0)
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1091

1092
    status = _cairo_array_append (&surface->fonts, &font);
1093
    if (unlikely (status))
1094 1095
	return status;

1096
    return _cairo_array_append (&res->fonts, &font);
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
}

static cairo_pdf_resource_t
_cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface,
				      unsigned int         font_id,
				      unsigned int         subset_id)
{
    cairo_pdf_font_t font;
    int num_fonts, i;

    num_fonts = _cairo_array_num_elements (&surface->fonts);
    for (i = 0; i < num_fonts; i++) {
	_cairo_array_copy_element (&surface->fonts, i, &font);
	if (font.font_id == font_id && font.subset_id == subset_id)
	    return font.subset_resource;
    }

1114 1115
    font.subset_resource.id = 0;
    return font.subset_resource;
1116 1117
}

1118 1119 1120 1121
static const char *
_cairo_operator_to_pdf_blend_mode (cairo_operator_t op)
{
    switch (op) {
Chris Wilson's avatar
Chris Wilson committed
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
    /* The extend blend mode operators */
    case CAIRO_OPERATOR_MULTIPLY:       return "Multiply";
    case CAIRO_OPERATOR_SCREEN:         return "Screen";
    case CAIRO_OPERATOR_OVERLAY:        return "Overlay";
    case CAIRO_OPERATOR_DARKEN:         return "Darken";
    case CAIRO_OPERATOR_LIGHTEN:        return "Lighten";
    case CAIRO_OPERATOR_COLOR_DODGE:    return "ColorDodge";
    case CAIRO_OPERATOR_COLOR_BURN:     return "ColorBurn";
    case CAIRO_OPERATOR_HARD_LIGHT:     return "HardLight";
    case CAIRO_OPERATOR_SOFT_LIGHT:     return "SoftLight";
    case CAIRO_OPERATOR_DIFFERENCE:     return "Difference";
    case CAIRO_OPERATOR_EXCLUSION:      return "Exclusion";
    case CAIRO_OPERATOR_HSL_HUE:        return "Hue";
    case CAIRO_OPERATOR_HSL_SATURATION: return "Saturation";
    case CAIRO_OPERATOR_HSL_COLOR:      return "Color";
    case CAIRO_OPERATOR_HSL_LUMINOSITY: return "Luminosity";
1138 1139

    default:
Chris Wilson's avatar
Chris Wilson committed
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
    /* The original Porter-Duff set */
    case CAIRO_OPERATOR_CLEAR:
    case CAIRO_OPERATOR_SOURCE:
    case CAIRO_OPERATOR_OVER:
    case CAIRO_OPERATOR_IN:
    case CAIRO_OPERATOR_OUT:
    case CAIRO_OPERATOR_ATOP:
    case CAIRO_OPERATOR_DEST:
    case CAIRO_OPERATOR_DEST_OVER:
    case CAIRO_OPERATOR_DEST_IN:
    case CAIRO_OPERATOR_DEST_OUT:
    case CAIRO_OPERATOR_DEST_ATOP:
    case CAIRO_OPERATOR_XOR:
    case CAIRO_OPERATOR_ADD:
    case CAIRO_OPERATOR_SATURATE:
1155 1156 1157 1158
	return "Normal";
    }
}

1159 1160 1161 1162 1163 1164
static void
_cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t         *surface,
					 cairo_pdf_group_resources_t *res)
{
    int num_alphas, num_smasks, num_resources, i;
    double alpha;
1165
    cairo_pdf_resource_t *smask, *pattern, *shading, *xobject;
1166 1167
    cairo_pdf_font_t *font;

1168
    _cairo_output_stream_printf (surface->output, "<<\n");
1169 1170 1171 1172 1173

    num_alphas = _cairo_array_num_elements (&res->alphas);
    num_smasks = _cairo_array_num_elements (&res->smasks);
    if (num_alphas > 0 || num_smasks > 0) {
	_cairo_output_stream_printf (surface->output,
1174
				     "   /ExtGState <<\n");
1175

1176
	for (i = 0; i < CAIRO_NUM_OPERATORS; i++) {
Chris Wilson's avatar
Chris Wilson committed
1177
	    if (res->operators[i]) {
1178 1179 1180
		_cairo_output_stream_printf (surface->output,
					     "      /b%d << /BM /%s >>\n",
					     i, _cairo_operator_to_pdf_blend_mode(i));
Chris Wilson's avatar
Chris Wilson committed
1181
	    }
1182 1183
	}

1184 1185 1186
	for (i = 0; i < num_alphas; i++) {
	    _cairo_array_copy_element (&res->alphas, i, &alpha);
	    _cairo_output_stream_printf (surface->output,
1187
					 "      /a%d << /CA %f /ca %f >>\n",
1188 1189 1190 1191 1192 1193
					 i, alpha, alpha);
	}

	for (i = 0; i < num_smasks; i++) {
	    smask = _cairo_array_index (&res->smasks, i);
	    _cairo_output_stream_printf (surface->output,
1194
					 "      /s%d %d 0 R\n",
1195 1196 1197 1198
					 smask->id, smask->id);
	}

	_cairo_output_stream_printf (surface->output,
1199
				     "   >>\n");
1200 1201 1202 1203 1204
    }

    num_resources = _cairo_array_num_elements (&res->patterns);
    if (num_resources > 0) {
	_cairo_output_stream_printf (surface->output,
1205
				     "   /Pattern <<");
1206 1207 1208 1209 1210 1211 1212 1213
	for (i = 0; i < num_resources; i++) {
	    pattern = _cairo_array_index (&res->patterns, i);
	    _cairo_output_stream_printf (surface->output,
					 " /p%d %d 0 R",
					 pattern->id, pattern->id);
	}

	_cairo_output_stream_printf (surface->output,
1214
				     " >>\n");
1215 1216
    }

1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
    num_resources = _cairo_array_num_elements (&res->shadings);
    if (num_resources > 0) {
	_cairo_output_stream_printf (surface->output,
				     "   /Shading <<");
	for (i = 0; i < num_resources; i++) {
	    shading = _cairo_array_index (&res->shadings, i);
	    _cairo_output_stream_printf (surface->output,
					 " /sh%d %d 0 R",
					 shading->id, shading->id);
	}

	_cairo_output_stream_printf (surface->output,
				     " >>\n");
    }

1232 1233 1234
    num_resources = _cairo_array_num_elements (&res->xobjects);
    if (num_resources > 0) {
	_cairo_output_stream_printf (surface->output,
1235
				     "   /XObject <<");
1236 1237 1238 1239 1240 1241 1242 1243 1244

	for (