Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/cairo/src/cairo-pdf-surface.c
Line
Count
Source (jump to first uncovered line)
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
3
 *
4
 * Copyright © 2004 Red Hat, Inc
5
 * Copyright © 2006 Red Hat, Inc
6
 * Copyright © 2007, 2008 Adrian Johnson
7
 *
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.
15
 *
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
21
 *
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/
26
 *
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.
30
 *
31
 * The Original Code is the cairo graphics library.
32
 *
33
 * The Initial Developer of the Original Code is University of Southern
34
 * California.
35
 *
36
 * Contributor(s):
37
 *  Kristian Høgsberg <krh@redhat.com>
38
 *  Carl Worth <cworth@cworth.org>
39
 *  Adrian Johnson <ajohnson@redneon.com>
40
 */
41
42
#define _DEFAULT_SOURCE /* for snprintf() */
43
#include "cairoint.h"
44
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"
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"
65
66
#include <zlib.h>
67
68
/*
69
 * Page Structure of the Generated PDF:
70
 *
71
 * Each page requiring fallbacks images contains a knockout group at
72
 * the top level. The first operation of the knockout group paints a
73
 * group containing all the supported drawing operations. Fallback
74
 * images (if any) are painted in the knockout group. This ensures
75
 * that fallback images do not composite with any content under the
76
 * fallback images.
77
 *
78
 * Streams:
79
 *
80
 * This PDF surface has three types of streams:
81
 *  - PDF Stream
82
 *  - Content Stream
83
 *  - Group Stream
84
 *  - Object stream
85
 *
86
 * Calling _cairo_output_stream_printf (surface->output, ...) will
87
 * write to the currently open stream.
88
 *
89
 * PDF Stream:
90
 *   A PDF Stream may be opened and closed with the following functions:
91
 *     _cairo_pdf_surface_open stream ()
92
 *     _cairo_pdf_surface_close_stream ()
93
 *
94
 *   PDF Streams are written directly to the PDF file. They are used for
95
 *   fonts, images and patterns.
96
 *
97
 * Content Stream:
98
 *   The Content Stream is opened and closed with the following functions:
99
 *     _cairo_pdf_surface_open_content_stream ()
100
 *     _cairo_pdf_surface_close_content_stream ()
101
 *
102
 *   The Content Stream contains the text and graphics operators.
103
 *
104
 * Group Stream:
105
 *   A Group Stream may be opened and closed with the following functions:
106
 *     _cairo_pdf_surface_open_group ()
107
 *     _cairo_pdf_surface_close_group ()
108
 *
109
 *   A Group Stream is a Form XObject. It is used for short sequences
110
 *   of operators. As the content is very short the group is stored in
111
 *   memory until it is closed. This allows some optimization such as
112
 *   including the Resource dictionary and stream length inside the
113
 *   XObject instead of using an indirect object.
114
 *
115
 * Object Stream (PDF 1.5)
116
 *   An Object Stream may be opened and closed with the following functions:
117
 *     _cairo_pdf_surface_open_object_stream ()
118
 *     _cairo_pdf_surface_close_object_stream ()
119
 *
120
 *  An Object Stream contains one or more objects compressed into a stream.
121
 *  Only non stream objects are permitted. When emitting objects intended for
122
 *  the Object Stream, enclose the emit object operation with
123
 *  _cairo_pdf_surface_object_begin()/_cairo_pdf_surface_object_end().
124
 */
125
126
/**
127
 * SECTION:cairo-pdf
128
 * @Title: PDF Surfaces
129
 * @Short_Description: Rendering PDF documents
130
 * @See_Also: #cairo_surface_t
131
 *
132
 * The PDF surface is used to render cairo graphics to Adobe
133
 * PDF files and is a multi-page vector surface backend.
134
 *
135
 * The following mime types are supported: %CAIRO_MIME_TYPE_JPEG,
136
 * %CAIRO_MIME_TYPE_JP2, %CAIRO_MIME_TYPE_UNIQUE_ID,
137
 * %CAIRO_MIME_TYPE_JBIG2, %CAIRO_MIME_TYPE_JBIG2_GLOBAL,
138
 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
139
 * %CAIRO_MIME_TYPE_CCITT_FAX, %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS.
140
 *
141
 * # JBIG2 Images #
142
 * JBIG2 data in PDF must be in the embedded format as described in
143
 * ISO/IEC 11544. Image specific JBIG2 data must be in
144
 * %CAIRO_MIME_TYPE_JBIG2.  Any global segments in the JBIG2 data
145
 * (segments with page association field set to 0) must be in
146
 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data may be shared by
147
 * multiple images. All images sharing the same global data must set
148
 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID to a unique identifier. At least
149
 * one of the images must provide the global data using
150
 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data will only be
151
 * embedded once and shared by all JBIG2 images with the same
152
 * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
153
 *
154
 * # CCITT Fax Images # {#ccitt}
155
 * The %CAIRO_MIME_TYPE_CCITT_FAX mime data requires a number of decoding
156
 * parameters These parameters are specified using %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS.
157
 *
158
 * %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS mime data must contain a string of the form
159
 * "param1=value1 param2=value2 ...".
160
 *
161
 * @Columns: [required] An integer specifying the width of the image in pixels.
162
 *
163
 * @Rows: [required] An integer specifying the height of the image in scan lines.
164
 *
165
 * @K: [optional] An integer identifying the encoding scheme used. < 0
166
 * is 2 dimensional Group 4, = 0 is Group3 1 dimensional, > 0 is mixed 1
167
 * and 2 dimensional encoding. Default is 0.
168
 *
169
 * @EndOfLine: [optional] If true end-of-line bit patterns are present. Default is false.
170
 *
171
 * @EncodedByteAlign: [optional] If true the end of line is padded
172
 * with 0 bits so the next line begins on a byte boundary. Default is false.
173
 *
174
 * @EndOfBlock: [optional] If true the data contains an end-of-block pattern. Default is true.
175
 *
176
 * @BlackIs1: [optional] If true 1 bits are black pixels. Default is false.
177
 *
178
 * @DamagedRowsBeforeError: [optional] An integer specifying the
179
 * number of damages rows tolerated before an error occurs. Default is 0.
180
 *
181
 * Boolean values may be "true" or "false", or 1 or 0.
182
 *
183
 * These parameters are the same as the CCITTFaxDecode parameters in the
184
 * [PostScript Language Reference](https://www.adobe.com/products/postscript/pdfs/PLRM.pdf)
185
 * and [Portable Document Format (PDF)](https://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf).
186
 * Refer to these documents for further details.
187
 *
188
 * An example %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS string is:
189
 *
190
 * <programlisting>
191
 * "Columns=10230 Rows=40000 K=1 EndOfLine=true EncodedByteAlign=1 BlackIs1=false"
192
 * </programlisting>
193
 *
194
 **/
195
196
static cairo_bool_t
197
_cairo_pdf_surface_get_extents (void            *abstract_surface,
198
        cairo_rectangle_int_t   *rectangle);
199
200
/**
201
 * CAIRO_HAS_PDF_SURFACE:
202
 *
203
 * Defined if the PDF surface backend is available.
204
 * This macro can be used to conditionally compile backend-specific code.
205
 *
206
 * Since: 1.2
207
 **/
208
209
static const cairo_pdf_version_t _cairo_pdf_versions[] =
210
{
211
    CAIRO_PDF_VERSION_1_4,
212
    CAIRO_PDF_VERSION_1_5,
213
    CAIRO_PDF_VERSION_1_6,
214
    CAIRO_PDF_VERSION_1_7
215
};
216
217
0
#define CAIRO_PDF_VERSION_LAST ARRAY_LENGTH (_cairo_pdf_versions)
218
219
static const char * _cairo_pdf_version_strings[CAIRO_PDF_VERSION_LAST] =
220
{
221
    "PDF 1.4",
222
    "PDF 1.5"
223
    "PDF 1.6"
224
    "PDF 1.7"
225
};
226
227
static const char *_cairo_pdf_supported_mime_types[] =
228
{
229
    CAIRO_MIME_TYPE_JPEG,
230
    CAIRO_MIME_TYPE_JP2,
231
    CAIRO_MIME_TYPE_UNIQUE_ID,
232
    CAIRO_MIME_TYPE_JBIG2,
233
    CAIRO_MIME_TYPE_JBIG2_GLOBAL,
234
    CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
235
    CAIRO_MIME_TYPE_CCITT_FAX,
236
    CAIRO_MIME_TYPE_CCITT_FAX_PARAMS,
237
    NULL
238
};
239
240
/* PDF cross-reference stream types */
241
typedef enum {
242
    PDF_OBJECT_FREE = 0,
243
    PDF_OBJECT_UNCOMPRESSED = 1,
244
    PDF_OBJECT_COMPRESSED = 2,
245
} cairo_pdf_object_type_t;
246
247
typedef struct _cairo_pdf_object {
248
    cairo_pdf_object_type_t type;
249
    union {
250
  long long offset; /* type == PDF_OBJECT_UNCOMPRESSED */
251
  struct compressed_obj {  /* type == PDF_OBJECT_COMPRESSED */
252
      cairo_pdf_resource_t xref_stream;
253
      int index;
254
  } compressed_obj;
255
    } u;
256
} cairo_pdf_object_t;
257
258
typedef struct _cairo_xref_stream_object {
259
    cairo_pdf_resource_t resource;
260
    long long offset;
261
} cairo_xref_stream_object_t;
262
263
typedef struct _cairo_pdf_font {
264
    unsigned int font_id;
265
    unsigned int subset_id;
266
    cairo_pdf_resource_t subset_resource;
267
} cairo_pdf_font_t;
268
269
typedef struct _cairo_pdf_rgb_linear_function {
270
    cairo_pdf_resource_t resource;
271
    double               color1[3];
272
    double               color2[3];
273
} cairo_pdf_rgb_linear_function_t;
274
275
typedef struct _cairo_pdf_alpha_linear_function {
276
    cairo_pdf_resource_t resource;
277
    double               alpha1;
278
    double               alpha2;
279
} cairo_pdf_alpha_linear_function_t;
280
281
static void
282
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
283
284
static void
285
_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
286
287
static cairo_int_status_t
288
_cairo_pdf_surface_add_font (unsigned int        font_id,
289
           unsigned int        subset_id,
290
           void   *closure);
291
292
static void
293
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
294
295
static cairo_int_status_t
296
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
297
        cairo_pdf_resource_t    *resource,
298
                                cairo_bool_t             compressed,
299
        const char    *fmt,
300
        ...) CAIRO_PRINTF_FORMAT(4, 5);
301
static cairo_int_status_t
302
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t  *surface);
303
304
static cairo_int_status_t
305
_cairo_pdf_surface_emit_surface (cairo_pdf_surface_t        *surface,
306
         cairo_pdf_source_surface_t *source,
307
         cairo_bool_t                test,
308
         cairo_bool_t               *is_image);
309
310
static cairo_int_status_t
311
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
312
313
static cairo_int_status_t
314
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
315
316
static cairo_int_status_t
317
_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface,
318
          cairo_pdf_resource_t catalog);
319
320
static long long
321
_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
322
323
static cairo_int_status_t
324
_cairo_pdf_surface_write_xref_stream (cairo_pdf_surface_t  *surface,
325
              cairo_pdf_resource_t  xref_res,
326
              cairo_pdf_resource_t  root_res,
327
              cairo_pdf_resource_t  info_res,
328
              long long            *xref_offset);
329
330
static cairo_int_status_t
331
_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface,
332
                cairo_bool_t         finish);
333
334
static cairo_int_status_t
335
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
336
337
static cairo_bool_t
338
_cairo_pdf_source_surface_equal (const void *key_a, const void *key_b);
339
340
static const cairo_surface_backend_t cairo_pdf_surface_backend;
341
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
342
343
cairo_pdf_resource_t
344
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
345
24
{
346
24
    cairo_pdf_resource_t resource;
347
24
    cairo_int_status_t status;
348
24
    cairo_pdf_object_t object;
349
350
    /* Default to Uncompressed. If this object is used with
351
     * _cairo_pdf_surface_object_begin() and Object Streams are
352
     * enabled it will be changed to Compressed. */
353
24
    object.type = PDF_OBJECT_UNCOMPRESSED;
354
24
    object.u.offset = _cairo_output_stream_get_position (surface->output);
355
356
24
    status = _cairo_array_append (&surface->objects, &object);
357
24
    if (unlikely (status)) {
358
0
  resource.id = 0;
359
0
  return resource;
360
0
    }
361
362
24
    resource = surface->next_available_resource;
363
24
    surface->next_available_resource.id++;
364
365
24
    return resource;
366
24
}
367
368
void
369
_cairo_pdf_surface_update_object (cairo_pdf_surface_t *surface,
370
          cairo_pdf_resource_t   resource)
371
14
{
372
14
    cairo_pdf_object_t *object;
373
374
14
    object = _cairo_array_index (&surface->objects, resource.id - 1);
375
14
    object->u.offset = _cairo_output_stream_get_position (surface->output);
376
14
}
377
378
static void
379
_cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
380
              double      width,
381
              double      height)
382
0
{
383
0
    surface->width = width;
384
0
    surface->height = height;
385
0
    surface->surface_extents.x = 0;
386
0
    surface->surface_extents.y = 0;
387
0
    surface->surface_extents.width  = ceil (surface->width);
388
0
    surface->surface_extents.height = ceil (surface->height);
389
0
}
390
391
static cairo_bool_t
392
_path_covers_bbox (cairo_pdf_surface_t *surface,
393
       cairo_path_fixed_t *path)
394
0
{
395
0
    cairo_box_t box;
396
397
0
    return _cairo_path_fixed_is_box (path, &box) &&
398
0
     box.p1.x <= 0 &&
399
0
     box.p1.y <= 0 &&
400
0
     box.p2.x >= _cairo_fixed_from_double (surface->width) &&
401
0
     box.p2.y >= _cairo_fixed_from_double (surface->height);
402
0
}
403
404
static cairo_status_t
405
_cairo_pdf_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
406
            cairo_path_fixed_t  *path,
407
            cairo_fill_rule_t fill_rule,
408
            double      tolerance,
409
            cairo_antialias_t antialias)
410
0
{
411
0
    cairo_pdf_surface_t *surface = cairo_container_of (clipper,
412
0
                   cairo_pdf_surface_t,
413
0
                   clipper);
414
0
    cairo_int_status_t status;
415
416
0
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
417
0
    if (unlikely (status))
418
0
  return status;
419
420
0
    if (path == NULL) {
421
0
  _cairo_output_stream_printf (surface->output, "Q q\n");
422
423
0
  surface->current_pattern_is_solid_color = FALSE;
424
0
  _cairo_pdf_operators_reset (&surface->pdf_operators);
425
426
0
  return CAIRO_STATUS_SUCCESS;
427
0
    }
428
429
0
    if (_path_covers_bbox (surface, path))
430
0
  return CAIRO_STATUS_SUCCESS;
431
432
0
    return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
433
0
}
434
435
static cairo_surface_t *
436
_cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t  *output,
437
                 double      width,
438
                 double      height)
439
2
{
440
2
    cairo_pdf_surface_t *surface;
441
2
    cairo_status_t status, status_ignored;
442
443
2
    surface = _cairo_malloc (sizeof (cairo_pdf_surface_t));
444
2
    if (unlikely (surface == NULL)) {
445
  /* destroy stream on behalf of caller */
446
0
  status = _cairo_output_stream_destroy (output);
447
0
  return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
448
0
    }
449
450
2
    _cairo_surface_init (&surface->base,
451
2
       &cairo_pdf_surface_backend,
452
2
       NULL, /* device */
453
2
       CAIRO_CONTENT_COLOR_ALPHA,
454
2
       TRUE); /* is_vector */
455
456
2
    surface->output = output;
457
2
    surface->width = width;
458
2
    surface->height = height;
459
2
    cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, 1, 0, 0);
460
2
    surface->in_xobject = FALSE;
461
2
    surface->surface_extents.x = 0;
462
2
    surface->surface_extents.y = 0;
463
2
    surface->surface_extents.width  = ceil (surface->width);
464
2
    surface->surface_extents.height = ceil (surface->height);
465
2
    surface->surface_bounded = TRUE;
466
467
2
    _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
468
2
    _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
469
2
    _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
470
2
    _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
471
2
    _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
472
2
    _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
473
2
    _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t));
474
475
2
    _cairo_array_init (&surface->page_patterns, sizeof (cairo_pdf_pattern_t));
476
2
    _cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t));
477
2
    _cairo_array_init (&surface->doc_surfaces, sizeof (cairo_pdf_source_surface_t));
478
2
    _cairo_array_init (&surface->jbig2_global, sizeof (cairo_pdf_jbig2_global_t));
479
2
    _cairo_array_init (&surface->page_heights, sizeof (double));
480
2
    surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal);
481
2
    if (unlikely (surface->all_surfaces == NULL)) {
482
0
  status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
483
0
  goto BAIL0;
484
0
    }
485
486
2
    _cairo_pdf_group_resources_init (&surface->resources);
487
488
2
    surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
489
2
    if (! surface->font_subsets) {
490
0
  status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
491
0
  goto BAIL1;
492
0
    }
493
494
2
    _cairo_scaled_font_subsets_enable_latin_subset (surface->font_subsets, TRUE);
495
496
2
    surface->next_available_resource.id = 1;
497
2
    surface->pages_resource = _cairo_pdf_surface_new_object (surface);
498
2
    if (surface->pages_resource.id == 0) {
499
0
  status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
500
0
        goto BAIL2;
501
0
    }
502
503
2
    surface->struct_tree_root.id = 0;
504
2
    surface->pdf_version = CAIRO_PDF_VERSION_1_7;
505
2
    surface->compress_streams = TRUE;
506
2
    surface->pdf_stream.active = FALSE;
507
2
    surface->pdf_stream.old_output = NULL;
508
2
    surface->group_stream.active = FALSE;
509
2
    surface->group_stream.stream = NULL;
510
2
    surface->group_stream.mem_stream = NULL;
511
2
    surface->object_stream.active = FALSE;
512
2
    surface->object_stream.stream = NULL;
513
2
    _cairo_array_init (&surface->object_stream.objects, sizeof (cairo_xref_stream_object_t));
514
515
2
    surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
516
517
2
    surface->force_fallbacks = FALSE;
518
2
    surface->select_pattern_gstate_saved = FALSE;
519
2
    surface->current_pattern_is_solid_color = FALSE;
520
2
    surface->current_operator = CAIRO_OPERATOR_OVER;
521
2
    surface->header_emitted = FALSE;
522
523
2
    _cairo_surface_clipper_init (&surface->clipper,
524
2
         _cairo_pdf_surface_clipper_intersect_clip_path);
525
526
2
    _cairo_pdf_operators_init (&surface->pdf_operators,
527
2
             surface->output,
528
2
             &surface->cairo_to_pdf,
529
2
             surface->font_subsets,
530
2
             FALSE);
531
2
    _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
532
2
                _cairo_pdf_surface_add_font,
533
2
                surface);
534
2
    _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators, TRUE);
535
536
2
    status = _cairo_pdf_interchange_init (surface);
537
2
    if (unlikely (status))
538
0
  goto BAIL2;
539
540
2
    surface->page_parent_tree = -1;
541
2
    _cairo_array_init (&surface->page_annots, sizeof (cairo_pdf_resource_t));
542
2
    _cairo_array_init (&surface->forward_links, sizeof (cairo_pdf_forward_link_t));
543
2
    surface->tagged = FALSE;
544
2
    surface->current_page_label = NULL;
545
2
    _cairo_array_init (&surface->page_labels, sizeof (char *));
546
2
    surface->outlines_dict_res.id = 0;
547
2
    surface->names_dict_res.id = 0;
548
2
    surface->docinfo_res.id = 0;
549
2
    surface->page_labels_res.id = 0;
550
2
    surface->thumbnail_width = 0;
551
2
    surface->thumbnail_height = 0;
552
2
    surface->thumbnail_image = NULL;
553
554
2
    if (getenv ("CAIRO_DEBUG_PDF") != NULL)
555
0
  surface->compress_streams = FALSE;
556
557
2
    surface->paginated_surface =  _cairo_paginated_surface_create (
558
2
                                    &surface->base,
559
2
            CAIRO_CONTENT_COLOR_ALPHA,
560
2
            &cairo_pdf_surface_paginated_backend);
561
562
2
    status = surface->paginated_surface->status;
563
2
    if (status == CAIRO_STATUS_SUCCESS) {
564
  /* paginated keeps the only reference to surface now, drop ours */
565
2
  cairo_surface_destroy (&surface->base);
566
2
  return surface->paginated_surface;
567
2
    }
568
569
0
BAIL2:
570
0
    _cairo_scaled_font_subsets_destroy (surface->font_subsets);
571
0
BAIL1:
572
0
    _cairo_hash_table_destroy (surface->all_surfaces);
573
0
BAIL0:
574
0
    _cairo_array_fini (&surface->objects);
575
0
    free (surface);
576
577
    /* destroy stream on behalf of caller */
578
0
    status_ignored = _cairo_output_stream_destroy (output);
579
580
0
    return _cairo_surface_create_in_error (status);
581
0
}
582
583
/**
584
 * cairo_pdf_surface_create_for_stream:
585
 * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
586
 *              to indicate a no-op @write_func. With a no-op @write_func,
587
 *              the surface may be queried or used as a source without
588
 *              generating any temporary files.
589
 * @closure: the closure argument for @write_func
590
 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
591
 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
592
 *
593
 * Creates a PDF surface of the specified size in points to be written
594
 * incrementally to the stream represented by @write_func and @closure.
595
 *
596
 * Return value: a pointer to the newly created surface. The caller
597
 * owns the surface and should call cairo_surface_destroy() when done
598
 * with it.
599
 *
600
 * This function always returns a valid pointer, but it will return a
601
 * pointer to a "nil" surface if an error such as out of memory
602
 * occurs. You can use cairo_surface_status() to check for this.
603
 *
604
 * Since: 1.2
605
 **/
606
cairo_surface_t *
607
cairo_pdf_surface_create_for_stream (cairo_write_func_t    write_func,
608
             void     *closure,
609
             double      width_in_points,
610
             double      height_in_points)
611
0
{
612
0
    cairo_output_stream_t *output;
613
614
0
    output = _cairo_output_stream_create (write_func, NULL, closure);
615
0
    if (_cairo_output_stream_get_status (output))
616
0
  return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
617
618
0
    return _cairo_pdf_surface_create_for_stream_internal (output,
619
0
                width_in_points,
620
0
                height_in_points);
621
0
}
622
623
/**
624
 * cairo_pdf_surface_create:
625
 * @filename: a filename for the PDF output (must be writable), %NULL may be
626
 *            used to specify no output. This will generate a PDF surface that
627
 *            may be queried and used as a source, without generating a
628
 *            temporary file.
629
 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
630
 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
631
 *
632
 * Creates a PDF surface of the specified size in points to be written
633
 * to @filename.
634
 *
635
 * Return value: a pointer to the newly created surface. The caller
636
 * owns the surface and should call cairo_surface_destroy() when done
637
 * with it.
638
 *
639
 * This function always returns a valid pointer, but it will return a
640
 * pointer to a "nil" surface if an error such as out of memory
641
 * occurs. You can use cairo_surface_status() to check for this.
642
 *
643
 * Since: 1.2
644
 **/
645
cairo_surface_t *
646
cairo_pdf_surface_create (const char    *filename,
647
        double     width_in_points,
648
        double     height_in_points)
649
2
{
650
2
    cairo_output_stream_t *output;
651
652
2
    output = _cairo_output_stream_create_for_filename (filename);
653
2
    if (_cairo_output_stream_get_status (output))
654
0
  return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
655
656
2
    return _cairo_pdf_surface_create_for_stream_internal (output,
657
2
                width_in_points,
658
2
                height_in_points);
659
2
}
660
661
static cairo_bool_t
662
_cairo_surface_is_pdf (cairo_surface_t *surface)
663
0
{
664
0
    return surface->backend == &cairo_pdf_surface_backend;
665
0
}
666
667
/* If the abstract_surface is a paginated surface, and that paginated
668
 * surface's target is a pdf_surface, then set pdf_surface to that
669
 * target. Otherwise return FALSE.
670
 */
671
static cairo_bool_t
672
_extract_pdf_surface (cairo_surface_t    *surface,
673
          cairo_pdf_surface_t **pdf_surface)
674
0
{
675
0
    cairo_surface_t *target;
676
0
    cairo_status_t status_ignored;
677
678
0
    if (surface->status)
679
0
  return FALSE;
680
0
    if (surface->finished) {
681
0
  status_ignored = _cairo_surface_set_error (surface,
682
0
               _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
683
0
        return FALSE;
684
0
    }
685
686
0
    if (! _cairo_surface_is_paginated (surface)) {
687
0
  status_ignored = _cairo_surface_set_error (surface,
688
0
               _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
689
0
  return FALSE;
690
0
    }
691
692
0
    target = _cairo_paginated_surface_get_target (surface);
693
0
    if (target->status) {
694
0
  status_ignored = _cairo_surface_set_error (surface,
695
0
               target->status);
696
0
  return FALSE;
697
0
    }
698
0
    if (target->finished) {
699
0
  status_ignored = _cairo_surface_set_error (surface,
700
0
               _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
701
0
  return FALSE;
702
0
    }
703
704
0
    if (! _cairo_surface_is_pdf (target)) {
705
0
  status_ignored = _cairo_surface_set_error (surface,
706
0
               _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
707
0
  return FALSE;
708
0
    }
709
710
0
    *pdf_surface = (cairo_pdf_surface_t *) target;
711
0
    return TRUE;
712
0
}
713
714
/**
715
 * cairo_pdf_surface_restrict_to_version:
716
 * @surface: a PDF #cairo_surface_t
717
 * @version: PDF version
718
 *
719
 * Restricts the generated PDF file to @version. See cairo_pdf_get_versions()
720
 * for a list of available version values that can be used here.
721
 *
722
 * This function should only be called before any drawing operations
723
 * have been performed on the given surface. The simplest way to do
724
 * this is to call this function immediately after creating the
725
 * surface.
726
 *
727
 * Since: 1.10
728
 **/
729
void
730
cairo_pdf_surface_restrict_to_version (cairo_surface_t    *abstract_surface,
731
               cairo_pdf_version_t     version)
732
0
{
733
0
    cairo_pdf_surface_t *surface = NULL; /* hide compiler warning */
734
735
0
    if (! _extract_pdf_surface (abstract_surface, &surface))
736
0
  return;
737
738
0
    if (version < CAIRO_PDF_VERSION_LAST)
739
0
  surface->pdf_version = version;
740
741
0
    _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators,
742
0
              version >= CAIRO_PDF_VERSION_1_5);
743
0
}
744
745
/**
746
 * cairo_pdf_get_versions:
747
 * @versions: supported version list
748
 * @num_versions: list length
749
 *
750
 * Used to retrieve the list of supported versions. See
751
 * cairo_pdf_surface_restrict_to_version().
752
 *
753
 * Since: 1.10
754
 **/
755
void
756
cairo_pdf_get_versions (cairo_pdf_version_t const **versions,
757
                        int                        *num_versions)
758
0
{
759
0
    if (versions != NULL)
760
0
  *versions = _cairo_pdf_versions;
761
762
0
    if (num_versions != NULL)
763
0
  *num_versions = CAIRO_PDF_VERSION_LAST;
764
0
}
765
766
/**
767
 * cairo_pdf_version_to_string:
768
 * @version: a version id
769
 *
770
 * Get the string representation of the given @version id. This function
771
 * will return %NULL if @version isn't valid. See cairo_pdf_get_versions()
772
 * for a way to get the list of valid version ids.
773
 *
774
 * Return value: the string associated to given version.
775
 *
776
 * Since: 1.10
777
 **/
778
const char *
779
cairo_pdf_version_to_string (cairo_pdf_version_t version)
780
0
{
781
0
    if (version >= CAIRO_PDF_VERSION_LAST)
782
0
  return NULL;
783
784
0
    return _cairo_pdf_version_strings[version];
785
0
}
786
787
/**
788
 * cairo_pdf_surface_set_size:
789
 * @surface: a PDF #cairo_surface_t
790
 * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
791
 * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
792
 *
793
 * Changes the size of a PDF surface for the current (and
794
 * subsequent) pages.
795
 *
796
 * This function should only be called before any drawing operations
797
 * have been performed on the current page. The simplest way to do
798
 * this is to call this function immediately after creating the
799
 * surface or immediately after completing a page with either
800
 * cairo_show_page() or cairo_copy_page().
801
 *
802
 * Since: 1.2
803
 **/
804
void
805
cairo_pdf_surface_set_size (cairo_surface_t *surface,
806
          double     width_in_points,
807
          double     height_in_points)
808
0
{
809
0
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
810
0
    cairo_status_t status;
811
812
0
    if (! _extract_pdf_surface (surface, &pdf_surface))
813
0
  return;
814
815
0
    _cairo_pdf_surface_set_size_internal (pdf_surface,
816
0
            width_in_points,
817
0
            height_in_points);
818
0
    status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
819
0
            width_in_points,
820
0
            height_in_points);
821
0
    if (status)
822
0
  status = _cairo_surface_set_error (surface, status);
823
0
}
824
825
/**
826
 * CAIRO_PDF_OUTLINE_ROOT:
827
 *
828
 * The root outline item in cairo_pdf_surface_add_outline().
829
 *
830
 * Since: 1.16
831
 **/
832
833
/**
834
 * cairo_pdf_surface_add_outline:
835
 * @surface: a PDF #cairo_surface_t
836
 * @parent_id: the id of the parent item or %CAIRO_PDF_OUTLINE_ROOT if this is a top level item.
837
 * @utf8: the name of the outline
838
 * @link_attribs: the link attributes specifying where this outline links to
839
 * @flags: outline item flags
840
 *
841
 * Add an item to the document outline hierarchy with the name @utf8
842
 * that links to the location specified by @link_attribs. Link
843
 * attributes have the same keys and values as the [Link Tag][link],
844
 * excluding the "rect" attribute. The item will be a child of the
845
 * item with id @parent_id. Use %CAIRO_PDF_OUTLINE_ROOT as the parent
846
 * id of top level items.
847
 *
848
 * Return value: the id for the added item.
849
 *
850
 * Since: 1.16
851
 **/
852
int
853
cairo_pdf_surface_add_outline (cairo_surface_t           *surface,
854
             int                        parent_id,
855
             const char                *utf8,
856
             const char                *link_attribs,
857
             cairo_pdf_outline_flags_t  flags)
858
0
{
859
0
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
860
0
    cairo_status_t status;
861
0
    int id = 0;
862
863
0
    if (! _extract_pdf_surface (surface, &pdf_surface))
864
0
  return 0;
865
866
0
    status = _cairo_pdf_interchange_add_outline (pdf_surface,
867
0
             parent_id,
868
0
             utf8,
869
0
             link_attribs,
870
0
             flags,
871
0
             &id);
872
0
    if (status)
873
0
  status = _cairo_surface_set_error (surface, status);
874
875
0
    return id;
876
0
}
877
878
/**
879
 * cairo_pdf_surface_set_metadata:
880
 * @surface: a PDF #cairo_surface_t
881
 * @metadata: The metadata item to set.
882
 * @utf8: metadata value
883
 *
884
 * Set document metadata. The %CAIRO_PDF_METADATA_CREATE_DATE and
885
 * %CAIRO_PDF_METADATA_MOD_DATE values must be in ISO-8601 format:
886
 * YYYY-MM-DDThh:mm:ss. An optional timezone of the form "[+/-]hh:mm"
887
 * or "Z" for UTC time can be appended. All other metadata values can be any UTF-8
888
 * string.
889
 *
890
 * For example:
891
 * <informalexample><programlisting>
892
 * cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_TITLE, "My Document");
893
 * cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_CREATE_DATE, "2015-12-31T23:59+02:00");
894
 * </programlisting></informalexample>
895
 *
896
 * Since: 1.16
897
 **/
898
void
899
cairo_pdf_surface_set_metadata (cairo_surface_t      *surface,
900
        cairo_pdf_metadata_t  metadata,
901
                                const char           *utf8)
902
0
{
903
0
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
904
0
    cairo_status_t status;
905
906
0
    if (! _extract_pdf_surface (surface, &pdf_surface))
907
0
  return;
908
909
0
    status = _cairo_pdf_interchange_set_metadata (pdf_surface, metadata, utf8);
910
0
    if (status)
911
0
  status = _cairo_surface_set_error (surface, status);
912
0
}
913
914
/**
915
 * cairo_pdf_surface_set_custom_metadata:
916
 * @surface: a PDF #cairo_surface_t
917
 * @name: The name of the custom metadata item to set (utf8).
918
 * @value: The value of the metadata (utf8).
919
 *
920
 * Set custom document metadata. @name may be any string except for
921
 * the following names reserved by PDF: "Title", "Author", "Subject",
922
 * "Keywords", "Creator", "Producer", "CreationDate", "ModDate",
923
 * "Trapped".
924
 *
925
 * If @value is NULL or an empty string, the @name metadata will not be set.
926
 *
927
 * For example:
928
 * <informalexample><programlisting>
929
 * cairo_pdf_surface_set_custom_metadata (surface, "ISBN", "978-0123456789");
930
 * </programlisting></informalexample>
931
 *
932
 * Since: 1.18
933
 **/
934
void
935
cairo_pdf_surface_set_custom_metadata (cairo_surface_t      *surface,
936
                                       const char           *name,
937
                                       const char           *value)
938
0
{
939
0
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
940
0
    cairo_status_t status;
941
942
0
    if (! _extract_pdf_surface (surface, &pdf_surface))
943
0
  return;
944
945
0
    status = _cairo_pdf_interchange_set_custom_metadata (pdf_surface, name, value);
946
0
    if (status)
947
0
  status = _cairo_surface_set_error (surface, status);
948
0
}
949
950
/**
951
 * cairo_pdf_surface_set_page_label:
952
 * @surface: a PDF #cairo_surface_t
953
 * @utf8: The page label.
954
 *
955
 * Set page label for the current page.
956
 *
957
 * Since: 1.16
958
 **/
959
void
960
cairo_pdf_surface_set_page_label (cairo_surface_t *surface,
961
                                  const char      *utf8)
962
0
{
963
0
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
964
965
0
    if (! _extract_pdf_surface (surface, &pdf_surface))
966
0
  return;
967
968
0
    free (pdf_surface->current_page_label);
969
0
    pdf_surface->current_page_label = utf8 ? strdup (utf8) : NULL;
970
0
}
971
972
/**
973
 * cairo_pdf_surface_set_thumbnail_size:
974
 * @surface: a PDF #cairo_surface_t
975
 * @width: Thumbnail width.
976
 * @height: Thumbnail height
977
 *
978
 * Set the thumbnail image size for the current and all subsequent
979
 * pages. Setting a width or height of 0 disables thumbnails for the
980
 * current and subsequent pages.
981
 *
982
 * Since: 1.16
983
 **/
984
void
985
cairo_pdf_surface_set_thumbnail_size (cairo_surface_t *surface,
986
              int              width,
987
              int              height)
988
0
{
989
0
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
990
991
0
    if (! _extract_pdf_surface (surface, &pdf_surface))
992
0
  return;
993
994
0
    pdf_surface->thumbnail_width = width;
995
0
    pdf_surface->thumbnail_height = height;
996
0
}
997
998
static void
999
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
1000
4
{
1001
4
    int i, size;
1002
4
    cairo_pdf_pattern_t *pattern;
1003
4
    cairo_pdf_source_surface_t *src_surface;
1004
4
    cairo_pdf_smask_group_t *group;
1005
1006
4
    size = _cairo_array_num_elements (&surface->page_patterns);
1007
4
    for (i = 0; i < size; i++) {
1008
0
  pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->page_patterns, i);
1009
0
  cairo_pattern_destroy (pattern->pattern);
1010
0
    }
1011
4
    _cairo_array_truncate (&surface->page_patterns, 0);
1012
1013
4
    size = _cairo_array_num_elements (&surface->page_surfaces);
1014
4
    for (i = 0; i < size; i++) {
1015
0
  src_surface = (cairo_pdf_source_surface_t *) _cairo_array_index (&surface->page_surfaces, i);
1016
0
  cairo_surface_destroy (src_surface->surface);
1017
0
    }
1018
4
    _cairo_array_truncate (&surface->page_surfaces, 0);
1019
1020
4
    size = _cairo_array_num_elements (&surface->smask_groups);
1021
4
    for (i = 0; i < size; i++) {
1022
0
  _cairo_array_copy_element (&surface->smask_groups, i, &group);
1023
0
  _cairo_pdf_smask_group_destroy (group);
1024
0
    }
1025
4
    _cairo_array_truncate (&surface->smask_groups, 0);
1026
4
    _cairo_array_truncate (&surface->knockout_group, 0);
1027
4
    _cairo_array_truncate (&surface->page_annots, 0);
1028
1029
4
    if (surface->thumbnail_image)
1030
0
  cairo_surface_destroy (&surface->thumbnail_image->base);
1031
4
    surface->thumbnail_image = NULL;
1032
4
}
1033
1034
static void
1035
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
1036
2
{
1037
2
    int i;
1038
1039
60
    for (i = 0; i < CAIRO_NUM_OPERATORS; i++)
1040
58
  res->operators[i] = FALSE;
1041
1042
2
    _cairo_array_init (&res->alphas, sizeof (double));
1043
2
    _cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t));
1044
2
    _cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t));
1045
2
    _cairo_array_init (&res->shadings, sizeof (cairo_pdf_resource_t));
1046
2
    _cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t));
1047
2
    _cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t));
1048
2
}
1049
1050
static void
1051
_cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
1052
2
{
1053
2
    _cairo_array_fini (&res->alphas);
1054
2
    _cairo_array_fini (&res->smasks);
1055
2
    _cairo_array_fini (&res->patterns);
1056
2
    _cairo_array_fini (&res->shadings);
1057
2
    _cairo_array_fini (&res->xobjects);
1058
2
    _cairo_array_fini (&res->fonts);
1059
2
}
1060
1061
static void
1062
_cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
1063
4
{
1064
4
    int i;
1065
1066
120
    for (i = 0; i < CAIRO_NUM_OPERATORS; i++)
1067
116
  res->operators[i] = FALSE;
1068
1069
4
    _cairo_array_truncate (&res->alphas, 0);
1070
4
    _cairo_array_truncate (&res->smasks, 0);
1071
4
    _cairo_array_truncate (&res->patterns, 0);
1072
4
    _cairo_array_truncate (&res->shadings, 0);
1073
4
    _cairo_array_truncate (&res->xobjects, 0);
1074
4
    _cairo_array_truncate (&res->fonts, 0);
1075
4
}
1076
1077
static void
1078
_cairo_pdf_surface_add_operator (cairo_pdf_surface_t *surface,
1079
         cairo_operator_t     op)
1080
0
{
1081
0
    cairo_pdf_group_resources_t *res = &surface->resources;
1082
1083
0
    res->operators[op] = TRUE;
1084
0
}
1085
1086
static cairo_int_status_t
1087
_cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
1088
            double               alpha,
1089
            int                 *index)
1090
0
{
1091
0
    int num_alphas, i;
1092
0
    double other;
1093
0
    cairo_int_status_t status;
1094
0
    cairo_pdf_group_resources_t *res = &surface->resources;
1095
1096
0
    num_alphas = _cairo_array_num_elements (&res->alphas);
1097
0
    for (i = 0; i < num_alphas; i++) {
1098
0
  _cairo_array_copy_element (&res->alphas, i, &other);
1099
0
  if (alpha == other) {
1100
0
      *index = i;
1101
0
      return CAIRO_STATUS_SUCCESS;
1102
0
  }
1103
0
    }
1104
1105
0
    status = _cairo_array_append (&res->alphas, &alpha);
1106
0
    if (unlikely (status))
1107
0
  return status;
1108
1109
0
    *index = _cairo_array_num_elements (&res->alphas) - 1;
1110
1111
0
    return CAIRO_STATUS_SUCCESS;
1112
0
}
1113
1114
static cairo_int_status_t
1115
_cairo_pdf_surface_add_smask (cairo_pdf_surface_t  *surface,
1116
            cairo_pdf_resource_t  smask)
1117
0
{
1118
0
    return _cairo_array_append (&(surface->resources.smasks), &smask);
1119
0
}
1120
1121
static cairo_int_status_t
1122
_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t  *surface,
1123
        cairo_pdf_resource_t  pattern)
1124
0
{
1125
0
    return _cairo_array_append (&(surface->resources.patterns), &pattern);
1126
0
}
1127
1128
static cairo_int_status_t
1129
_cairo_pdf_surface_add_shading (cairo_pdf_surface_t  *surface,
1130
        cairo_pdf_resource_t  shading)
1131
0
{
1132
0
    return _cairo_array_append (&(surface->resources.shadings), &shading);
1133
0
}
1134
1135
1136
static cairo_int_status_t
1137
_cairo_pdf_surface_add_xobject (cairo_pdf_surface_t  *surface,
1138
        cairo_pdf_resource_t  xobject)
1139
0
{
1140
0
    return _cairo_array_append (&(surface->resources.xobjects), &xobject);
1141
0
}
1142
1143
static cairo_int_status_t
1144
_cairo_pdf_surface_add_font (unsigned int        font_id,
1145
           unsigned int        subset_id,
1146
           void   *closure)
1147
0
{
1148
0
    cairo_pdf_surface_t *surface = closure;
1149
0
    cairo_pdf_font_t font;
1150
0
    int num_fonts, i;
1151
0
    cairo_int_status_t status;
1152
0
    cairo_pdf_group_resources_t *res = &surface->resources;
1153
1154
0
    num_fonts = _cairo_array_num_elements (&res->fonts);
1155
0
    for (i = 0; i < num_fonts; i++) {
1156
0
  _cairo_array_copy_element (&res->fonts, i, &font);
1157
0
  if (font.font_id == font_id &&
1158
0
      font.subset_id == subset_id)
1159
0
      return CAIRO_STATUS_SUCCESS;
1160
0
    }
1161
1162
0
    num_fonts = _cairo_array_num_elements (&surface->fonts);
1163
0
    for (i = 0; i < num_fonts; i++) {
1164
0
  _cairo_array_copy_element (&surface->fonts, i, &font);
1165
0
  if (font.font_id == font_id &&
1166
0
      font.subset_id == subset_id)
1167
0
      return _cairo_array_append (&res->fonts, &font);
1168
0
    }
1169
1170
0
    font.font_id = font_id;
1171
0
    font.subset_id = subset_id;
1172
0
    font.subset_resource = _cairo_pdf_surface_new_object (surface);
1173
0
    if (font.subset_resource.id == 0)
1174
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1175
1176
0
    status = _cairo_array_append (&surface->fonts, &font);
1177
0
    if (unlikely (status))
1178
0
  return status;
1179
1180
0
    return _cairo_array_append (&res->fonts, &font);
1181
0
}
1182
1183
static cairo_pdf_resource_t
1184
_cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface,
1185
              unsigned int         font_id,
1186
              unsigned int         subset_id)
1187
0
{
1188
0
    cairo_pdf_font_t font;
1189
0
    int num_fonts, i;
1190
1191
0
    num_fonts = _cairo_array_num_elements (&surface->fonts);
1192
0
    for (i = 0; i < num_fonts; i++) {
1193
0
  _cairo_array_copy_element (&surface->fonts, i, &font);
1194
0
  if (font.font_id == font_id && font.subset_id == subset_id)
1195
0
      return font.subset_resource;
1196
0
    }
1197
1198
0
    font.subset_resource.id = 0;
1199
0
    return font.subset_resource;
1200
0
}
1201
1202
static const char *
1203
_cairo_operator_to_pdf_blend_mode (cairo_operator_t op)
1204
0
{
1205
0
    switch (op) {
1206
    /* The extend blend mode operators */
1207
0
    case CAIRO_OPERATOR_MULTIPLY:       return "Multiply";
1208
0
    case CAIRO_OPERATOR_SCREEN:         return "Screen";
1209
0
    case CAIRO_OPERATOR_OVERLAY:        return "Overlay";
1210
0
    case CAIRO_OPERATOR_DARKEN:         return "Darken";
1211
0
    case CAIRO_OPERATOR_LIGHTEN:        return "Lighten";
1212
0
    case CAIRO_OPERATOR_COLOR_DODGE:    return "ColorDodge";
1213
0
    case CAIRO_OPERATOR_COLOR_BURN:     return "ColorBurn";
1214
0
    case CAIRO_OPERATOR_HARD_LIGHT:     return "HardLight";
1215
0
    case CAIRO_OPERATOR_SOFT_LIGHT:     return "SoftLight";
1216
0
    case CAIRO_OPERATOR_DIFFERENCE:     return "Difference";
1217
0
    case CAIRO_OPERATOR_EXCLUSION:      return "Exclusion";
1218
0
    case CAIRO_OPERATOR_HSL_HUE:        return "Hue";
1219
0
    case CAIRO_OPERATOR_HSL_SATURATION: return "Saturation";
1220
0
    case CAIRO_OPERATOR_HSL_COLOR:      return "Color";
1221
0
    case CAIRO_OPERATOR_HSL_LUMINOSITY: return "Luminosity";
1222
1223
0
    default:
1224
    /* The original Porter-Duff set */
1225
0
    case CAIRO_OPERATOR_CLEAR:
1226
0
    case CAIRO_OPERATOR_SOURCE:
1227
0
    case CAIRO_OPERATOR_OVER:
1228
0
    case CAIRO_OPERATOR_IN:
1229
0
    case CAIRO_OPERATOR_OUT:
1230
0
    case CAIRO_OPERATOR_ATOP:
1231
0
    case CAIRO_OPERATOR_DEST:
1232
0
    case CAIRO_OPERATOR_DEST_OVER:
1233
0
    case CAIRO_OPERATOR_DEST_IN:
1234
0
    case CAIRO_OPERATOR_DEST_OUT:
1235
0
    case CAIRO_OPERATOR_DEST_ATOP:
1236
0
    case CAIRO_OPERATOR_XOR:
1237
0
    case CAIRO_OPERATOR_ADD:
1238
0
    case CAIRO_OPERATOR_SATURATE:
1239
0
  return "Normal";
1240
0
    }
1241
0
}
1242
1243
static void
1244
_cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t         *surface,
1245
           cairo_pdf_group_resources_t *res)
1246
2
{
1247
2
    int num_alphas, num_smasks, num_resources, i;
1248
2
    double alpha;
1249
2
    cairo_pdf_resource_t *smask, *pattern, *shading, *xobject;
1250
2
    cairo_pdf_font_t *font;
1251
1252
2
    _cairo_output_stream_printf (surface->output, "<<\n");
1253
1254
2
    num_alphas = _cairo_array_num_elements (&res->alphas);
1255
2
    num_smasks = _cairo_array_num_elements (&res->smasks);
1256
2
    if (num_alphas > 0 || num_smasks > 0) {
1257
0
  _cairo_output_stream_printf (surface->output,
1258
0
             "   /ExtGState <<\n");
1259
1260
0
  for (i = 0; i < CAIRO_NUM_OPERATORS; i++) {
1261
0
      if (res->operators[i]) {
1262
0
    _cairo_output_stream_printf (surface->output,
1263
0
               "      /b%d << /BM /%s >>\n",
1264
0
               i, _cairo_operator_to_pdf_blend_mode(i));
1265
0
      }
1266
0
  }
1267
1268
0
  for (i = 0; i < num_alphas; i++) {
1269
0
      _cairo_array_copy_element (&res->alphas, i, &alpha);
1270
0
      _cairo_output_stream_printf (surface->output,
1271
0
           "      /a%d << /CA %f /ca %f >>\n",
1272
0
           i, alpha, alpha);
1273
0
  }
1274
1275
0
  for (i = 0; i < num_smasks; i++) {
1276
0
      smask = _cairo_array_index (&res->smasks, i);
1277
0
      _cairo_output_stream_printf (surface->output,
1278
0
           "      /s%d %d 0 R\n",
1279
0
           smask->id, smask->id);
1280
0
  }
1281
1282
0
  _cairo_output_stream_printf (surface->output,
1283
0
             "   >>\n");
1284
0
    }
1285
1286
2
    num_resources = _cairo_array_num_elements (&res->patterns);
1287
2
    if (num_resources > 0) {
1288
0
  _cairo_output_stream_printf (surface->output,
1289
0
             "   /Pattern <<");
1290
0
  for (i = 0; i < num_resources; i++) {
1291
0
      pattern = _cairo_array_index (&res->patterns, i);
1292
0
      _cairo_output_stream_printf (surface->output,
1293
0
           " /p%d %d 0 R",
1294
0
           pattern->id, pattern->id);
1295
0
  }
1296
1297
0
  _cairo_output_stream_printf (surface->output,
1298
0
             " >>\n");
1299
0
    }
1300
1301
2
    num_resources = _cairo_array_num_elements (&res->shadings);
1302
2
    if (num_resources > 0) {
1303
0
  _cairo_output_stream_printf (surface->output,
1304
0
             "   /Shading <<");
1305
0
  for (i = 0; i < num_resources; i++) {
1306
0
      shading = _cairo_array_index (&res->shadings, i);
1307
0
      _cairo_output_stream_printf (surface->output,
1308
0
           " /sh%d %d 0 R",
1309
0
           shading->id, shading->id);
1310
0
  }
1311
1312
0
  _cairo_output_stream_printf (surface->output,
1313
0
             " >>\n");
1314
0
    }
1315
1316
2
    num_resources = _cairo_array_num_elements (&res->xobjects);
1317
2
    if (num_resources > 0) {
1318
0
  _cairo_output_stream_printf (surface->output,
1319
0
             "   /XObject <<");
1320
1321
0
  for (i = 0; i < num_resources; i++) {
1322
0
      xobject = _cairo_array_index (&res->xobjects, i);
1323
0
      _cairo_output_stream_printf (surface->output,
1324
0
           " /x%d %d 0 R",
1325
0
           xobject->id, xobject->id);
1326
0
  }
1327
1328
0
  _cairo_output_stream_printf (surface->output,
1329
0
             " >>\n");
1330
0
    }
1331
1332
2
    num_resources = _cairo_array_num_elements (&res->fonts);
1333
2
    if (num_resources > 0) {
1334
0
  _cairo_output_stream_printf (surface->output,"   /Font <<\n");
1335
0
  for (i = 0; i < num_resources; i++) {
1336
0
      font = _cairo_array_index (&res->fonts, i);
1337
0
      _cairo_output_stream_printf (surface->output,
1338
0
           "      /f-%d-%d %d 0 R\n",
1339
0
           font->font_id,
1340
0
           font->subset_id,
1341
0
           font->subset_resource.id);
1342
0
  }
1343
0
  _cairo_output_stream_printf (surface->output, "   >>\n");
1344
0
    }
1345
1346
2
    _cairo_output_stream_printf (surface->output,
1347
2
         ">>\n");
1348
2
}
1349
1350
static cairo_pdf_smask_group_t *
1351
_cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t      *surface,
1352
               const cairo_rectangle_int_t  *extents)
1353
0
{
1354
0
    cairo_pdf_smask_group_t *group;
1355
1356
0
    group = calloc (1, sizeof (cairo_pdf_smask_group_t));
1357
0
    if (unlikely (group == NULL)) {
1358
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1359
0
  return NULL;
1360
0
    }
1361
1362
0
    group->group_res = _cairo_pdf_surface_new_object (surface);
1363
0
    if (group->group_res.id == 0) {
1364
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1365
0
  free (group);
1366
0
  return NULL;
1367
0
    }
1368
0
    group->width = surface->width;
1369
0
    group->height = surface->height;
1370
0
    if (extents != NULL) {
1371
0
  group->extents = *extents;
1372
0
    } else {
1373
0
  group->extents.x = 0;
1374
0
  group->extents.y = 0;
1375
0
  group->extents.width = surface->width;
1376
0
  group->extents.height = surface->height;
1377
0
    }
1378
1379
0
    return group;
1380
0
}
1381
1382
static void
1383
_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
1384
0
{
1385
0
    if (group->operation == PDF_FILL || group->operation == PDF_STROKE)
1386
0
  _cairo_path_fixed_fini (&group->path);
1387
0
    if (group->source)
1388
0
  cairo_pattern_destroy (group->source);
1389
0
    if (group->mask)
1390
0
  cairo_pattern_destroy (group->mask);
1391
0
    free (group->utf8);
1392
0
    free (group->glyphs);
1393
0
    free (group->clusters);
1394
0
    if (group->scaled_font)
1395
0
  cairo_scaled_font_destroy (group->scaled_font);
1396
0
    free (group);
1397
0
}
1398
1399
static cairo_int_status_t
1400
_cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t     *surface,
1401
            cairo_pdf_smask_group_t *group)
1402
0
{
1403
0
    return _cairo_array_append (&surface->smask_groups, &group);
1404
0
}
1405
1406
static cairo_bool_t
1407
_cairo_pdf_source_surface_equal (const void *key_a, const void *key_b)
1408
0
{
1409
0
    const cairo_pdf_source_surface_entry_t *a = key_a;
1410
0
    const cairo_pdf_source_surface_entry_t *b = key_b;
1411
1412
0
    if (a->interpolate != b->interpolate)
1413
0
  return FALSE;
1414
1415
0
    if (a->unique_id && b->unique_id && a->unique_id_length == b->unique_id_length)
1416
0
  return (memcmp (a->unique_id, b->unique_id, a->unique_id_length) == 0);
1417
1418
0
    return (a->id == b->id);
1419
0
}
1420
1421
static void
1422
_cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key)
1423
0
{
1424
0
    if (key->unique_id && key->unique_id_length > 0) {
1425
0
  key->base.hash = _cairo_hash_bytes (_CAIRO_HASH_INIT_VALUE,
1426
0
              key->unique_id, key->unique_id_length);
1427
0
    } else {
1428
0
  key->base.hash = key->id;
1429
0
    }
1430
0
}
1431
1432
static cairo_int_status_t
1433
_cairo_pdf_surface_acquire_source_image_from_pattern (cairo_pdf_surface_t          *surface,
1434
                  const cairo_pattern_t        *pattern,
1435
                  cairo_image_surface_t       **image,
1436
                  void                        **image_extra)
1437
0
{
1438
0
    switch (pattern->type) {
1439
0
    case CAIRO_PATTERN_TYPE_SURFACE: {
1440
0
  cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
1441
0
  return _cairo_surface_acquire_source_image (surf_pat->surface, image, image_extra);
1442
0
    } break;
1443
1444
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
1445
0
  cairo_surface_t *surf;
1446
0
  surf = _cairo_raster_source_pattern_acquire (pattern, &surface->base, NULL);
1447
0
  if (!surf)
1448
0
      return CAIRO_INT_STATUS_UNSUPPORTED;
1449
0
  assert (_cairo_surface_is_image (surf));
1450
0
  *image = (cairo_image_surface_t *) surf;
1451
0
    } break;
1452
1453
0
    case CAIRO_PATTERN_TYPE_SOLID:
1454
0
    case CAIRO_PATTERN_TYPE_LINEAR:
1455
0
    case CAIRO_PATTERN_TYPE_RADIAL:
1456
0
    case CAIRO_PATTERN_TYPE_MESH:
1457
0
    default:
1458
0
  ASSERT_NOT_REACHED;
1459
0
  break;
1460
0
    }
1461
1462
0
    return CAIRO_STATUS_SUCCESS;
1463
0
}
1464
1465
static void
1466
_cairo_pdf_surface_release_source_image_from_pattern (cairo_pdf_surface_t          *surface,
1467
                  const cairo_pattern_t        *pattern,
1468
                  cairo_image_surface_t        *image,
1469
                  void                         *image_extra)
1470
0
{
1471
0
    switch (pattern->type) {
1472
0
    case CAIRO_PATTERN_TYPE_SURFACE: {
1473
0
  cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
1474
0
  _cairo_surface_release_source_image (surf_pat->surface, image, image_extra);
1475
0
    } break;
1476
1477
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1478
0
  _cairo_raster_source_pattern_release (pattern, &image->base);
1479
0
  break;
1480
1481
0
    case CAIRO_PATTERN_TYPE_SOLID:
1482
0
    case CAIRO_PATTERN_TYPE_LINEAR:
1483
0
    case CAIRO_PATTERN_TYPE_RADIAL:
1484
0
    case CAIRO_PATTERN_TYPE_MESH:
1485
0
    default:
1486
1487
0
  ASSERT_NOT_REACHED;
1488
0
  break;
1489
0
    }
1490
0
}
1491
1492
static cairo_int_status_t
1493
_get_source_surface_extents (cairo_surface_t         *source,
1494
           cairo_rectangle_int_t   *extents,
1495
           cairo_bool_t            *bounded,
1496
           cairo_bool_t            *subsurface)
1497
0
{
1498
0
    cairo_int_status_t status;
1499
1500
0
    *bounded = TRUE;
1501
0
    *subsurface = FALSE;
1502
0
    if (source->type == CAIRO_SURFACE_TYPE_RECORDING) {
1503
0
  cairo_surface_t *free_me = NULL;
1504
1505
0
  if (_cairo_surface_is_snapshot (source))
1506
0
      free_me = source = _cairo_surface_snapshot_get_target (source);
1507
1508
0
  if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1509
0
      cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
1510
1511
0
      *extents = sub->extents;
1512
0
      *subsurface = TRUE;
1513
0
  } else {
1514
0
      cairo_box_t box;
1515
1516
0
      *bounded = _cairo_surface_get_extents (source, extents);
1517
0
      if (! *bounded) {
1518
0
    status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)source,
1519
0
                &box, NULL);
1520
0
    if (unlikely (status)) {
1521
0
        cairo_surface_destroy (free_me);
1522
0
        return status;
1523
0
    }
1524
0
    _cairo_box_round_to_rectangle (&box, extents);
1525
0
      }
1526
0
  }
1527
0
  cairo_surface_destroy (free_me);
1528
0
    } else {
1529
0
  *bounded =  _cairo_surface_get_extents (source, extents);
1530
0
    }
1531
1532
0
    return CAIRO_STATUS_SUCCESS;
1533
0
}
1534
1535
/**
1536
 * _cairo_pdf_surface_add_source_surface:
1537
 * @surface: [in] the pdf surface
1538
 * @source_surface: [in] A #cairo_surface_t to use as the source surface
1539
 * @source_pattern: [in] A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source
1540
 * @op: [in] the operator used to composite this source
1541
 * @filter: [in] filter type of the source pattern
1542
 * @stencil_mask: [in] if true, the surface will be written to the PDF as an /ImageMask
1543
 * @smask: [in] if true, only the alpha channel will be written (images only)
1544
 * @need_transp_group: [in] if true and an XObject is used, make it a Transparency group
1545
 * @extents: [in] extents of the operation that is using this source
1546
 * @smask_res: [in] if not NULL, the image written will specify this resource as the smask for
1547
 * the image (images only)
1548
 * @pdf_source: [out] return pdf_source_surface entry in hash table
1549
 * @x_offset: [out] if not NULL return x offset of surface
1550
 * @y_offset: [out] if not NULL return y offset of surface
1551
 * @source_extents: [out] if not NULL return operation extents in source space
1552
 *
1553
 * Add surface or raster_source pattern to list of surfaces to be
1554
 * written to the PDF file when the current page is finished. Returns
1555
 * a PDF resource to reference the surface. A hash table of all
1556
 * surfaces in the PDF file (keyed by CAIRO_MIME_TYPE_UNIQUE_ID or
1557
 * surface unique_id) is used to ensure surfaces with the same id are
1558
 * only written once to the PDF file.
1559
 *
1560
 * Only one of @source_pattern or @source_surface is to be
1561
 * specified. Set the other to NULL.
1562
 **/
1563
static cairo_int_status_t
1564
_cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t           *surface,
1565
               cairo_surface_t                   *source_surface,
1566
               const cairo_pattern_t           *source_pattern,
1567
               cairo_operator_t                   op,
1568
               cairo_filter_t             filter,
1569
               cairo_bool_t                       stencil_mask,
1570
               cairo_bool_t                       smask,
1571
               cairo_bool_t                       need_transp_group,
1572
               const cairo_rectangle_int_t       *extents,
1573
               cairo_pdf_resource_t          *smask_res,
1574
               cairo_pdf_source_surface_entry_t **pdf_source,
1575
               double                            *x_offset,
1576
               double                            *y_offset,
1577
               cairo_rectangle_int_t             *source_extents)
1578
0
{
1579
0
    cairo_pdf_source_surface_t src_surface;
1580
0
    cairo_pdf_source_surface_entry_t surface_key;
1581
0
    cairo_pdf_source_surface_entry_t *surface_entry;
1582
0
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
1583
0
    cairo_bool_t interpolate;
1584
0
    unsigned char *unique_id = NULL;
1585
0
    unsigned long unique_id_length = 0;
1586
0
    cairo_image_surface_t *image;
1587
0
    void *image_extra;
1588
0
    cairo_box_t box;
1589
0
    cairo_rectangle_int_t op_extents;
1590
0
    double x, y;
1591
0
    cairo_bool_t subsurface;
1592
1593
0
    switch (filter) {
1594
0
    default:
1595
0
    case CAIRO_FILTER_GOOD:
1596
0
    case CAIRO_FILTER_BEST:
1597
0
    case CAIRO_FILTER_BILINEAR:
1598
0
  interpolate = TRUE;
1599
0
  break;
1600
0
    case CAIRO_FILTER_FAST:
1601
0
    case CAIRO_FILTER_NEAREST:
1602
0
    case CAIRO_FILTER_GAUSSIAN:
1603
0
  interpolate = FALSE;
1604
0
  break;
1605
0
    }
1606
1607
0
    x = 0;
1608
0
    y = 0;
1609
0
    if (source_pattern) {
1610
0
  if (source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1611
0
      status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source_pattern,
1612
0
                     &image, &image_extra);
1613
0
      if (unlikely (status))
1614
0
    return status;
1615
0
      source_surface = &image->base;
1616
0
      cairo_surface_get_device_offset (source_surface, &x, &y);
1617
0
  } else {
1618
0
      cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source_pattern;
1619
0
      source_surface = surface_pattern->surface;
1620
0
  }
1621
0
    }
1622
0
    if (x_offset)
1623
0
  *x_offset = x;
1624
0
    if (y_offset)
1625
0
  *y_offset = y;
1626
1627
    /* transform operation extents to pattern space */
1628
0
    op_extents = *extents;
1629
0
    if (source_pattern)
1630
0
    {
1631
0
  _cairo_box_from_rectangle (&box, extents);
1632
0
  _cairo_matrix_transform_bounding_box_fixed (&source_pattern->matrix, &box, NULL);
1633
0
  _cairo_box_round_to_rectangle (&box, &op_extents);
1634
0
    }
1635
0
    if (source_extents)
1636
0
  *source_extents = op_extents;
1637
1638
0
    surface_key.id  = source_surface->unique_id;
1639
0
    surface_key.interpolate = interpolate;
1640
0
    cairo_surface_get_mime_data (source_surface, CAIRO_MIME_TYPE_UNIQUE_ID,
1641
0
         (const unsigned char **) &surface_key.unique_id,
1642
0
         &surface_key.unique_id_length);
1643
0
    _cairo_pdf_source_surface_init_key (&surface_key);
1644
0
    surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base);
1645
0
    if (surface_entry) {
1646
0
  if (pdf_source)
1647
0
      *pdf_source = surface_entry;
1648
1649
0
  if (source_pattern && source_pattern->extend != CAIRO_EXTEND_NONE)
1650
0
      _cairo_unbounded_rectangle_init (&op_extents);
1651
1652
0
  _cairo_rectangle_intersect (&op_extents, &surface_entry->extents);
1653
0
  _cairo_rectangle_union (&surface_entry->required_extents, &op_extents);
1654
0
  status = CAIRO_STATUS_SUCCESS;
1655
0
    }
1656
1657
0
    if (status || surface_entry) {
1658
0
  if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1659
0
      _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra);
1660
0
  return status;
1661
0
    }
1662
1663
0
    if (surface_key.unique_id && surface_key.unique_id_length > 0) {
1664
0
  unique_id = _cairo_malloc (surface_key.unique_id_length);
1665
0
  if (unique_id == NULL) {
1666
0
      status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1667
0
      goto fail1;
1668
0
  }
1669
1670
0
  unique_id_length = surface_key.unique_id_length;
1671
0
      memcpy (unique_id, surface_key.unique_id, unique_id_length);
1672
0
    } else {
1673
0
  unique_id = NULL;
1674
0
  unique_id_length = 0;
1675
0
    }
1676
1677
0
    surface_entry = _cairo_malloc (sizeof (cairo_pdf_source_surface_entry_t));
1678
0
    if (surface_entry == NULL) {
1679
0
  status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1680
0
  goto fail1;
1681
0
    }
1682
1683
0
    if (pdf_source)
1684
0
  *pdf_source = surface_entry;
1685
0
    surface_entry->id = surface_key.id;
1686
0
    surface_entry->operator = op;
1687
0
    surface_entry->interpolate = interpolate;
1688
0
    surface_entry->stencil_mask = stencil_mask;
1689
0
    surface_entry->smask = smask;
1690
0
    surface_entry->need_transp_group = need_transp_group;
1691
0
    surface_entry->unique_id_length = unique_id_length;
1692
0
    surface_entry->unique_id = unique_id;
1693
0
    if (smask_res)
1694
0
  surface_entry->smask_res = *smask_res;
1695
0
    else
1696
0
  surface_entry->smask_res.id = 0;
1697
1698
0
    status = _get_source_surface_extents (source_surface,
1699
0
            &surface_entry->extents,
1700
0
            &surface_entry->bounded,
1701
0
            &subsurface);
1702
0
    if (unlikely (status))
1703
0
  goto fail2;
1704
1705
0
    if (subsurface) {
1706
0
  *x_offset = -surface_entry->extents.x;
1707
0
  *y_offset = -surface_entry->extents.y;
1708
0
    }
1709
1710
0
    if (source_pattern && source_pattern->extend != CAIRO_EXTEND_NONE)
1711
0
  _cairo_unbounded_rectangle_init (&op_extents);
1712
1713
0
    _cairo_rectangle_intersect (&op_extents, &surface_entry->extents);
1714
0
    surface_entry->required_extents = op_extents;
1715
1716
0
    _cairo_pdf_source_surface_init_key (surface_entry);
1717
1718
0
    src_surface.hash_entry = surface_entry;
1719
0
    if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
1720
0
  src_surface.type = CAIRO_PATTERN_TYPE_RASTER_SOURCE;
1721
0
  src_surface.surface = NULL;
1722
0
  status = _cairo_pattern_create_copy (&src_surface.raster_pattern, source_pattern);
1723
0
  if (unlikely (status))
1724
0
      goto fail2;
1725
1726
0
    } else {
1727
0
  src_surface.type = CAIRO_PATTERN_TYPE_SURFACE;
1728
0
  src_surface.surface = cairo_surface_reference (source_surface);
1729
0
  src_surface.raster_pattern = NULL;
1730
0
    }
1731
1732
0
    surface_entry->surface_res = _cairo_pdf_surface_new_object (surface);
1733
0
    if (surface_entry->surface_res.id == 0) {
1734
0
  status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1735
0
  goto fail3;
1736
0
    }
1737
1738
    /* Test if surface will be emitted as image or recording */
1739
0
    status = _cairo_pdf_surface_emit_surface (surface, &src_surface, TRUE, &surface_entry->emit_image);
1740
0
    if (unlikely (status))
1741
0
  goto fail3;
1742
1743
0
    if (surface_entry->bounded) {
1744
0
  status = _cairo_array_append (&surface->page_surfaces, &src_surface);
1745
0
  if (unlikely (status))
1746
0
      goto fail3;
1747
0
    } else {
1748
0
  status = _cairo_array_append (&surface->doc_surfaces, &src_surface);
1749
0
  if (unlikely (status))
1750
0
      goto fail3;
1751
0
    }
1752
1753
0
    status = _cairo_hash_table_insert (surface->all_surfaces,
1754
0
               &surface_entry->base);
1755
0
    if (unlikely(status))
1756
0
  goto fail3;
1757
1758
0
    if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1759
0
  _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra);
1760
1761
0
    return CAIRO_STATUS_SUCCESS;
1762
1763
0
fail3:
1764
0
    if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1765
0
  cairo_pattern_destroy (src_surface.raster_pattern);
1766
0
    else
1767
0
  cairo_surface_destroy (src_surface.surface);
1768
1769
0
fail2:
1770
0
    free (surface_entry);
1771
1772
0
fail1:
1773
0
    if (unique_id)
1774
0
  free (unique_id);
1775
1776
0
    if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
1777
0
  _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra);
1778
1779
0
    return status;
1780
0
}
1781
1782
static cairo_int_status_t
1783
_cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t     *surface,
1784
                 const cairo_pattern_t     *pattern,
1785
                 cairo_operator_t             op,
1786
                 const cairo_rectangle_int_t *extents,
1787
                 cairo_bool_t                 is_shading,
1788
                 cairo_pdf_resource_t    *pattern_res,
1789
                 cairo_pdf_resource_t    *gstate_res)
1790
0
{
1791
0
    cairo_pdf_pattern_t pdf_pattern;
1792
0
    cairo_int_status_t status;
1793
1794
0
    pdf_pattern.is_shading = is_shading;
1795
0
    pdf_pattern.operator = op;
1796
1797
    /* Solid colors are emitted into the content stream */
1798
0
    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
1799
0
  pattern_res->id = 0;
1800
0
  gstate_res->id = 0;
1801
0
  return CAIRO_INT_STATUS_SUCCESS;
1802
0
    }
1803
1804
0
    status = _cairo_pattern_create_copy (&pdf_pattern.pattern, pattern);
1805
0
    if (unlikely (status))
1806
0
  return status;
1807
1808
0
    pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface);
1809
0
    if (pdf_pattern.pattern_res.id == 0) {
1810
0
  cairo_pattern_destroy (pdf_pattern.pattern);
1811
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1812
0
    }
1813
1814
0
    pdf_pattern.gstate_res.id = 0;
1815
1816
    /* gradient patterns require an smask object to implement transparency */
1817
0
    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
1818
0
  pattern->type == CAIRO_PATTERN_TYPE_RADIAL ||
1819
0
  pattern->type == CAIRO_PATTERN_TYPE_MESH)
1820
0
    {
1821
0
  double min_alpha;
1822
1823
0
  _cairo_pattern_alpha_range (pattern, &min_alpha, NULL);
1824
0
  if (! CAIRO_ALPHA_IS_OPAQUE (min_alpha)) {
1825
0
            pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
1826
0
      if (pdf_pattern.gstate_res.id == 0) {
1827
0
    cairo_pattern_destroy (pdf_pattern.pattern);
1828
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1829
0
      }
1830
0
        }
1831
0
    }
1832
1833
0
    pdf_pattern.width  = surface->width;
1834
0
    pdf_pattern.height = surface->height;
1835
0
    if (extents != NULL) {
1836
0
  pdf_pattern.extents = *extents;
1837
0
    } else {
1838
0
  pdf_pattern.extents.x = 0;
1839
0
  pdf_pattern.extents.y = 0;
1840
0
  pdf_pattern.extents.width  = surface->width;
1841
0
  pdf_pattern.extents.height = surface->height;
1842
0
    }
1843
1844
0
    *pattern_res = pdf_pattern.pattern_res;
1845
0
    *gstate_res = pdf_pattern.gstate_res;
1846
    /* If the pattern requires a gstate it will be drawn from within
1847
     * an XObject. The initial space of each XObject has an inverted
1848
     * Y-axis. */
1849
0
    pdf_pattern.inverted_y_axis = pdf_pattern.gstate_res.id ? TRUE : surface->in_xobject;
1850
1851
0
    status = _cairo_array_append (&surface->page_patterns, &pdf_pattern);
1852
0
    if (unlikely (status)) {
1853
0
  cairo_pattern_destroy (pdf_pattern.pattern);
1854
0
  return status;
1855
0
    }
1856
1857
0
    return CAIRO_INT_STATUS_SUCCESS;
1858
0
}
1859
1860
/* Get BBox from extents */
1861
static void
1862
_get_bbox_from_extents (const cairo_rectangle_int_t  *extents,
1863
      cairo_box_double_t           *bbox)
1864
0
{
1865
0
    bbox->p1.x = extents->x;
1866
0
    bbox->p1.y = extents->y;
1867
0
    bbox->p2.x = extents->x + extents->width;
1868
0
    bbox->p2.y = extents->y + extents->height;
1869
0
}
1870
1871
static cairo_int_status_t
1872
_cairo_pdf_surface_add_pdf_shading (cairo_pdf_surface_t   *surface,
1873
            const cairo_pattern_t *pattern,
1874
            cairo_operator_t           op,
1875
            const cairo_rectangle_int_t *extents,
1876
            cairo_pdf_resource_t  *shading_res,
1877
            cairo_pdf_resource_t  *gstate_res)
1878
0
{
1879
0
    return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
1880
0
                pattern,
1881
0
                op,
1882
0
                extents,
1883
0
                TRUE,
1884
0
                shading_res,
1885
0
                gstate_res);
1886
0
}
1887
1888
static cairo_int_status_t
1889
_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t   *surface,
1890
            const cairo_pattern_t *pattern,
1891
            cairo_operator_t           op,
1892
            const cairo_rectangle_int_t *extents,
1893
            cairo_pdf_resource_t  *pattern_res,
1894
            cairo_pdf_resource_t  *gstate_res)
1895
0
{
1896
0
    return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
1897
0
                pattern,
1898
0
                op,
1899
0
                extents,
1900
0
                FALSE,
1901
0
                pattern_res,
1902
0
                gstate_res);
1903
0
}
1904
1905
static cairo_int_status_t
1906
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
1907
        cairo_pdf_resource_t    *resource,
1908
        cairo_bool_t             compressed,
1909
        const char    *fmt,
1910
        ...)
1911
2
{
1912
2
    va_list ap;
1913
2
    cairo_pdf_resource_t self, length;
1914
2
    cairo_output_stream_t *output = NULL;
1915
1916
2
    if (resource) {
1917
0
  self = *resource;
1918
0
  _cairo_pdf_surface_update_object (surface, self);
1919
2
    } else {
1920
2
  self = _cairo_pdf_surface_new_object (surface);
1921
2
  if (self.id == 0)
1922
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1923
2
    }
1924
1925
2
    length = _cairo_pdf_surface_new_object (surface);
1926
2
    if (length.id == 0)
1927
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1928
1929
2
    if (compressed) {
1930
2
  output = _cairo_deflate_stream_create (surface->output);
1931
2
  if (_cairo_output_stream_get_status (output))
1932
0
      return _cairo_output_stream_destroy (output);
1933
2
    }
1934
1935
2
    surface->pdf_stream.active = TRUE;
1936
2
    surface->pdf_stream.self = self;
1937
2
    surface->pdf_stream.length = length;
1938
2
    surface->pdf_stream.compressed = compressed;
1939
2
    surface->current_pattern_is_solid_color = FALSE;
1940
2
    surface->current_operator = CAIRO_OPERATOR_OVER;
1941
2
    _cairo_pdf_operators_reset (&surface->pdf_operators);
1942
1943
2
    _cairo_output_stream_printf (surface->output,
1944
2
         "%d 0 obj\n"
1945
2
         "<< /Length %d 0 R\n",
1946
2
         surface->pdf_stream.self.id,
1947
2
         surface->pdf_stream.length.id);
1948
2
    if (compressed)
1949
2
  _cairo_output_stream_printf (surface->output,
1950
2
             "   /Filter /FlateDecode\n");
1951
1952
2
    if (fmt != NULL) {
1953
0
  va_start (ap, fmt);
1954
0
  _cairo_output_stream_vprintf (surface->output, fmt, ap);
1955
0
  va_end (ap);
1956
0
    }
1957
1958
2
    _cairo_output_stream_printf (surface->output,
1959
2
         ">>\n"
1960
2
         "stream\n");
1961
1962
2
    surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
1963
1964
2
    if (compressed) {
1965
2
  assert (surface->pdf_stream.old_output == NULL);
1966
2
        surface->pdf_stream.old_output = surface->output;
1967
2
        surface->output = output;
1968
2
  _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1969
2
    }
1970
2
    _cairo_pdf_operators_reset (&surface->pdf_operators);
1971
1972
2
    return _cairo_output_stream_get_status (surface->output);
1973
2
}
1974
1975
static cairo_int_status_t
1976
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
1977
4
{
1978
4
    cairo_int_status_t status;
1979
4
    long long length;
1980
1981
4
    if (! surface->pdf_stream.active)
1982
2
  return CAIRO_INT_STATUS_SUCCESS;
1983
1984
2
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1985
1986
2
    if (surface->pdf_stream.compressed) {
1987
2
  cairo_int_status_t status2;
1988
1989
2
  status2 = _cairo_output_stream_destroy (surface->output);
1990
2
  if (likely (status == CAIRO_INT_STATUS_SUCCESS))
1991
2
      status = status2;
1992
1993
2
  surface->output = surface->pdf_stream.old_output;
1994
2
  _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1995
2
  surface->pdf_stream.old_output = NULL;
1996
2
    }
1997
1998
2
    length = _cairo_output_stream_get_position (surface->output) -
1999
2
  surface->pdf_stream.start_offset;
2000
2
    _cairo_output_stream_printf (surface->output,
2001
2
         "\n"
2002
2
         "endstream\n"
2003
2
         "endobj\n");
2004
2005
2
    _cairo_pdf_surface_update_object (surface,
2006
2
              surface->pdf_stream.length);
2007
2
    _cairo_output_stream_printf (surface->output,
2008
2
         "%d 0 obj\n"
2009
2
         "   %lld\n"
2010
2
         "endobj\n",
2011
2
         surface->pdf_stream.length.id,
2012
2
         length);
2013
2014
2
    surface->pdf_stream.active = FALSE;
2015
2016
2
    if (likely (status == CAIRO_INT_STATUS_SUCCESS))
2017
2
  status = _cairo_output_stream_get_status (surface->output);
2018
2019
2
    return status;
2020
4
}
2021
2022
static void
2023
_cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t         *surface,
2024
          cairo_output_stream_t       *mem_stream,
2025
          cairo_pdf_resource_t         resource,
2026
          cairo_pdf_group_resources_t *resources,
2027
          cairo_bool_t                 is_knockout_group,
2028
          const cairo_box_double_t    *bbox)
2029
0
{
2030
0
    _cairo_pdf_surface_update_object (surface, resource);
2031
2032
0
    _cairo_output_stream_printf (surface->output,
2033
0
         "%d 0 obj\n"
2034
0
         "<< /Type /XObject\n"
2035
0
         "   /Length %d\n",
2036
0
         resource.id,
2037
0
         _cairo_memory_stream_length (mem_stream));
2038
2039
0
    if (surface->compress_streams) {
2040
0
  _cairo_output_stream_printf (surface->output,
2041
0
             "   /Filter /FlateDecode\n");
2042
0
    }
2043
2044
0
    _cairo_output_stream_printf (surface->output,
2045
0
         "   /Subtype /Form\n"
2046
0
         "   /BBox [ %f %f %f %f ]\n"
2047
0
         "   /Group <<\n"
2048
0
         "      /Type /Group\n"
2049
0
         "      /S /Transparency\n"
2050
0
         "      /I true\n"
2051
0
         "      /CS /DeviceRGB\n",
2052
0
         bbox->p1.x, bbox->p1.y, bbox->p2.x, bbox->p2.y);
2053
2054
0
    if (is_knockout_group)
2055
0
        _cairo_output_stream_printf (surface->output,
2056
0
                                     "      /K true\n");
2057
2058
0
    _cairo_output_stream_printf (surface->output,
2059
0
         "   >>\n"
2060
0
         "   /Resources\n");
2061
0
    _cairo_pdf_surface_emit_group_resources (surface, resources);
2062
0
    _cairo_output_stream_printf (surface->output,
2063
0
         ">>\n"
2064
0
         "stream\n");
2065
0
    _cairo_memory_stream_copy (mem_stream, surface->output);
2066
0
    _cairo_output_stream_printf (surface->output,
2067
0
         "endstream\n"
2068
0
         "endobj\n");
2069
0
}
2070
2071
static cairo_int_status_t
2072
_cairo_pdf_surface_open_group (cairo_pdf_surface_t         *surface,
2073
             const cairo_box_double_t    *bbox,
2074
             cairo_pdf_resource_t        *resource)
2075
0
{
2076
0
    cairo_int_status_t status;
2077
2078
0
    assert (surface->pdf_stream.active == FALSE);
2079
0
    assert (surface->group_stream.active == FALSE);
2080
2081
0
    surface->group_stream.active = TRUE;
2082
0
    surface->current_pattern_is_solid_color = FALSE;
2083
0
    surface->current_operator = CAIRO_OPERATOR_OVER;
2084
0
    _cairo_pdf_operators_reset (&surface->pdf_operators);
2085
2086
0
    surface->group_stream.mem_stream = _cairo_memory_stream_create ();
2087
2088
0
    if (surface->compress_streams) {
2089
0
  surface->group_stream.stream =
2090
0
      _cairo_deflate_stream_create (surface->group_stream.mem_stream);
2091
0
    } else {
2092
0
  surface->group_stream.stream = surface->group_stream.mem_stream;
2093
0
    }
2094
0
    status = _cairo_output_stream_get_status (surface->group_stream.stream);
2095
2096
0
    surface->group_stream.old_output = surface->output;
2097
0
    surface->output = surface->group_stream.stream;
2098
0
    _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
2099
0
    _cairo_pdf_group_resources_clear (&surface->resources);
2100
2101
0
    if (resource) {
2102
0
  surface->group_stream.resource = *resource;
2103
0
    } else {
2104
0
  surface->group_stream.resource = _cairo_pdf_surface_new_object (surface);
2105
0
  if (surface->group_stream.resource.id == 0)
2106
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2107
0
    }
2108
0
    surface->group_stream.is_knockout = FALSE;
2109
0
    surface->group_stream.bbox = *bbox;
2110
2111
0
    return status;
2112
0
}
2113
2114
static cairo_int_status_t
2115
_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t         *surface,
2116
          const cairo_box_double_t    *bbox)
2117
0
{
2118
0
    cairo_int_status_t status;
2119
2120
0
    status = _cairo_pdf_surface_open_group (surface, bbox, NULL);
2121
0
    if (unlikely (status))
2122
0
  return status;
2123
2124
0
    surface->group_stream.is_knockout = TRUE;
2125
2126
0
    return CAIRO_INT_STATUS_SUCCESS;
2127
0
}
2128
2129
static cairo_int_status_t
2130
_cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
2131
        cairo_pdf_resource_t *group)
2132
0
{
2133
0
    cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS, status2;
2134
2135
0
    assert (surface->pdf_stream.active == FALSE);
2136
0
    assert (surface->group_stream.active == TRUE);
2137
2138
0
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
2139
0
    if (unlikely (status))
2140
0
  return status;
2141
2142
0
    if (surface->compress_streams) {
2143
0
  status = _cairo_output_stream_destroy (surface->group_stream.stream);
2144
0
  surface->group_stream.stream = NULL;
2145
2146
0
  _cairo_output_stream_printf (surface->group_stream.mem_stream,
2147
0
             "\n");
2148
0
    }
2149
0
    surface->output = surface->group_stream.old_output;
2150
0
    _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
2151
0
    surface->group_stream.active = FALSE;
2152
0
    _cairo_pdf_surface_write_memory_stream (surface,
2153
0
              surface->group_stream.mem_stream,
2154
0
              surface->group_stream.resource,
2155
0
              &surface->resources,
2156
0
              surface->group_stream.is_knockout,
2157
0
              &surface->group_stream.bbox);
2158
0
    if (group)
2159
0
  *group = surface->group_stream.resource;
2160
2161
0
    status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
2162
0
    if (status == CAIRO_INT_STATUS_SUCCESS)
2163
0
  status = status2;
2164
2165
0
    surface->group_stream.mem_stream = NULL;
2166
0
    surface->group_stream.stream = NULL;
2167
2168
0
    return status;
2169
0
}
2170
2171
static cairo_int_status_t
2172
_cairo_pdf_surface_open_object_stream (cairo_pdf_surface_t *surface)
2173
4
{
2174
4
    if (surface->pdf_version < CAIRO_PDF_VERSION_1_5) {
2175
  /* Object streams not supported. All objects will be written
2176
   * directly to the file. */
2177
0
  assert (surface->pdf_stream.active == FALSE);
2178
0
  assert (surface->group_stream.active == FALSE);
2179
0
  surface->object_stream.stream = surface->output;
2180
4
    } else {
2181
4
  surface->object_stream.resource = _cairo_pdf_surface_new_object (surface);
2182
4
  if (surface->object_stream.resource.id == 0)
2183
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2184
2185
4
  _cairo_array_truncate (&surface->object_stream.objects, 0);
2186
4
  surface->object_stream.stream = _cairo_memory_stream_create ();
2187
4
  surface->object_stream.active = TRUE;
2188
4
    }
2189
4
    return _cairo_output_stream_get_status (surface->object_stream.stream);
2190
4
}
2191
2192
cairo_int_status_t
2193
_cairo_pdf_surface_object_begin (cairo_pdf_surface_t *surface,
2194
         cairo_pdf_resource_t resource)
2195
8
{
2196
8
    cairo_xref_stream_object_t xref_obj;
2197
8
    cairo_pdf_object_t *object;
2198
8
    cairo_int_status_t status;
2199
2200
8
    if (surface->object_stream.active) {
2201
8
  xref_obj.resource = resource;
2202
8
  xref_obj.offset = _cairo_output_stream_get_position (surface->object_stream.stream);
2203
8
  status = _cairo_array_append (&surface->object_stream.objects, &xref_obj);
2204
8
  if (unlikely (status))
2205
0
      return status;
2206
2207
8
  object = _cairo_array_index (&surface->objects, resource.id - 1);
2208
8
  object->type = PDF_OBJECT_COMPRESSED;
2209
8
  object->u.compressed_obj.xref_stream = surface->object_stream.resource;
2210
8
  object->u.compressed_obj.index = _cairo_array_num_elements (&surface->object_stream.objects) - 1;
2211
2212
8
    } else {
2213
0
  _cairo_pdf_surface_update_object (surface, resource);
2214
0
  _cairo_output_stream_printf (surface->output,
2215
0
             "%d 0 obj\n",
2216
0
             resource.id);
2217
0
    }
2218
8
    return CAIRO_INT_STATUS_SUCCESS;
2219
8
}
2220
2221
void
2222
_cairo_pdf_surface_object_end (cairo_pdf_surface_t *surface)
2223
8
{
2224
8
    if (!surface->object_stream.active) {
2225
0
  _cairo_output_stream_printf (surface->output,
2226
0
             "endobj\n");
2227
0
    }
2228
8
}
2229
2230
static int _cairo_xref_stream_object_compare (const void *a, const void *b)
2231
4
{
2232
4
    const cairo_xref_stream_object_t *a_obj = a;
2233
4
    const cairo_xref_stream_object_t *b_obj = b;
2234
2235
4
    if (a_obj->offset < b_obj->offset)
2236
4
  return -1;
2237
0
    else if (a_obj->offset > b_obj->offset)
2238
0
  return 1;
2239
0
    else
2240
0
  return 0;
2241
4
}
2242
2243
static cairo_int_status_t
2244
_cairo_pdf_surface_close_object_stream (cairo_pdf_surface_t *surface)
2245
4
{
2246
4
    int i, num_objects;
2247
4
    cairo_xref_stream_object_t *xref_obj;
2248
4
    long long start_pos, length;
2249
4
    cairo_output_stream_t *index_stream;
2250
4
    cairo_output_stream_t *deflate_stream;
2251
4
    cairo_pdf_resource_t length_res;
2252
4
    cairo_int_status_t status;
2253
4
    cairo_pdf_object_t *object;
2254
2255
4
    if (!surface->object_stream.active) {
2256
0
  surface->object_stream.stream = NULL;
2257
0
  return CAIRO_INT_STATUS_SUCCESS;
2258
0
    }
2259
2260
4
    num_objects = _cairo_array_num_elements (&surface->object_stream.objects);
2261
4
    if (num_objects == 0) {
2262
0
  object = _cairo_array_index (&surface->objects, surface->object_stream.resource.id - 1);
2263
0
  object->type = PDF_OBJECT_FREE;
2264
0
  return CAIRO_INT_STATUS_SUCCESS;
2265
0
    }
2266
2267
4
    index_stream = _cairo_memory_stream_create ();
2268
    /* PDF requires the object id/offset pairs to be sorted by offset. */
2269
4
    _cairo_array_sort (&surface->object_stream.objects, _cairo_xref_stream_object_compare);
2270
12
    for (i = 0; i < num_objects; i++) {
2271
8
  xref_obj = _cairo_array_index (&surface->object_stream.objects, i);
2272
8
  _cairo_output_stream_printf (index_stream,
2273
8
             "%d %lld\n",
2274
8
             xref_obj->resource.id,
2275
8
             xref_obj->offset);
2276
8
    }
2277
2278
4
    length_res = _cairo_pdf_surface_new_object (surface);
2279
4
    if (length_res.id == 0)
2280
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2281
2282
4
    _cairo_pdf_surface_update_object (surface, surface->object_stream.resource);
2283
4
    _cairo_output_stream_printf (surface->output,
2284
4
         "%d 0 obj\n"
2285
4
         "<< /Type /ObjStm\n"
2286
4
                                 "   /Length %d 0 R\n"
2287
4
                                 "   /N %d\n"
2288
4
                                 "   /First %d\n",
2289
4
         surface->object_stream.resource.id,
2290
4
         length_res.id,
2291
4
         num_objects,
2292
4
         _cairo_memory_stream_length (index_stream));
2293
2294
4
    if (surface->compress_streams) {
2295
4
  _cairo_output_stream_printf (surface->output,
2296
4
             "   /Filter /FlateDecode\n");
2297
4
    }
2298
2299
4
    _cairo_output_stream_printf (surface->output,
2300
4
         ">>\n"
2301
4
         "stream\n");
2302
2303
4
    start_pos = _cairo_output_stream_get_position (surface->output);
2304
4
    if (surface->compress_streams) {
2305
4
  deflate_stream = _cairo_deflate_stream_create (surface->output);
2306
4
  _cairo_memory_stream_copy (index_stream, deflate_stream);
2307
4
  _cairo_memory_stream_copy (surface->object_stream.stream, deflate_stream);
2308
4
  status = _cairo_output_stream_destroy (deflate_stream);
2309
4
  if (unlikely (status))
2310
0
      return status;
2311
2312
4
  length = _cairo_output_stream_get_position (surface->output) - start_pos;
2313
4
    } else {
2314
0
  _cairo_memory_stream_copy (index_stream, surface->output);
2315
0
  _cairo_memory_stream_copy (surface->object_stream.stream, surface->output);
2316
0
  length = _cairo_output_stream_get_position (surface->output) - start_pos;
2317
0
    }
2318
2319
4
    _cairo_output_stream_printf (surface->output,
2320
4
         "\n"
2321
4
         "endstream\n"
2322
4
         "endobj\n");
2323
2324
4
    _cairo_pdf_surface_update_object (surface,
2325
4
              length_res);
2326
4
    _cairo_output_stream_printf (surface->output,
2327
4
         "%d 0 obj\n"
2328
4
         "   %lld\n"
2329
4
         "endobj\n",
2330
4
         length_res.id,
2331
4
         length);
2332
2333
4
    status = _cairo_output_stream_destroy (index_stream);
2334
4
    if (unlikely (status))
2335
0
  return status;
2336
2337
4
    status = _cairo_output_stream_destroy (surface->object_stream.stream);
2338
4
    if (unlikely (status))
2339
0
  return status;
2340
2341
4
    surface->object_stream.stream = NULL;
2342
4
    surface->object_stream.active = FALSE;
2343
2344
4
    return _cairo_output_stream_get_status (surface->output);
2345
4
}
2346
2347
static cairo_int_status_t
2348
_cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t       *surface,
2349
          const cairo_box_double_t  *bbox,
2350
          cairo_pdf_resource_t      *resource,
2351
          cairo_bool_t               is_form,
2352
          cairo_bool_t               is_group)
2353
2
{
2354
2
    cairo_int_status_t status;
2355
2356
2
    assert (surface->pdf_stream.active == FALSE);
2357
2
    assert (surface->group_stream.active == FALSE);
2358
2359
2
    surface->content_resources = _cairo_pdf_surface_new_object (surface);
2360
2
    if (surface->content_resources.id == 0)
2361
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2362
2363
2
    if (is_form) {
2364
0
  assert (bbox != NULL);
2365
2366
0
  if (is_group) {
2367
0
      status =
2368
0
    _cairo_pdf_surface_open_stream (surface,
2369
0
            resource,
2370
0
            surface->compress_streams,
2371
0
            "   /Type /XObject\n"
2372
0
            "   /Subtype /Form\n"
2373
0
            "   /BBox [ %f %f %f %f ]\n"
2374
0
            "   /Group <<\n"
2375
0
            "      /Type /Group\n"
2376
0
            "      /S /Transparency\n"
2377
0
            "      /I true\n"
2378
0
            "      /CS /DeviceRGB\n"
2379
0
            "   >>\n"
2380
0
            "   /Resources %d 0 R\n",
2381
0
            bbox->p1.x,
2382
0
            bbox->p1.y,
2383
0
            bbox->p2.x,
2384
0
            bbox->p2.y,
2385
0
            surface->content_resources.id);
2386
0
  } else {
2387
0
      status =
2388
0
    _cairo_pdf_surface_open_stream (surface,
2389
0
            resource,
2390
0
            surface->compress_streams,
2391
0
            "   /Type /XObject\n"
2392
0
            "   /Subtype /Form\n"
2393
0
            "   /BBox [ %f %f %f %f ]\n"
2394
0
            "   /Resources %d 0 R\n",
2395
0
            bbox->p1.x,
2396
0
            bbox->p1.y,
2397
0
            bbox->p2.x,
2398
0
            bbox->p2.y,
2399
0
            surface->content_resources.id);
2400
0
  }
2401
2
    } else {
2402
2
  status =
2403
2
      _cairo_pdf_surface_open_stream (surface,
2404
2
              resource,
2405
2
              surface->compress_streams,
2406
2
              NULL);
2407
2
  _cairo_output_stream_printf (surface->output,
2408
2
             "1 0 0 -1 0 %f cm\n",
2409
2
             surface->height);
2410
2
    }
2411
2
    if (unlikely (status))
2412
0
  return status;
2413
2414
2
    surface->content = surface->pdf_stream.self;
2415
2416
2
    _cairo_output_stream_printf (surface->output, "q\n");
2417
2
    _cairo_pdf_operators_reset (&surface->pdf_operators);
2418
2419
2
    return _cairo_output_stream_get_status (surface->output);
2420
2
}
2421
2422
static cairo_int_status_t
2423
_cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
2424
2
{
2425
2
    cairo_int_status_t status;
2426
2427
2
    assert (surface->pdf_stream.active == TRUE);
2428
2
    assert (surface->group_stream.active == FALSE);
2429
2430
2
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
2431
2
    if (unlikely (status))
2432
0
  return status;
2433
2434
2
    _cairo_output_stream_printf (surface->output, "Q\n");
2435
2
    status = _cairo_pdf_surface_close_stream (surface);
2436
2
    if (unlikely (status))
2437
0
  return status;
2438
2439
2
    _cairo_pdf_surface_update_object (surface, surface->content_resources);
2440
2
    _cairo_output_stream_printf (surface->output,
2441
2
         "%d 0 obj\n",
2442
2
         surface->content_resources.id);
2443
2
    _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
2444
2
    _cairo_output_stream_printf (surface->output,
2445
2
         "endobj\n");
2446
2447
2
    return _cairo_output_stream_get_status (surface->output);
2448
2
}
2449
2450
static void
2451
_cairo_pdf_source_surface_entry_pluck (void *entry, void *closure)
2452
0
{
2453
0
    cairo_pdf_source_surface_entry_t *surface_entry = entry;
2454
0
    cairo_hash_table_t *patterns = closure;
2455
2456
0
    _cairo_hash_table_remove (patterns, &surface_entry->base);
2457
0
    free (surface_entry->unique_id);
2458
2459
0
    free (surface_entry);
2460
0
}
2461
2462
static cairo_status_t
2463
_cairo_pdf_surface_finish (void *abstract_surface)
2464
2
{
2465
2
    cairo_pdf_surface_t *surface = abstract_surface;
2466
2
    long long offset;
2467
2
    cairo_pdf_resource_t catalog;
2468
2
    cairo_status_t status, status2;
2469
2
    int size, i;
2470
2
    cairo_pdf_source_surface_t doc_surface;
2471
2
    cairo_pdf_jbig2_global_t *global;
2472
2
    char *label;
2473
2
    cairo_pdf_resource_t xref_res;
2474
2475
    /* Some of the data may be in an inconistent state if there is an error status. */
2476
2
    if (surface->base.status != CAIRO_STATUS_SUCCESS)
2477
0
  goto CLEANUP;
2478
2479
2
    _cairo_pdf_surface_clear (surface);
2480
2481
2
    status = _cairo_pdf_surface_open_object_stream (surface);
2482
2
    if (unlikely (status))
2483
0
  return status;
2484
2485
    /* Emit unbounded surfaces */
2486
2
    _cairo_pdf_surface_write_patterns_and_smask_groups (surface, TRUE);
2487
2488
2
    status = surface->base.status;
2489
2
    if (status == CAIRO_STATUS_SUCCESS)
2490
2
  status = _cairo_pdf_surface_emit_font_subsets (surface);
2491
2492
2
    status = _cairo_pdf_surface_write_pages (surface);
2493
2
    if (unlikely (status))
2494
0
  return status;
2495
2496
2
    status = _cairo_pdf_interchange_write_document_objects (surface);
2497
2
    if (unlikely (status))
2498
0
  return status;
2499
2500
2
    catalog = _cairo_pdf_surface_new_object (surface);
2501
2
    if (catalog.id == 0)
2502
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2503
2504
2
    status = _cairo_pdf_surface_write_catalog (surface, catalog);
2505
2
    if (unlikely (status))
2506
0
  return status;
2507
2508
2
    status = _cairo_pdf_surface_close_object_stream (surface);
2509
2
    if (unlikely (status))
2510
0
  return status;
2511
2512
2
    if (surface->pdf_version >= CAIRO_PDF_VERSION_1_5)
2513
2
    {
2514
2
  xref_res = _cairo_pdf_surface_new_object (surface);
2515
2
  status = _cairo_pdf_surface_write_xref_stream (surface,
2516
2
                   xref_res,
2517
2
                   catalog,
2518
2
                   surface->docinfo_res,
2519
2
                   &offset);
2520
2
    } else {
2521
0
  offset = _cairo_pdf_surface_write_xref (surface);
2522
0
  _cairo_output_stream_printf (surface->output,
2523
0
             "trailer\n"
2524
0
             "<< /Size %d\n"
2525
0
             "   /Root %d 0 R\n"
2526
0
             "   /Info %d 0 R\n"
2527
0
             ">>\n",
2528
0
             surface->next_available_resource.id,
2529
0
             catalog.id,
2530
0
             surface->docinfo_res.id);
2531
0
    }
2532
2
    _cairo_output_stream_printf (surface->output,
2533
2
         "startxref\n"
2534
2
         "%lld\n"
2535
2
         "%%%%EOF\n",
2536
2
         offset);
2537
2538
2
  CLEANUP:
2539
2540
    /* pdf_operators has already been flushed when the last stream was
2541
     * closed so we should never be writing anything here - however,
2542
     * the stream may itself be in an error state. */
2543
2
    status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
2544
2
    if (status == CAIRO_STATUS_SUCCESS)
2545
2
  status = status2;
2546
2547
    /* close any active streams still open due to fatal errors */
2548
2
    status2 = _cairo_pdf_surface_close_stream (surface);
2549
2
    if (status == CAIRO_STATUS_SUCCESS)
2550
2
  status = status2;
2551
2552
2
    if (surface->group_stream.stream != NULL) {
2553
0
  status2 = _cairo_output_stream_destroy (surface->group_stream.stream);
2554
0
  if (status == CAIRO_STATUS_SUCCESS)
2555
0
      status = status2;
2556
0
    }
2557
2
    if (surface->group_stream.mem_stream != NULL) {
2558
0
  status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
2559
0
  if (status == CAIRO_STATUS_SUCCESS)
2560
0
      status = status2;
2561
0
    }
2562
2
    if (surface->pdf_stream.active)
2563
0
  surface->output = surface->pdf_stream.old_output;
2564
2
    if (surface->group_stream.active)
2565
0
  surface->output = surface->group_stream.old_output;
2566
2567
    /* and finish the pdf surface */
2568
2
    status2 = _cairo_output_stream_destroy (surface->output);
2569
2
    if (status == CAIRO_STATUS_SUCCESS)
2570
2
  status = status2;
2571
2572
2
    _cairo_pdf_group_resources_fini (&surface->resources);
2573
2574
2
    _cairo_array_fini (&surface->objects);
2575
2
    _cairo_array_fini (&surface->pages);
2576
2
    _cairo_array_fini (&surface->rgb_linear_functions);
2577
2
    _cairo_array_fini (&surface->alpha_linear_functions);
2578
2
    _cairo_array_fini (&surface->page_patterns);
2579
2
    _cairo_array_fini (&surface->page_surfaces);
2580
2
    _cairo_array_fini (&surface->object_stream.objects);
2581
2582
2
    size = _cairo_array_num_elements (&surface->doc_surfaces);
2583
2
    for (i = 0; i < size; i++) {
2584
0
  _cairo_array_copy_element (&surface->doc_surfaces, i, &doc_surface);
2585
0
  cairo_surface_destroy (doc_surface.surface);
2586
0
    }
2587
2
    _cairo_array_fini (&surface->doc_surfaces);
2588
2
    _cairo_hash_table_foreach (surface->all_surfaces,
2589
2
             _cairo_pdf_source_surface_entry_pluck,
2590
2
             surface->all_surfaces);
2591
2
    _cairo_hash_table_destroy (surface->all_surfaces);
2592
2
    _cairo_array_fini (&surface->smask_groups);
2593
2
    _cairo_array_fini (&surface->fonts);
2594
2
    _cairo_array_fini (&surface->knockout_group);
2595
2
    _cairo_array_fini (&surface->page_annots);
2596
2
    _cairo_array_fini (&surface->forward_links);
2597
2598
2
    if (surface->font_subsets) {
2599
0
  _cairo_scaled_font_subsets_destroy (surface->font_subsets);
2600
0
  surface->font_subsets = NULL;
2601
0
    }
2602
2603
2
    size = _cairo_array_num_elements (&surface->jbig2_global);
2604
2
    for (i = 0; i < size; i++) {
2605
0
  global = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, i);
2606
0
  free(global->id);
2607
0
  if (!global->emitted)
2608
0
      return _cairo_error (CAIRO_STATUS_JBIG2_GLOBAL_MISSING);
2609
0
    }
2610
2
    _cairo_array_fini (&surface->jbig2_global);
2611
2
    _cairo_array_fini (&surface->page_heights);
2612
2613
2
    size = _cairo_array_num_elements (&surface->page_labels);
2614
4
    for (i = 0; i < size; i++) {
2615
2
  _cairo_array_copy_element (&surface->page_labels, i, &label);
2616
2
  free (label);
2617
2
    }
2618
2
    _cairo_array_fini (&surface->page_labels);
2619
2620
2
    _cairo_surface_clipper_reset (&surface->clipper);
2621
2622
2
    _cairo_pdf_interchange_fini (surface);
2623
2624
2
    return status;
2625
2
}
2626
2627
static cairo_int_status_t
2628
_cairo_pdf_surface_start_page (void *abstract_surface)
2629
2
{
2630
2
    cairo_pdf_surface_t *surface = abstract_surface;
2631
2
    cairo_pdf_resource_t page;
2632
2
    cairo_int_status_t status;
2633
2634
    /* Document header */
2635
2
    if (! surface->header_emitted) {
2636
2
  const char *version;
2637
2638
2
  switch (surface->pdf_version) {
2639
0
  case CAIRO_PDF_VERSION_1_4:
2640
0
      version = "1.4";
2641
0
      break;
2642
0
  case CAIRO_PDF_VERSION_1_5:
2643
0
      version = "1.5";
2644
0
      break;
2645
0
  case CAIRO_PDF_VERSION_1_6:
2646
0
      version = "1.6";
2647
0
      break;
2648
0
  default:
2649
2
  case CAIRO_PDF_VERSION_1_7:
2650
2
      version = "1.7";
2651
2
      break;
2652
2
  }
2653
2654
2
  _cairo_output_stream_printf (surface->output,
2655
2
             "%%PDF-%s\n", version);
2656
2
  _cairo_output_stream_printf (surface->output,
2657
2
             "%%%c%c%c%c\n", 181, 237, 174, 251);
2658
2
  surface->header_emitted = TRUE;
2659
2
    }
2660
2661
2
    _cairo_pdf_group_resources_clear (&surface->resources);
2662
2
    surface->in_xobject = FALSE;
2663
2664
2
    page = _cairo_pdf_surface_new_object (surface);
2665
2
    if (page.id == 0)
2666
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2667
2668
2
    status = _cairo_array_append (&surface->pages, &page);
2669
2
    if (unlikely (status))
2670
0
  return status;
2671
2672
2
    return CAIRO_STATUS_SUCCESS;
2673
2
}
2674
2675
static cairo_int_status_t
2676
_cairo_pdf_surface_has_fallback_images (void    *abstract_surface,
2677
          cairo_bool_t   has_fallbacks)
2678
2
{
2679
2
    cairo_int_status_t status;
2680
2
    cairo_pdf_surface_t *surface = abstract_surface;
2681
2
    cairo_box_double_t bbox;
2682
2683
2
    surface->has_fallback_images = has_fallbacks;
2684
2
    surface->in_xobject = has_fallbacks;
2685
2
    bbox.p1.x = 0;
2686
2
    bbox.p1.y = 0;
2687
2
    bbox.p2.x = surface->width;
2688
2
    bbox.p2.y = surface->height;
2689
2
    status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, has_fallbacks, has_fallbacks);
2690
2
    if (unlikely (status))
2691
0
  return status;
2692
2693
2
    return CAIRO_STATUS_SUCCESS;
2694
2
}
2695
2696
static cairo_bool_t
2697
_cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
2698
2
{
2699
2
    return TRUE;
2700
2
}
2701
2702
static cairo_bool_t
2703
_cairo_pdf_surface_requires_thumbnail_image (void *abstract_surface,
2704
               int  *width,
2705
               int  *height)
2706
2
{
2707
2
    cairo_pdf_surface_t *surface = abstract_surface;
2708
2709
2
    if (surface->thumbnail_width > 0 && surface->thumbnail_height > 0) {
2710
0
  *width = surface->thumbnail_width;
2711
0
  *height = surface->thumbnail_height;
2712
0
  return TRUE;
2713
0
    }
2714
2715
2
    return FALSE;
2716
2
}
2717
2718
static cairo_int_status_t
2719
_cairo_pdf_surface_set_thumbnail_image (void                  *abstract_surface,
2720
          cairo_image_surface_t *image)
2721
0
{
2722
0
    cairo_pdf_surface_t *surface = abstract_surface;
2723
2724
0
    surface->thumbnail_image =  (cairo_image_surface_t *)cairo_surface_reference(&image->base);
2725
2726
0
    return CAIRO_STATUS_SUCCESS;
2727
0
}
2728
2729
static cairo_int_status_t
2730
_cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t          *surface,
2731
               const cairo_pattern_t        *source,
2732
               const cairo_rectangle_int_t  *extents,
2733
               cairo_pdf_source_surface_entry_t **pdf_source,
2734
               double                       *x_offset,
2735
               double                       *y_offset,
2736
               cairo_rectangle_int_t        *source_extents)
2737
0
{
2738
0
    cairo_image_surface_t *image;
2739
0
    cairo_surface_t *pad_image;
2740
0
    void *image_extra;
2741
0
    cairo_int_status_t status;
2742
0
    int w, h;
2743
0
    cairo_box_t box;
2744
0
    cairo_rectangle_int_t rect;
2745
0
    cairo_surface_pattern_t pad_pattern;
2746
2747
0
    status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source,
2748
0
                   &image, &image_extra);
2749
0
    if (unlikely (status))
2750
0
        return status;
2751
2752
0
    pad_image = &image->base;
2753
2754
    /* get the operation extents in pattern space */
2755
0
    _cairo_box_from_rectangle (&box, extents);
2756
0
    _cairo_matrix_transform_bounding_box_fixed (&source->matrix, &box, NULL);
2757
0
    _cairo_box_round_to_rectangle (&box, &rect);
2758
2759
    /* Check if image needs padding to fill extents */
2760
0
    w = image->width;
2761
0
    h = image->height;
2762
0
    if (_cairo_fixed_integer_ceil(box.p1.x) < 0 ||
2763
0
  _cairo_fixed_integer_ceil(box.p1.y) < 0 ||
2764
0
  _cairo_fixed_integer_floor(box.p2.x) > w ||
2765
0
  _cairo_fixed_integer_floor(box.p2.y) > h)
2766
0
    {
2767
0
  pad_image = _cairo_image_surface_create_with_content (image->base.content,
2768
0
                    rect.width,
2769
0
                    rect.height);
2770
0
  if (pad_image->status) {
2771
0
      status = pad_image->status;
2772
0
      goto BAIL;
2773
0
  }
2774
2775
0
  _cairo_pattern_init_for_surface (&pad_pattern, &image->base);
2776
0
  cairo_matrix_init_translate (&pad_pattern.base.matrix, rect.x, rect.y);
2777
0
  pad_pattern.base.extend = CAIRO_EXTEND_PAD;
2778
0
  status = _cairo_surface_paint (pad_image,
2779
0
               CAIRO_OPERATOR_SOURCE, &pad_pattern.base,
2780
0
               NULL);
2781
0
        _cairo_pattern_fini (&pad_pattern.base);
2782
0
        if (unlikely (status))
2783
0
            goto BAIL;
2784
0
    }
2785
2786
0
    status = _cairo_pdf_surface_add_source_surface (surface,
2787
0
                pad_image,
2788
0
                NULL,
2789
0
                CAIRO_OPERATOR_OVER, /* not used for images */
2790
0
                source->filter,
2791
0
                FALSE, /* stencil mask */
2792
0
                FALSE, /* smask */
2793
0
                FALSE, /* need_transp_group */
2794
0
                extents,
2795
0
                NULL, /* smask_res */
2796
0
                pdf_source,
2797
0
                x_offset,
2798
0
                y_offset,
2799
0
                source_extents);
2800
0
    if (unlikely (status))
2801
0
        goto BAIL;
2802
2803
0
    if (pad_image != &image->base) {
2804
  /* If using a padded image, replace _add_source_surface
2805
   * x/y_offset with padded image offset. Note:
2806
   * _add_source_surface only sets a non zero x/y_offset for
2807
   * RASTER_SOURCE patterns. _add_source_surface will always set
2808
   * x/y_offset to 0 for surfaces so we can ignore the returned
2809
   * offset and replace it with the offset required for the
2810
   * padded image */
2811
0
  *x_offset = rect.x;
2812
0
  *y_offset = rect.y;
2813
0
    }
2814
2815
0
BAIL:
2816
0
    if (pad_image != &image->base)
2817
0
        cairo_surface_destroy (pad_image);
2818
2819
0
    _cairo_pdf_surface_release_source_image_from_pattern (surface, source, image, image_extra);
2820
2821
0
    return status;
2822
0
}
2823
2824
/* Emit alpha channel from the image into stream_res.
2825
 */
2826
static cairo_int_status_t
2827
_cairo_pdf_surface_emit_smask (cairo_pdf_surface_t  *surface,
2828
             cairo_image_surface_t  *image,
2829
             cairo_bool_t              stencil_mask,
2830
             cairo_bool_t              interpolate,
2831
             cairo_pdf_resource_t *stream_res)
2832
0
{
2833
0
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
2834
0
    char *alpha;
2835
0
    unsigned long alpha_size;
2836
0
    uint32_t *pixel32;
2837
0
    uint8_t *pixel8;
2838
0
    int i, x, y, bit, a;
2839
0
    cairo_image_transparency_t transparency;
2840
2841
    /* This is the only image format we support, which simplifies things. */
2842
0
    assert (image->format == CAIRO_FORMAT_ARGB32 ||
2843
0
      image->format == CAIRO_FORMAT_RGB24 ||
2844
0
      image->format == CAIRO_FORMAT_A8 ||
2845
0
      image->format == CAIRO_FORMAT_A1 );
2846
2847
0
    transparency = _cairo_image_analyze_transparency (image);
2848
0
    if (stencil_mask) {
2849
0
  assert (transparency == CAIRO_IMAGE_IS_OPAQUE ||
2850
0
    transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA);
2851
0
    } else {
2852
0
  assert (transparency != CAIRO_IMAGE_IS_OPAQUE);
2853
0
    }
2854
2855
0
    if (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA || transparency == CAIRO_IMAGE_IS_OPAQUE) {
2856
0
  alpha_size = (image->width + 7) / 8 * image->height;
2857
0
  alpha = _cairo_malloc_ab ((image->width+7) / 8, image->height);
2858
0
    } else {
2859
0
  alpha_size = image->height * image->width;
2860
0
  alpha = _cairo_malloc_ab (image->height, image->width);
2861
0
    }
2862
2863
0
    if (unlikely (alpha == NULL)) {
2864
0
  status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2865
0
  goto CLEANUP;
2866
0
    }
2867
2868
0
    i = 0;
2869
0
    for (y = 0; y < image->height; y++) {
2870
0
  if (transparency == CAIRO_IMAGE_IS_OPAQUE) {
2871
0
      for (x = 0; x < (image->width + 7) / 8; x++)
2872
0
    alpha[i++] = 0xff;
2873
0
  } else if (image->format == CAIRO_FORMAT_A1) {
2874
0
      pixel8 = (uint8_t *) (image->data + y * image->stride);
2875
2876
0
      for (x = 0; x < (image->width + 7) / 8; x++, pixel8++) {
2877
0
    a = *pixel8;
2878
0
    a = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a);
2879
0
    alpha[i++] = a;
2880
0
      }
2881
0
  } else {
2882
0
      pixel8 = (uint8_t *) (image->data + y * image->stride);
2883
0
      pixel32 = (uint32_t *) (image->data + y * image->stride);
2884
0
      bit = 7;
2885
0
      for (x = 0; x < image->width; x++) {
2886
0
    if (image->format == CAIRO_FORMAT_ARGB32) {
2887
0
        a = (*pixel32 & 0xff000000) >> 24;
2888
0
        pixel32++;
2889
0
    } else {
2890
0
        a = *pixel8;
2891
0
        pixel8++;
2892
0
    }
2893
2894
0
    if (transparency == CAIRO_IMAGE_HAS_ALPHA) {
2895
0
        alpha[i++] = a;
2896
0
    } else { /* transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA or CAIRO_IMAGE_IS_OPAQUE */
2897
0
        if (bit == 7)
2898
0
      alpha[i] = 0;
2899
0
        if (a != 0)
2900
0
      alpha[i] |= (1 << bit);
2901
0
        bit--;
2902
0
        if (bit < 0) {
2903
0
      bit = 7;
2904
0
      i++;
2905
0
        }
2906
0
    }
2907
0
      }
2908
0
      if (bit != 7)
2909
0
    i++;
2910
0
  }
2911
0
    }
2912
2913
0
    if (stencil_mask) {
2914
0
  status = _cairo_pdf_surface_open_stream (surface,
2915
0
             stream_res,
2916
0
             TRUE,
2917
0
             "   /Type /XObject\n"
2918
0
             "   /Subtype /Image\n"
2919
0
             "   /ImageMask true\n"
2920
0
             "   /Width %d\n"
2921
0
             "   /Height %d\n"
2922
0
             "   /Interpolate %s\n"
2923
0
             "   /BitsPerComponent 1\n"
2924
0
             "   /Decode [1 0]\n",
2925
0
             image->width, image->height,
2926
0
             interpolate ? "true" : "false");
2927
0
    } else {
2928
0
  status = _cairo_pdf_surface_open_stream (surface,
2929
0
             stream_res,
2930
0
             TRUE,
2931
0
             "   /Type /XObject\n"
2932
0
             "   /Subtype /Image\n"
2933
0
             "   /Width %d\n"
2934
0
             "   /Height %d\n"
2935
0
             "   /ColorSpace /DeviceGray\n"
2936
0
             "   /Interpolate %s\n"
2937
0
             "   /BitsPerComponent %d\n",
2938
0
             image->width, image->height,
2939
0
             interpolate ? "true" : "false",
2940
0
             transparency == CAIRO_IMAGE_HAS_ALPHA ? 8 : 1);
2941
0
    }
2942
0
    if (unlikely (status))
2943
0
  goto CLEANUP_ALPHA;
2944
2945
0
    _cairo_output_stream_write (surface->output, alpha, alpha_size);
2946
0
    status = _cairo_pdf_surface_close_stream (surface);
2947
2948
0
 CLEANUP_ALPHA:
2949
0
    free (alpha);
2950
0
 CLEANUP:
2951
0
    return status;
2952
0
}
2953
2954
/**
2955
 * _cairo_pdf_surface_emit_image:
2956
 * @surface: the pdf surface
2957
 * @image_surf: The image to write
2958
 * @surface_entry: Contains image resource, smask resource, interpolate and stencil mask parameters.
2959
 *
2960
 * Emit an image stream using the @image_res resource and write out
2961
 * the image data from @image_surf. If @smask_res is not null, @smask_res will
2962
 * be specified as the smask for the image. Otherwise emit the an smask if
2963
 * the image is requires one.
2964
 **/
2965
static cairo_int_status_t
2966
_cairo_pdf_surface_emit_image (cairo_pdf_surface_t              *surface,
2967
                               cairo_image_surface_t            *image_surf,
2968
             cairo_pdf_source_surface_entry_t *surface_entry)
2969
0
{
2970
0
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
2971
0
    char *data;
2972
0
    unsigned long data_size;
2973
0
    uint32_t *pixel;
2974
0
    int i, x, y, bit;
2975
0
    cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
2976
0
    cairo_bool_t need_smask;
2977
0
    cairo_image_color_t color;
2978
0
    cairo_image_surface_t *image;
2979
0
    cairo_image_transparency_t transparency;
2980
0
    char smask_buf[30];
2981
2982
0
    image  = image_surf;
2983
0
    if (image->format != CAIRO_FORMAT_RGB24 &&
2984
0
  image->format != CAIRO_FORMAT_ARGB32 &&
2985
0
  image->format != CAIRO_FORMAT_A8 &&
2986
0
  image->format != CAIRO_FORMAT_A1)
2987
0
    {
2988
0
  cairo_surface_t *surf;
2989
0
  cairo_surface_pattern_t pattern;
2990
2991
0
  surf = _cairo_image_surface_create_with_content (image_surf->base.content,
2992
0
               image_surf->width,
2993
0
               image_surf->height);
2994
0
  image = (cairo_image_surface_t *) surf;
2995
0
  if (surf->status) {
2996
0
      status = surf->status;
2997
0
      goto CLEANUP;
2998
0
  }
2999
3000
0
  _cairo_pattern_init_for_surface (&pattern, &image_surf->base);
3001
0
  status = _cairo_surface_paint (surf,
3002
0
               CAIRO_OPERATOR_SOURCE, &pattern.base,
3003
0
               NULL);
3004
0
        _cairo_pattern_fini (&pattern.base);
3005
0
        if (unlikely (status))
3006
0
            goto CLEANUP;
3007
0
    }
3008
3009
0
    if (surface_entry->smask || surface_entry->stencil_mask) {
3010
0
  return _cairo_pdf_surface_emit_smask (surface, image,
3011
0
                surface_entry->stencil_mask,
3012
0
                surface_entry->interpolate,
3013
0
                &surface_entry->surface_res);
3014
0
    }
3015
3016
0
    color = _cairo_image_analyze_color (image);
3017
0
    switch (color) {
3018
0
        default:
3019
0
  case CAIRO_IMAGE_UNKNOWN_COLOR:
3020
0
      ASSERT_NOT_REACHED;
3021
0
  case CAIRO_IMAGE_IS_COLOR:
3022
0
      data_size = image->height * image->width * 3;
3023
0
      data = _cairo_malloc_abc (image->width, image->height, 3);
3024
0
      break;
3025
3026
0
  case CAIRO_IMAGE_IS_GRAYSCALE:
3027
0
      data_size = image->height * image->width;
3028
0
      data = _cairo_malloc_ab (image->width, image->height);
3029
0
      break;
3030
0
  case CAIRO_IMAGE_IS_MONOCHROME:
3031
0
      data_size = (image->width + 7) / 8 * image->height;
3032
0
      data = _cairo_malloc_ab ((image->width+7) / 8, image->height);
3033
0
      break;
3034
0
    }
3035
0
    if (unlikely (data == NULL)) {
3036
0
  status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3037
0
  goto CLEANUP;
3038
0
    }
3039
3040
0
    i = 0;
3041
0
    for (y = 0; y < image->height; y++) {
3042
0
  pixel = (uint32_t *) (image->data + y * image->stride);
3043
3044
0
  bit = 7;
3045
0
  for (x = 0; x < image->width; x++, pixel++) {
3046
0
      int r, g, b;
3047
3048
      /* XXX: We're un-premultiplying alpha here. My reading of the PDF
3049
       * specification suggests that we should be able to avoid having
3050
       * to do this by filling in the SMask's Matte dictionary
3051
       * appropriately, but my attempts to do that so far have
3052
       * failed. */
3053
0
      if (image->format == CAIRO_FORMAT_ARGB32) {
3054
0
    uint8_t a;
3055
0
    a = (*pixel & 0xff000000) >> 24;
3056
0
    if (a == 0) {
3057
0
        r = g = b = 0;
3058
0
    } else {
3059
0
        r = (((*pixel & 0xff0000) >> 16) * 255 + a / 2) / a;
3060
0
        g = (((*pixel & 0x00ff00) >>  8) * 255 + a / 2) / a;
3061
0
        b = (((*pixel & 0x0000ff) >>  0) * 255 + a / 2) / a;
3062
0
    }
3063
0
      } else if (image->format == CAIRO_FORMAT_RGB24) {
3064
0
    r = (*pixel & 0x00ff0000) >> 16;
3065
0
    g = (*pixel & 0x0000ff00) >>  8;
3066
0
    b = (*pixel & 0x000000ff) >>  0;
3067
0
      } else {
3068
0
    r = g = b = 0;
3069
0
      }
3070
3071
0
      switch (color) {
3072
0
    case CAIRO_IMAGE_IS_COLOR:
3073
0
    case CAIRO_IMAGE_UNKNOWN_COLOR:
3074
0
        data[i++] = r;
3075
0
        data[i++] = g;
3076
0
        data[i++] = b;
3077
0
        break;
3078
3079
0
    case CAIRO_IMAGE_IS_GRAYSCALE:
3080
0
        data[i++] = r;
3081
0
        break;
3082
3083
0
    case CAIRO_IMAGE_IS_MONOCHROME:
3084
0
        if (bit == 7)
3085
0
      data[i] = 0;
3086
0
        if (r != 0)
3087
0
      data[i] |= (1 << bit);
3088
0
        bit--;
3089
0
        if (bit < 0) {
3090
0
      bit = 7;
3091
0
      i++;
3092
0
        }
3093
0
        break;
3094
0
      }
3095
0
  }
3096
0
  if (bit != 7)
3097
0
      i++;
3098
0
    }
3099
3100
0
    if (surface_entry->smask_res.id != 0) {
3101
0
  need_smask = TRUE;
3102
0
  smask = surface_entry->smask_res;
3103
0
    } else {
3104
0
  need_smask = FALSE;
3105
0
  if (image->format == CAIRO_FORMAT_ARGB32 ||
3106
0
      image->format == CAIRO_FORMAT_A8 ||
3107
0
      image->format == CAIRO_FORMAT_A1)
3108
0
  {
3109
0
      transparency = _cairo_image_analyze_transparency (image);
3110
0
      if (transparency != CAIRO_IMAGE_IS_OPAQUE) {
3111
0
    need_smask = TRUE;
3112
0
    smask = _cairo_pdf_surface_new_object (surface);
3113
0
    if (smask.id == 0) {
3114
0
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3115
0
        goto CLEANUP_RGB;
3116
0
    }
3117
3118
0
    status = _cairo_pdf_surface_emit_smask (surface, image, FALSE, surface_entry->interpolate, &smask);
3119
0
    if (unlikely (status))
3120
0
        goto CLEANUP_RGB;
3121
0
      }
3122
0
  }
3123
0
    }
3124
3125
0
    if (need_smask)
3126
0
  snprintf(smask_buf, sizeof(smask_buf), "   /SMask %d 0 R\n", smask.id);
3127
0
    else
3128
0
  smask_buf[0] = 0;
3129
3130
0
    status = _cairo_pdf_surface_open_stream (surface,
3131
0
               &surface_entry->surface_res,
3132
0
               TRUE,
3133
0
               "   /Type /XObject\n"
3134
0
               "   /Subtype /Image\n"
3135
0
               "   /Width %d\n"
3136
0
               "   /Height %d\n"
3137
0
               "   /ColorSpace %s\n"
3138
0
               "   /Interpolate %s\n"
3139
0
               "   /BitsPerComponent %d\n"
3140
0
               "%s",
3141
0
               image->width,
3142
0
               image->height,
3143
0
               color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray",
3144
0
               surface_entry->interpolate ? "true" : "false",
3145
0
               color == CAIRO_IMAGE_IS_MONOCHROME? 1 : 8,
3146
0
               smask_buf);
3147
0
    if (unlikely (status))
3148
0
  goto CLEANUP_RGB;
3149
3150
0
#undef IMAGE_DICTIONARY
3151
3152
0
    _cairo_output_stream_write (surface->output, data, data_size);
3153
0
    status = _cairo_pdf_surface_close_stream (surface);
3154
3155
0
CLEANUP_RGB:
3156
0
    free (data);
3157
0
CLEANUP:
3158
0
    if (image != image_surf)
3159
0
  cairo_surface_destroy (&image->base);
3160
3161
0
    return status;
3162
0
}
3163
3164
static cairo_int_status_t
3165
_cairo_pdf_surface_lookup_jbig2_global (cairo_pdf_surface_t       *surface,
3166
          const unsigned char       *global_id,
3167
          unsigned long              global_id_length,
3168
          cairo_pdf_jbig2_global_t **entry)
3169
0
{
3170
0
    cairo_pdf_jbig2_global_t global;
3171
0
    int size, i;
3172
0
    cairo_int_status_t status;
3173
3174
0
    size = _cairo_array_num_elements (&surface->jbig2_global);
3175
0
    for (i = 0; i < size; i++) {
3176
0
  *entry = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, i);
3177
0
  if ((*entry)->id && global_id && (*entry)->id_length == global_id_length
3178
0
      && memcmp((*entry)->id, global_id, global_id_length) == 0) {
3179
0
      return CAIRO_STATUS_SUCCESS;
3180
0
  }
3181
0
    }
3182
3183
0
    global.id = _cairo_malloc (global_id_length);
3184
0
    if (unlikely (global.id == NULL)) {
3185
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3186
0
    }
3187
3188
0
    memcpy (global.id, global_id, global_id_length);
3189
0
    global.id_length = global_id_length;
3190
0
    global.res = _cairo_pdf_surface_new_object (surface);
3191
0
    if (global.res.id == 0) {
3192
0
  free(global.id);
3193
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3194
0
    }
3195
3196
0
    global.emitted = FALSE;
3197
0
    status = _cairo_array_append (&surface->jbig2_global, &global);
3198
0
    if (unlikely(status))
3199
0
  return status;
3200
3201
0
    size = _cairo_array_num_elements (&surface->jbig2_global);
3202
0
    *entry = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, size - 1);
3203
0
    return CAIRO_STATUS_SUCCESS;
3204
0
}
3205
3206
static cairo_int_status_t
3207
_cairo_pdf_surface_emit_jbig2_image (cairo_pdf_surface_t              *surface,
3208
             cairo_surface_t                *source,
3209
             cairo_pdf_source_surface_entry_t *surface_entry,
3210
             cairo_bool_t                      test)
3211
0
{
3212
0
    cairo_int_status_t status;
3213
0
    const unsigned char *mime_data;
3214
0
    unsigned long mime_data_length;
3215
0
    cairo_image_info_t info;
3216
0
    const unsigned char *global_id;
3217
0
    unsigned long global_id_length;
3218
0
    const unsigned char *global_data;
3219
0
    unsigned long global_data_length;
3220
0
    cairo_pdf_jbig2_global_t *global_entry = NULL; /* hide compiler warning */
3221
0
    char smask_buf[30];
3222
0
    char decode_parms_buf[100];
3223
3224
0
    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2,
3225
0
         &mime_data, &mime_data_length);
3226
0
    if (mime_data == NULL)
3227
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
3228
3229
0
    status = _cairo_image_info_get_jbig2_info (&info, mime_data, mime_data_length);
3230
0
    if (status)
3231
0
  return status;
3232
3233
    /* At this point we know emitting jbig2 will succeed. */
3234
0
    if (test)
3235
0
  return CAIRO_STATUS_SUCCESS;
3236
3237
0
    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
3238
0
         &global_id, &global_id_length);
3239
0
    if (global_id && global_id_length > 0) {
3240
0
  status = _cairo_pdf_surface_lookup_jbig2_global (surface, global_id, global_id_length, &global_entry);
3241
0
  if (unlikely(status))
3242
0
      return status;
3243
3244
0
  if (!global_entry->emitted) {
3245
0
      cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL,
3246
0
           &global_data, &global_data_length);
3247
0
      if (global_data) {
3248
0
    status = _cairo_pdf_surface_open_stream (surface, &global_entry->res, FALSE, NULL);
3249
0
    if (unlikely(status))
3250
0
        return status;
3251
3252
0
    _cairo_output_stream_write (surface->output, global_data, global_data_length);
3253
0
    status = _cairo_pdf_surface_close_stream (surface);
3254
0
    if (unlikely(status))
3255
0
        return status;
3256
3257
0
    global_entry->emitted = TRUE;
3258
0
      }
3259
0
  }
3260
3261
0
  snprintf(decode_parms_buf, sizeof(decode_parms_buf),
3262
0
     "   /DecodeParms << /JBIG2Globals %d 0 R >>\n", global_entry->res.id);
3263
0
    } else {
3264
0
  decode_parms_buf[0] = 0;
3265
0
    }
3266
3267
0
    if (surface_entry->smask_res.id)
3268
0
  snprintf(smask_buf, sizeof(smask_buf), "   /SMask %d 0 R\n", surface_entry->smask_res.id);
3269
0
    else
3270
0
  smask_buf[0] = 0;
3271
3272
0
    if (surface_entry->stencil_mask) {
3273
0
  status = _cairo_pdf_surface_open_stream (surface,
3274
0
             &surface_entry->surface_res,
3275
0
             FALSE,
3276
0
             "   /Type /XObject\n"
3277
0
             "   /Subtype /Image\n"
3278
0
             "   /ImageMask true\n"
3279
0
             "   /Width %d\n"
3280
0
             "   /Height %d\n"
3281
0
             "   /Interpolate %s\n"
3282
0
             "   /BitsPerComponent 1\n"
3283
0
             "   /Decode [1 0]\n"
3284
0
             "   /Filter /JPXDecode\n"
3285
0
             "%s",
3286
0
             info.width,
3287
0
             info.height,
3288
0
             surface_entry->interpolate ? "true" : "false",
3289
0
             decode_parms_buf);
3290
0
    } else {
3291
0
  status = _cairo_pdf_surface_open_stream (surface,
3292
0
             &surface_entry->surface_res,
3293
0
             FALSE,
3294
0
             "   /Type /XObject\n"
3295
0
             "   /Subtype /Image\n"
3296
0
             "   /Width %d\n"
3297
0
             "   /Height %d\n"
3298
0
             "   /ColorSpace /DeviceGray\n"
3299
0
             "   /BitsPerComponent 1\n"
3300
0
             "   /Interpolate %s\n"
3301
0
             "%s"
3302
0
             "   /Filter /JBIG2Decode\n"
3303
0
             "%s",
3304
0
             info.width,
3305
0
             info.height,
3306
0
             surface_entry->interpolate ? "true" : "false",
3307
0
             smask_buf,
3308
0
             decode_parms_buf);
3309
0
    }
3310
0
    if (unlikely(status))
3311
0
  return status;
3312
3313
0
    _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
3314
0
    status = _cairo_pdf_surface_close_stream (surface);
3315
3316
0
    return status;
3317
0
}
3318
3319
static cairo_int_status_t
3320
_cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t              *surface,
3321
           cairo_surface_t              *source,
3322
           cairo_pdf_source_surface_entry_t *surface_entry,
3323
           cairo_bool_t                      test)
3324
0
{
3325
0
    cairo_int_status_t status;
3326
0
    const unsigned char *mime_data;
3327
0
    unsigned long mime_data_length;
3328
0
    cairo_image_info_t info;
3329
0
    char smask_buf[30];
3330
3331
0
    if (surface->pdf_version < CAIRO_PDF_VERSION_1_5)
3332
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
3333
3334
0
    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
3335
0
         &mime_data, &mime_data_length);
3336
0
    if (mime_data == NULL)
3337
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
3338
3339
0
    status = _cairo_image_info_get_jpx_info (&info, mime_data, mime_data_length);
3340
0
    if (status)
3341
0
  return status;
3342
3343
0
    if ((surface_entry->smask || surface_entry->stencil_mask) && info.num_components != 1)
3344
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
3345
3346
0
    if ((surface_entry->stencil_mask) && info.bits_per_component != 1)
3347
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
3348
3349
0
    if (surface_entry->smask_res.id)
3350
0
  snprintf(smask_buf, sizeof(smask_buf), "   /SMask %d 0 R\n", surface_entry->smask_res.id);
3351
0
    else
3352
0
  smask_buf[0] = 0;
3353
3354
    /* At this point we know emitting jpx will succeed. */
3355
0
    if (test)
3356
0
  return CAIRO_STATUS_SUCCESS;
3357
3358
0
    if (surface_entry->stencil_mask) {
3359
0
  status = _cairo_pdf_surface_open_stream (surface,
3360
0
             &surface_entry->surface_res,
3361
0
             FALSE,
3362
0
             "   /Type /XObject\n"
3363
0
             "   /Subtype /Image\n"
3364
0
             "   /ImageMask true\n"
3365
0
             "   /Width %d\n"
3366
0
             "   /Height %d\n"
3367
0
             "   /Interpolate %s\n"
3368
0
             "   /BitsPerComponent 1\n"
3369
0
             "   /Decode [1 0]\n"
3370
0
             "   /Filter /JPXDecode\n",
3371
0
             info.width,
3372
0
             info.height,
3373
0
             surface_entry->interpolate ? "true" : "false");
3374
0
    } else {
3375
0
  status = _cairo_pdf_surface_open_stream (surface,
3376
0
             &surface_entry->surface_res,
3377
0
             FALSE,
3378
0
             "   /Type /XObject\n"
3379
0
             "   /Subtype /Image\n"
3380
0
             "   /Width %d\n"
3381
0
             "   /Height %d\n"
3382
0
             "   /Interpolate %s\n"
3383
0
             "%s"
3384
0
             "   /Filter /JPXDecode\n",
3385
0
             info.width,
3386
0
             info.height,
3387
0
             surface_entry->interpolate ? "true" : "false",
3388
0
             smask_buf);
3389
0
    }
3390
0
    if (status)
3391
0
  return status;
3392
3393
0
    _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
3394
0
    status = _cairo_pdf_surface_close_stream (surface);
3395
3396
0
    return status;
3397
0
}
3398
3399
static cairo_int_status_t
3400
_cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t              *surface,
3401
            cairo_surface_t              *source,
3402
            cairo_pdf_source_surface_entry_t *surface_entry,
3403
            cairo_bool_t                      test)
3404
0
{
3405
0
    cairo_int_status_t status;
3406
0
    const unsigned char *mime_data;
3407
0
    unsigned long mime_data_length;
3408
0
    cairo_image_info_t info;
3409
0
    const char *colorspace;
3410
0
    char smask_buf[30];
3411
3412
0
    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
3413
0
         &mime_data, &mime_data_length);
3414
0
    if (unlikely (source->status))
3415
0
  return source->status;
3416
0
    if (mime_data == NULL)
3417
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
3418
3419
0
    status = _cairo_image_info_get_jpeg_info (&info, mime_data, mime_data_length);
3420
0
    if (unlikely (status))
3421
0
  return status;
3422
3423
0
    if ((surface_entry->smask || surface_entry->stencil_mask) && info.num_components != 1)
3424
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
3425
3426
0
    if ((surface_entry->stencil_mask) && info.bits_per_component != 1)
3427
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
3428
3429
0
    switch (info.num_components) {
3430
0
  case 1:
3431
0
      colorspace = "/DeviceGray";
3432
0
      break;
3433
0
  case 3:
3434
0
      colorspace = "/DeviceRGB";
3435
0
      break;
3436
0
  case 4:
3437
0
      colorspace = "/DeviceCMYK";
3438
0
      break;
3439
0
  default:
3440
0
      return CAIRO_INT_STATUS_UNSUPPORTED;
3441
0
    }
3442
3443
    /* At this point we know emitting jpeg will succeed. */
3444
0
    if (test)
3445
0
  return CAIRO_STATUS_SUCCESS;
3446
3447
0
    if (surface_entry->smask_res.id)
3448
0
  snprintf(smask_buf, sizeof(smask_buf), "   /SMask %d 0 R\n", surface_entry->smask_res.id);
3449
0
    else
3450
0
  smask_buf[0] = 0;
3451
3452
0
    if (surface_entry->stencil_mask) {
3453
0
  status = _cairo_pdf_surface_open_stream (surface,
3454
0
             &surface_entry->surface_res,
3455
0
             FALSE,
3456
0
             "   /Type /XObject\n"
3457
0
             "   /Subtype /Image\n"
3458
0
             "   /ImageMask true\n"
3459
0
             "   /Width %d\n"
3460
0
             "   /Height %d\n"
3461
0
             "   /Interpolate %s\n"
3462
0
             "   /BitsPerComponent 1\n"
3463
0
             "   /Decode [1 0]\n"
3464
0
             "   /Filter /DCTDecode\n",
3465
0
             info.width,
3466
0
             info.height,
3467
0
             surface_entry->interpolate ? "true" : "false");
3468
0
    } else {
3469
0
  status = _cairo_pdf_surface_open_stream (surface,
3470
0
             &surface_entry->surface_res,
3471
0
             FALSE,
3472
0
             "   /Type /XObject\n"
3473
0
             "   /Subtype /Image\n"
3474
0
             "   /Width %d\n"
3475
0
             "   /Height %d\n"
3476
0
             "   /ColorSpace %s\n"
3477
0
             "   /Interpolate %s\n"
3478
0
             "   /BitsPerComponent %d\n"
3479
0
             "%s"
3480
0
             "   /Filter /DCTDecode\n",
3481
0
             info.width,
3482
0
             info.height,
3483
0
             colorspace,
3484
0
             surface_entry->interpolate ? "true" : "false",
3485
0
             info.bits_per_component,
3486
0
             smask_buf);
3487
0
    }
3488
0
    if (unlikely (status))
3489
0
  return status;
3490
3491
0
    _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
3492
0
    status = _cairo_pdf_surface_close_stream (surface);
3493
3494
0
    return status;
3495
0
}
3496
3497
static cairo_int_status_t
3498
_cairo_pdf_surface_emit_ccitt_image (cairo_pdf_surface_t              *surface,
3499
             cairo_surface_t               *source,
3500
             cairo_pdf_source_surface_entry_t *surface_entry,
3501
             cairo_bool_t                      test)
3502
0
{
3503
0
    cairo_status_t status;
3504
0
    const unsigned char *ccitt_data;
3505
0
    unsigned long ccitt_data_len;
3506
0
    const unsigned char *ccitt_params_string;
3507
0
    unsigned long ccitt_params_string_len;
3508
0
    char *params, *p, *end;
3509
0
    cairo_ccitt_params_t ccitt_params;
3510
0
    char buf[300];
3511
3512
0
    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_CCITT_FAX,
3513
0
         &ccitt_data, &ccitt_data_len);
3514
0
    if (unlikely (source->status))
3515
0
  return source->status;
3516
0
    if (ccitt_data == NULL)
3517
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
3518
3519
0
    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_CCITT_FAX_PARAMS,
3520
0
         &ccitt_params_string, &ccitt_params_string_len);
3521
0
    if (unlikely (source->status))
3522
0
  return source->status;
3523
0
    if (ccitt_params_string == NULL)
3524
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
3525
3526
    /* ensure params_string is null terminated */
3527
0
    params = malloc (ccitt_params_string_len + 1);
3528
0
    memcpy (params, ccitt_params_string, ccitt_params_string_len);
3529
0
    params[ccitt_params_string_len] = 0;
3530
0
    status = _cairo_tag_parse_ccitt_params (params, &ccitt_params);
3531
0
    if (unlikely(status))
3532
0
  return source->status;
3533
3534
0
    free (params);
3535
3536
    /* At this point we know emitting jbig2 will succeed. */
3537
0
    if (test)
3538
0
  return CAIRO_STATUS_SUCCESS;
3539
3540
0
    p = buf;
3541
0
    *p = 0;
3542
0
    end = buf + sizeof(buf) - 1;
3543
0
    p += snprintf (p, end - p, "/Columns %d /Rows %d /K %d",
3544
0
         ccitt_params.columns,
3545
0
         ccitt_params.rows,
3546
0
         ccitt_params.k);
3547
0
    if (ccitt_params.end_of_line)
3548
0
  p += snprintf (p, end - p, " /EndOfLine true");
3549
3550
0
    if (ccitt_params.encoded_byte_align)
3551
0
  p += snprintf (p, end - p, " /EncodedByteAlign true");
3552
3553
0
    if (!ccitt_params.end_of_block)
3554
0
  p += snprintf (p, end - p, " /EndOfBlock false");
3555
3556
0
    if (ccitt_params.black_is_1)
3557
0
  p += snprintf (p, end - p, " /BlackIs1 true");
3558
3559
0
    if (ccitt_params.damaged_rows_before_error > 0) {
3560
0
  p += snprintf (p, end - p, " /DamagedRowsBeforeError %d",
3561
0
           ccitt_params.damaged_rows_before_error);
3562
0
    }
3563
3564
0
    if (surface_entry->stencil_mask) {
3565
0
  status = _cairo_pdf_surface_open_stream (surface,
3566
0
             &surface_entry->surface_res,
3567
0
             FALSE,
3568
0
             "   /Type /XObject\n"
3569
0
             "   /Subtype /Image\n"
3570
0
             "   /ImageMask true\n"
3571
0
             "   /Width %d\n"
3572
0
             "   /Height %d\n"
3573
0
             "   /Interpolate %s\n"
3574
0
             "   /BitsPerComponent 1\n"
3575
0
             "   /Decode [1 0]\n"
3576
0
             "   /Filter /CCITTFaxDecode\n"
3577
0
             "   /DecodeParms << %s >> ",
3578
0
             ccitt_params.columns,
3579
0
             ccitt_params.rows,
3580
0
             surface_entry->interpolate ? "true" : "false",
3581
0
             buf);
3582
0
    } else {
3583
0
  status = _cairo_pdf_surface_open_stream (surface,
3584
0
             &surface_entry->surface_res,
3585
0
             FALSE,
3586
0
             "   /Type /XObject\n"
3587
0
             "   /Subtype /Image\n"
3588
0
             "   /Width %d\n"
3589
0
             "   /Height %d\n"
3590
0
             "   /ColorSpace /DeviceGray\n"
3591
0
             "   /BitsPerComponent 1\n"
3592
0
             "   /Interpolate %s\n"
3593
0
             "   /Filter /CCITTFaxDecode\n"
3594
0
             "   /DecodeParms << %s >> ",
3595
0
             ccitt_params.columns,
3596
0
             ccitt_params.rows,
3597
0
             surface_entry->interpolate ? "true" : "false",
3598
0
             buf);
3599
0
    }
3600
0
    if (unlikely (status))
3601
0
  return status;
3602
3603
0
    _cairo_output_stream_write (surface->output, ccitt_data, ccitt_data_len);
3604
0
    status = _cairo_pdf_surface_close_stream (surface);
3605
3606
0
    return status;
3607
0
}
3608
3609
static cairo_int_status_t
3610
_cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t        *surface,
3611
             cairo_pdf_source_surface_t *pdf_source)
3612
0
{
3613
0
    cairo_rectangle_int_t old_surface_extents;
3614
0
    cairo_bool_t old_surface_bounded;
3615
0
    cairo_paginated_mode_t old_paginated_mode;
3616
0
    cairo_surface_clipper_t old_clipper;
3617
0
    cairo_bool_t old_in_xobject;
3618
0
    cairo_box_double_t bbox;
3619
0
    cairo_int_status_t status;
3620
0
    int alpha = 0;
3621
0
    cairo_surface_t *free_me = NULL;
3622
0
    cairo_surface_t *source;
3623
0
    const cairo_rectangle_int_t *extents;
3624
0
    cairo_bool_t is_subsurface;
3625
0
    cairo_bool_t transparency_group;
3626
0
    cairo_recording_surface_t *recording;
3627
3628
0
    assert (pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE);
3629
3630
0
    if (pdf_source->hash_entry->bounded) {
3631
0
  extents = &pdf_source->hash_entry->extents;
3632
0
    } else {
3633
0
  extents = &pdf_source->hash_entry->required_extents;
3634
0
    }
3635
3636
0
    is_subsurface = FALSE;
3637
0
    source = pdf_source->surface;
3638
0
    if (_cairo_surface_is_snapshot (source))
3639
0
  free_me = source = _cairo_surface_snapshot_get_target (source);
3640
3641
0
    if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
3642
0
  cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
3643
3644
0
  source = sub->target;
3645
0
  extents = &sub->extents;
3646
0
  is_subsurface = TRUE;
3647
0
    }
3648
3649
0
    assert (source->type == CAIRO_SURFACE_TYPE_RECORDING);
3650
0
    recording = (cairo_recording_surface_t *) source;
3651
3652
0
    old_in_xobject = surface->in_xobject;
3653
0
    old_surface_extents = surface->surface_extents;
3654
0
    old_surface_bounded = surface->surface_bounded;
3655
0
    old_paginated_mode = surface->paginated_mode;
3656
0
    old_clipper = surface->clipper;
3657
0
    surface->surface_extents = *extents;
3658
0
    _cairo_surface_clipper_init (&surface->clipper,
3659
0
         _cairo_pdf_surface_clipper_intersect_clip_path);
3660
3661
0
    _cairo_pdf_operators_reset (&surface->pdf_operators);
3662
0
    surface->in_xobject = TRUE;
3663
0
    surface->surface_extents = *extents;
3664
0
    surface->surface_bounded = TRUE;
3665
3666
    /* Patterns are emitted after fallback images. The paginated mode
3667
     * needs to be set to _RENDER while the recording surface is replayed
3668
     * back to this surface.
3669
     */
3670
0
    surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
3671
0
    _cairo_pdf_group_resources_clear (&surface->resources);
3672
0
    _get_bbox_from_extents (extents, &bbox);
3673
3674
    /* We can optimize away the transparency group allowing the viewer
3675
     * to replay the group in place when:
3676
     *  - ca/CA when painting this groups is 1.0 (need_transp_group is FALSE),
3677
     *  - all operators are OVER, and
3678
     *  - the recording contains only opaque and/or clear alpha.
3679
     */
3680
0
    transparency_group = pdf_source->hash_entry->need_transp_group ||
3681
0
  !(pdf_source->hash_entry->operator == CAIRO_OPERATOR_OVER &&
3682
0
         _cairo_recording_surface_has_only_bilevel_alpha (recording) &&
3683
0
         _cairo_recording_surface_has_only_op_over (recording));
3684
3685
0
    status = _cairo_pdf_surface_open_content_stream (surface,
3686
0
                 &bbox,
3687
0
                 &pdf_source->hash_entry->surface_res,
3688
0
                 TRUE,
3689
0
                 transparency_group);
3690
0
    if (unlikely (status))
3691
0
  goto err;
3692
3693
0
    if (source->content == CAIRO_CONTENT_COLOR) {
3694
0
  status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
3695
0
  if (unlikely (status))
3696
0
      goto err;
3697
3698
0
  _cairo_output_stream_printf (surface->output,
3699
0
             "q /a%d gs 0 0 0 rg %d %d %d %d re f Q\n",
3700
0
             alpha,
3701
0
             extents->x,
3702
0
             extents->y,
3703
0
             extents->width,
3704
0
             extents->height);
3705
0
    }
3706
3707
0
    status = _cairo_recording_surface_replay_region (source,
3708
0
                 is_subsurface ? extents : NULL,
3709
0
                 &surface->base,
3710
0
                 CAIRO_RECORDING_REGION_NATIVE);
3711
0
    assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
3712
0
    if (unlikely (status))
3713
0
  goto err;
3714
3715
0
    status = _cairo_pdf_surface_close_content_stream (surface);
3716
3717
0
    _cairo_surface_clipper_reset (&surface->clipper);
3718
0
    surface->clipper = old_clipper;
3719
0
    _cairo_pdf_operators_reset (&surface->pdf_operators);
3720
0
    surface->in_xobject = old_in_xobject;
3721
0
    surface->paginated_mode = old_paginated_mode;
3722
0
    surface->surface_extents = old_surface_extents;
3723
0
    surface->surface_bounded = old_surface_bounded;
3724
3725
0
err:
3726
0
    cairo_surface_destroy (free_me);
3727
0
    return status;
3728
0
}
3729
3730
/**
3731
 * _cairo_pdf_surface_emit_surface:
3732
 * @surface: [in] the pdf surface
3733
 * @source: [in] #cairo_pdf_source_surface_t containing the surface to write
3734
 * @test: [in] if true, test what type of surface will be emitted.
3735
 * @is_image: [out] if @test is true, returns TRUE if the surface will be emitted
3736
 *  as an Image XObject.
3737
 *
3738
 * If @test is FALSE, emit @src_surface as an XObject.
3739
 * If @test is TRUE, don't emit anything. Set @is_image based on the output that would be emitted.
3740
 **/
3741
static cairo_int_status_t
3742
_cairo_pdf_surface_emit_surface (cairo_pdf_surface_t        *surface,
3743
         cairo_pdf_source_surface_t *source,
3744
         cairo_bool_t                test,
3745
         cairo_bool_t               *is_image)
3746
0
{
3747
0
    cairo_image_surface_t *image;
3748
0
    void *image_extra;
3749
0
    cairo_int_status_t status;
3750
3751
    /* Try all the supported mime types and recording type, falling through
3752
     * each option if unsupported */
3753
0
    if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
3754
0
  status = _cairo_pdf_surface_emit_jbig2_image (surface,
3755
0
                  source->surface,
3756
0
                  source->hash_entry,
3757
0
                  test);
3758
0
  if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
3759
0
      *is_image = TRUE;
3760
0
      return status;
3761
0
  }
3762
3763
0
  status = _cairo_pdf_surface_emit_jpx_image (surface,
3764
0
                source->surface,
3765
0
                source->hash_entry,
3766
0
                test);
3767
0
  if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
3768
0
      *is_image = TRUE;
3769
0
      return status;
3770
0
  }
3771
3772
0
  status = _cairo_pdf_surface_emit_jpeg_image (surface,
3773
0
                 source->surface,
3774
0
                 source->hash_entry,
3775
0
                 test);
3776
0
  if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
3777
0
      *is_image = TRUE;
3778
0
      return status;
3779
0
  }
3780
3781
0
  status = _cairo_pdf_surface_emit_ccitt_image (surface,
3782
0
                  source->surface,
3783
0
                  source->hash_entry,
3784
0
                  test);
3785
0
  if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
3786
0
      *is_image = TRUE;
3787
0
      return status;
3788
0
  }
3789
3790
0
  if (source->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
3791
0
      if (test) {
3792
0
    *is_image = FALSE;
3793
0
    return CAIRO_INT_STATUS_SUCCESS;
3794
0
      } else {
3795
0
    return _cairo_pdf_surface_emit_recording_surface (surface, source);
3796
0
      }
3797
0
  }
3798
0
    }
3799
3800
    /* The only option left is to emit as an image surface */
3801
3802
0
    if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
3803
0
  status = _cairo_surface_acquire_source_image (source->surface, &image, &image_extra);
3804
0
    } else {
3805
0
  status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface,
3806
0
                       source->raster_pattern,
3807
0
                       &image,
3808
0
                       &image_extra);
3809
0
    }
3810
0
    if (unlikely (status))
3811
0
  return status;
3812
3813
0
    if (test) {
3814
0
  *is_image = TRUE;
3815
0
    } else {
3816
0
  status = _cairo_pdf_surface_emit_image (surface,
3817
0
            image,
3818
0
            source->hash_entry);
3819
0
    }
3820
3821
0
    if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
3822
0
  _cairo_surface_release_source_image (source->surface, image, image_extra);
3823
0
    } else {
3824
0
  _cairo_pdf_surface_release_source_image_from_pattern (surface,
3825
0
                    source->raster_pattern,
3826
0
                    image,
3827
0
                    image_extra);
3828
0
    }
3829
3830
0
    return status;
3831
0
}
3832
3833
static cairo_int_status_t
3834
_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t  *surface,
3835
           cairo_pdf_pattern_t  *pdf_pattern)
3836
0
{
3837
0
    cairo_pattern_t *pattern = pdf_pattern->pattern;
3838
0
    cairo_int_status_t status;
3839
0
    cairo_matrix_t cairo_p2d, pdf_p2d;
3840
0
    cairo_extend_t extend = cairo_pattern_get_extend (pattern);
3841
0
    double xstep, ystep;
3842
0
    cairo_rectangle_int_t pattern_extents;
3843
0
    double x_offset;
3844
0
    double y_offset;
3845
0
    char draw_surface[50];
3846
0
    char draw_surface2[200];
3847
0
    cairo_box_double_t bbox;
3848
0
    cairo_matrix_t mat;
3849
0
    cairo_pdf_source_surface_entry_t *pdf_source;
3850
0
    cairo_rectangle_int_t op_extents;
3851
3852
0
    assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
3853
0
    if (pattern->extend == CAIRO_EXTEND_PAD) {
3854
0
  status = _cairo_pdf_surface_add_padded_image_surface (surface,
3855
0
                    pattern,
3856
0
                    &pdf_pattern->extents,
3857
0
                    &pdf_source,
3858
0
                    &x_offset,
3859
0
                    &y_offset,
3860
0
                    &op_extents);
3861
0
    } else {
3862
0
  status = _cairo_pdf_surface_add_source_surface (surface,
3863
0
              NULL,
3864
0
              pattern,
3865
0
              pdf_pattern->operator,
3866
0
              pattern->filter,
3867
0
              FALSE, /* stencil mask */
3868
0
              FALSE, /* smask */
3869
0
              FALSE, /* need_transp_group */
3870
0
              &pdf_pattern->extents,
3871
0
              NULL, /* smask_res */
3872
0
              &pdf_source,
3873
0
              &x_offset,
3874
0
              &y_offset,
3875
0
              &op_extents);
3876
0
    }
3877
0
    if (unlikely (status))
3878
0
  return status;
3879
3880
0
    pattern_extents = pdf_source->extents;
3881
0
    if (!pdf_source->bounded)
3882
0
    {
3883
0
  extend = CAIRO_EXTEND_NONE;
3884
0
  _cairo_rectangle_intersect (&pattern_extents, &op_extents);
3885
0
    }
3886
3887
0
    switch (extend) {
3888
0
    case CAIRO_EXTEND_PAD:
3889
0
    case CAIRO_EXTEND_NONE:
3890
0
    {
3891
  /* In PS/PDF, (as far as I can tell), all patterns are
3892
   * repeating. So we support cairo's EXTEND_NONE semantics
3893
   * by setting the repeat step size to a size large enough
3894
   * to guarantee that no more than a single occurrence will
3895
   * be visible.
3896
   *
3897
   * First, map the surface extents into pattern space (since
3898
   * xstep and ystep are in pattern space).  Then use an upper
3899
   * bound on the length of the diagonal of the pattern image
3900
   * and the surface as repeat size.  This guarantees to never
3901
   * repeat visibly.
3902
   */
3903
0
  double x1 = 0.0, y1 = 0.0;
3904
0
  double x2 = surface->surface_extents.width;
3905
0
  double y2 = surface->surface_extents.height;
3906
0
  _cairo_matrix_transform_bounding_box (&pattern->matrix,
3907
0
                &x1, &y1, &x2, &y2,
3908
0
                NULL);
3909
3910
  /* Rather than computing precise bounds of the union, just
3911
   * add the surface extents unconditionally. We only
3912
   * required an answer that's large enough, we don't really
3913
   * care if it's not as tight as possible.*/
3914
0
  xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
3915
0
            pattern_extents.width + pattern_extents.height);
3916
0
    }
3917
0
    break;
3918
0
    case CAIRO_EXTEND_REPEAT:
3919
0
  xstep = pattern_extents.width;
3920
0
  ystep = pattern_extents.height;
3921
0
  break;
3922
3923
0
    case CAIRO_EXTEND_REFLECT:
3924
0
  pattern_extents.width *= 2;
3925
0
  pattern_extents.height *= 2;
3926
0
  xstep = pattern_extents.width;
3927
0
  ystep = pattern_extents.height;
3928
0
  break;
3929
3930
    /* All the rest (if any) should have been analyzed away, so this
3931
     * case should be unreachable. */
3932
0
    default:
3933
0
  ASSERT_NOT_REACHED;
3934
0
  xstep = 0;
3935
0
  ystep = 0;
3936
0
    }
3937
3938
    /* At this point, (that is, within the surface backend interface),
3939
     * the pattern's matrix maps from cairo's device space to cairo's
3940
     * pattern space, (both with their origin at the upper-left, and
3941
     * cairo's pattern space of size width,height).
3942
     *
3943
     * Then, we must emit a PDF pattern object that maps from its own
3944
     * pattern space, (which has a size that we establish in the BBox
3945
     * dictionary entry), to the PDF page's *initial* space, (which
3946
     * does not benefit from the Y-axis flipping matrix that we emit
3947
     * on each page). So the PDF patterns matrix maps from a
3948
     * (width,height) pattern space to a device space with the origin
3949
     * in the lower-left corner.
3950
     *
3951
     * So to handle all of that, we start with an identity matrix for
3952
     * the PDF pattern to device matrix. We translate it up by the
3953
     * image height then flip it in the Y direction, (moving us from
3954
     * the PDF origin to cairo's origin). We then multiply in the
3955
     * inverse of the cairo pattern matrix, (since it maps from device
3956
     * to pattern, while we're setting up pattern to device). Finally,
3957
     * we translate back down by the image height and flip again to
3958
     * end up at the lower-left origin that PDF expects.
3959
     *
3960
     * Additionally, within the stream that paints the pattern itself,
3961
     * we are using a PDF image object that has a size of (1,1) so we
3962
     * have to scale it up by the image width and height to fill our
3963
     * pattern cell.
3964
     */
3965
0
    cairo_p2d = pattern->matrix;
3966
0
    status = cairo_matrix_invert (&cairo_p2d);
3967
    /* cairo_pattern_set_matrix ensures the matrix is invertible */
3968
0
    assert (status == CAIRO_INT_STATUS_SUCCESS);
3969
3970
0
    if (pdf_pattern->inverted_y_axis)
3971
0
  cairo_matrix_init (&mat, 1, 0, 0, 1, 0, 0);
3972
0
    else
3973
0
  cairo_matrix_init (&mat, 1, 0, 0, -1, 0, surface->height);
3974
3975
0
    cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &mat);
3976
0
    cairo_matrix_translate (&pdf_p2d, x_offset, y_offset);
3977
0
    if (pdf_source->emit_image) {
3978
0
  cairo_matrix_translate (&pdf_p2d, 0.0, pdf_source->extents.height);
3979
0
  cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
3980
0
    }
3981
3982
0
    _get_bbox_from_extents (&pattern_extents, &bbox);
3983
0
    _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
3984
0
    status = _cairo_pdf_surface_open_stream (surface,
3985
0
                     &pdf_pattern->pattern_res,
3986
0
               FALSE,
3987
0
               "   /PatternType 1\n"
3988
0
               "   /BBox [ %f %f %f %f ]\n"
3989
0
               "   /XStep %f\n"
3990
0
               "   /YStep %f\n"
3991
0
               "   /TilingType 1\n"
3992
0
               "   /PaintType 1\n"
3993
0
               "   /Matrix [ %f %f %f %f %f %f ]\n"
3994
0
               "   /Resources << /XObject << /x%d %d 0 R >> >>\n",
3995
0
               bbox.p1.x, bbox.p1.y, bbox.p2.x, bbox.p2.y,
3996
0
               xstep, ystep,
3997
0
               pdf_p2d.xx, pdf_p2d.yx,
3998
0
               pdf_p2d.xy, pdf_p2d.yy,
3999
0
               pdf_p2d.x0, pdf_p2d.y0,
4000
0
               pdf_source->surface_res.id,
4001
0
               pdf_source->surface_res.id);
4002
0
    if (unlikely (status))
4003
0
  return status;
4004
4005
0
    if (pdf_source->emit_image) {
4006
0
  snprintf(draw_surface,
4007
0
     sizeof (draw_surface),
4008
0
     "q %d 0 0 %d 0 0 cm /x%d Do Q",
4009
0
     pdf_source->extents.width,
4010
0
     pdf_source->extents.height,
4011
0
     pdf_source->surface_res.id);
4012
0
    } else {
4013
0
  snprintf(draw_surface,
4014
0
     sizeof (draw_surface),
4015
0
     "/x%d Do",
4016
0
     pdf_source->surface_res.id);
4017
0
    }
4018
4019
0
    if (extend == CAIRO_EXTEND_REFLECT) {
4020
0
  cairo_rectangle_int_t p_extents = pdf_source->extents;
4021
0
  snprintf(draw_surface2,
4022
0
     sizeof (draw_surface2),
4023
0
     "%d %d %d %d re W n %s",
4024
0
     p_extents.x, p_extents.y,
4025
0
     p_extents.width, p_extents.height,
4026
0
     draw_surface);
4027
4028
0
  _cairo_output_stream_printf (surface->output, "q %s Q\n", draw_surface2);
4029
4030
0
  cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y);
4031
0
  cairo_matrix_scale (&mat, -1, 1);
4032
0
  cairo_matrix_translate (&mat, -2*p_extents.width, 0);
4033
0
  cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y);
4034
0
  _cairo_output_stream_printf (surface->output, "q ");
4035
0
  _cairo_output_stream_print_matrix (surface->output, &mat);
4036
0
  _cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2);
4037
4038
0
  cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y);
4039
0
  cairo_matrix_scale (&mat, 1, -1);
4040
0
  cairo_matrix_translate (&mat, 0, -2*p_extents.height);
4041
0
  cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y);
4042
0
  _cairo_output_stream_printf (surface->output, "q ");
4043
0
  _cairo_output_stream_print_matrix (surface->output, &mat);
4044
0
  _cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2);
4045
4046
0
  cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y);
4047
0
  cairo_matrix_scale (&mat, -1, -1);
4048
0
  cairo_matrix_translate (&mat, -2*p_extents.width, -2*p_extents.height);
4049
0
  cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y);
4050
0
  _cairo_output_stream_printf (surface->output, "q ");
4051
0
  _cairo_output_stream_print_matrix (surface->output, &mat);
4052
0
  _cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2);
4053
0
    } else {
4054
0
  _cairo_output_stream_printf (surface->output,
4055
0
             " %s \n",
4056
0
             draw_surface);
4057
0
    }
4058
4059
0
    status = _cairo_pdf_surface_close_stream (surface);
4060
0
    if (unlikely (status))
4061
0
  return status;
4062
4063
0
    return _cairo_output_stream_get_status (surface->output);
4064
0
}
4065
4066
typedef struct _cairo_pdf_color_stop {
4067
    double offset;
4068
    double color[4];
4069
    cairo_pdf_resource_t resource;
4070
} cairo_pdf_color_stop_t;
4071
4072
static cairo_int_status_t
4073
cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t    *surface,
4074
                                            cairo_pdf_color_stop_t *stop1,
4075
                                            cairo_pdf_color_stop_t *stop2,
4076
                                            cairo_pdf_resource_t   *function)
4077
0
{
4078
0
    int num_elems, i;
4079
0
    cairo_pdf_rgb_linear_function_t elem;
4080
0
    cairo_pdf_resource_t res;
4081
0
    cairo_int_status_t status;
4082
4083
0
    num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions);
4084
0
    for (i = 0; i < num_elems; i++) {
4085
0
  _cairo_array_copy_element (&surface->rgb_linear_functions, i, &elem);
4086
0
        if (memcmp (&elem.color1[0], &stop1->color[0], sizeof (double)*3) != 0)
4087
0
            continue;
4088
0
        if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0)
4089
0
            continue;
4090
0
        *function =  elem.resource;
4091
0
        return CAIRO_STATUS_SUCCESS;
4092
0
    }
4093
4094
0
    res = _cairo_pdf_surface_new_object (surface);
4095
0
    if (res.id == 0)
4096
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4097
4098
0
    _cairo_output_stream_printf (surface->output,
4099
0
         "%d 0 obj\n"
4100
0
         "<< /FunctionType 2\n"
4101
0
         "   /Domain [ 0 1 ]\n"
4102
0
         "   /C0 [ %f %f %f ]\n"
4103
0
         "   /C1 [ %f %f %f ]\n"
4104
0
         "   /N 1\n"
4105
0
         ">>\n"
4106
0
         "endobj\n",
4107
0
         res.id,
4108
0
                                 stop1->color[0],
4109
0
                                 stop1->color[1],
4110
0
                                 stop1->color[2],
4111
0
                                 stop2->color[0],
4112
0
                                 stop2->color[1],
4113
0
                                 stop2->color[2]);
4114
4115
0
    elem.resource = res;
4116
0
    memcpy (&elem.color1[0], &stop1->color[0], sizeof (double)*3);
4117
0
    memcpy (&elem.color2[0], &stop2->color[0], sizeof (double)*3);
4118
4119
0
    status = _cairo_array_append (&surface->rgb_linear_functions, &elem);
4120
0
    *function = res;
4121
4122
0
    return status;
4123
0
}
4124
4125
static cairo_int_status_t
4126
cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t    *surface,
4127
                                              cairo_pdf_color_stop_t *stop1,
4128
                                              cairo_pdf_color_stop_t *stop2,
4129
                                              cairo_pdf_resource_t   *function)
4130
0
{
4131
0
    int num_elems, i;
4132
0
    cairo_pdf_alpha_linear_function_t elem;
4133
0
    cairo_pdf_resource_t res;
4134
0
    cairo_int_status_t status;
4135
4136
0
    num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions);
4137
0
    for (i = 0; i < num_elems; i++) {
4138
0
  _cairo_array_copy_element (&surface->alpha_linear_functions, i, &elem);
4139
0
        if (elem.alpha1 != stop1->color[3])
4140
0
            continue;
4141
0
        if (elem.alpha2 != stop2->color[3])
4142
0
            continue;
4143
0
        *function =  elem.resource;
4144
0
        return CAIRO_STATUS_SUCCESS;
4145
0
    }
4146
4147
0
    res = _cairo_pdf_surface_new_object (surface);
4148
0
    if (res.id == 0)
4149
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4150
4151
0
    _cairo_output_stream_printf (surface->output,
4152
0
         "%d 0 obj\n"
4153
0
         "<< /FunctionType 2\n"
4154
0
         "   /Domain [ 0 1 ]\n"
4155
0
         "   /C0 [ %f ]\n"
4156
0
         "   /C1 [ %f ]\n"
4157
0
         "   /N 1\n"
4158
0
         ">>\n"
4159
0
         "endobj\n",
4160
0
         res.id,
4161
0
                                 stop1->color[3],
4162
0
                                 stop2->color[3]);
4163
4164
0
    elem.resource = res;
4165
0
    elem.alpha1 = stop1->color[3];
4166
0
    elem.alpha2 = stop2->color[3];
4167
4168
0
    status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
4169
0
    *function = res;
4170
4171
0
    return status;
4172
0
}
4173
4174
static cairo_int_status_t
4175
_cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t    *surface,
4176
                                                unsigned int          n_stops,
4177
                                                cairo_pdf_color_stop_t *stops,
4178
                                                cairo_bool_t          is_alpha,
4179
                                                cairo_pdf_resource_t   *function)
4180
0
{
4181
0
    cairo_pdf_resource_t res;
4182
0
    unsigned int i;
4183
0
    cairo_int_status_t status;
4184
4185
    /* emit linear gradients between pairs of subsequent stops... */
4186
0
    for (i = 0; i < n_stops-1; i++) {
4187
0
        if (is_alpha) {
4188
0
            status = cairo_pdf_surface_emit_alpha_linear_function (surface,
4189
0
                                                                   &stops[i],
4190
0
                                                                   &stops[i+1],
4191
0
                                                                   &stops[i].resource);
4192
0
            if (unlikely (status))
4193
0
                return status;
4194
0
        } else {
4195
0
            status = cairo_pdf_surface_emit_rgb_linear_function (surface,
4196
0
                                                                 &stops[i],
4197
0
                                                                 &stops[i+1],
4198
0
                                                                 &stops[i].resource);
4199
0
            if (unlikely (status))
4200
0
                return status;
4201
0
        }
4202
0
    }
4203
4204
    /* ... and stitch them together */
4205
0
    res = _cairo_pdf_surface_new_object (surface);
4206
0
    if (res.id == 0)
4207
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4208
4209
0
    _cairo_output_stream_printf (surface->output,
4210
0
         "%d 0 obj\n"
4211
0
         "<< /FunctionType 3\n"
4212
0
         "   /Domain [ %f %f ]\n",
4213
0
         res.id,
4214
0
                                 stops[0].offset,
4215
0
                                 stops[n_stops - 1].offset);
4216
4217
0
    _cairo_output_stream_printf (surface->output,
4218
0
         "   /Functions [ ");
4219
0
    for (i = 0; i < n_stops-1; i++)
4220
0
        _cairo_output_stream_printf (surface->output,
4221
0
                                     "%d 0 R ", stops[i].resource.id);
4222
0
    _cairo_output_stream_printf (surface->output,
4223
0
         "]\n");
4224
4225
0
    _cairo_output_stream_printf (surface->output,
4226
0
         "   /Bounds [ ");
4227
0
    for (i = 1; i < n_stops-1; i++)
4228
0
        _cairo_output_stream_printf (surface->output,
4229
0
             "%f ", stops[i].offset);
4230
0
    _cairo_output_stream_printf (surface->output,
4231
0
         "]\n");
4232
4233
0
    _cairo_output_stream_printf (surface->output,
4234
0
         "   /Encode [ ");
4235
0
    for (i = 1; i < n_stops; i++)
4236
0
        _cairo_output_stream_printf (surface->output,
4237
0
             "0 1 ");
4238
0
    _cairo_output_stream_printf (surface->output,
4239
0
         "]\n");
4240
4241
0
    _cairo_output_stream_printf (surface->output,
4242
0
         ">>\n"
4243
0
         "endobj\n");
4244
4245
0
    *function = res;
4246
4247
0
    return _cairo_output_stream_get_status (surface->output);
4248
0
}
4249
4250
4251
static void
4252
calc_gradient_color (cairo_pdf_color_stop_t *new_stop,
4253
         cairo_pdf_color_stop_t *stop1,
4254
         cairo_pdf_color_stop_t *stop2)
4255
0
{
4256
0
    int i;
4257
0
    double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
4258
4259
0
    for (i = 0; i < 4; i++)
4260
0
  new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
4261
0
}
4262
4263
0
#define COLOR_STOP_EPSILON 1e-6
4264
4265
static cairo_int_status_t
4266
_cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t      *surface,
4267
                                       cairo_gradient_pattern_t *pattern,
4268
                                       cairo_pdf_resource_t     *color_function,
4269
                                       cairo_pdf_resource_t     *alpha_function)
4270
0
{
4271
0
    cairo_pdf_color_stop_t *allstops, *stops;
4272
0
    unsigned int n_stops;
4273
0
    unsigned int i;
4274
0
    cairo_bool_t emit_alpha = FALSE;
4275
0
    cairo_int_status_t status;
4276
4277
0
    color_function->id = 0;
4278
0
    alpha_function->id = 0;
4279
4280
0
    allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t));
4281
0
    if (unlikely (allstops == NULL))
4282
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4283
4284
0
    stops = &allstops[1];
4285
0
    n_stops = pattern->n_stops;
4286
4287
0
    for (i = 0; i < n_stops; i++) {
4288
0
  stops[i].color[0] = pattern->stops[i].color.red;
4289
0
  stops[i].color[1] = pattern->stops[i].color.green;
4290
0
  stops[i].color[2] = pattern->stops[i].color.blue;
4291
0
  stops[i].color[3] = pattern->stops[i].color.alpha;
4292
0
        if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
4293
0
            emit_alpha = TRUE;
4294
0
  stops[i].offset = pattern->stops[i].offset;
4295
0
    }
4296
4297
0
    if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
4298
0
  pattern->base.extend == CAIRO_EXTEND_REFLECT) {
4299
0
  if (stops[0].offset > COLOR_STOP_EPSILON) {
4300
0
      if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
4301
0
    memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
4302
0
      else
4303
0
    calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
4304
0
      stops = allstops;
4305
0
      n_stops++;
4306
0
  }
4307
0
  stops[0].offset = 0.0;
4308
4309
0
  if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
4310
0
      if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
4311
0
    memcpy (&stops[n_stops],
4312
0
      &stops[n_stops - 1],
4313
0
      sizeof (cairo_pdf_color_stop_t));
4314
0
      } else {
4315
0
    calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
4316
0
      }
4317
0
      n_stops++;
4318
0
  }
4319
0
  stops[n_stops-1].offset = 1.0;
4320
0
    }
4321
4322
0
    if (stops[0].offset == stops[n_stops - 1].offset) {
4323
  /*
4324
   * The first and the last stops have the same offset, but we
4325
   * don't want a function with an empty domain, because that
4326
   * would provoke underdefined behaviour from rasterisers.
4327
   * This can only happen with EXTEND_PAD, because EXTEND_NONE
4328
   * is optimised into a clear pattern in cairo-gstate, and
4329
   * REFLECT/REPEAT are always transformed to have the first
4330
   * stop at t=0 and the last stop at t=1.  Thus we want a step
4331
   * function going from the first color to the last one.
4332
   *
4333
   * This can be accomplished by stitching three functions:
4334
   *  - a constant first color function,
4335
   *  - a step from the first color to the last color (with empty domain)
4336
   *  - a constant last color function
4337
   */
4338
0
  cairo_pdf_color_stop_t pad_stops[4];
4339
4340
0
  assert (pattern->base.extend == CAIRO_EXTEND_PAD);
4341
4342
0
  pad_stops[0] = pad_stops[1] = stops[0];
4343
0
  pad_stops[2] = pad_stops[3] = stops[n_stops - 1];
4344
4345
0
  pad_stops[0].offset = 0;
4346
0
  pad_stops[3].offset = 1;
4347
4348
0
        status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
4349
0
                                                                 4,
4350
0
                                                                 pad_stops,
4351
0
                                                                 FALSE,
4352
0
                                                                 color_function);
4353
0
        if (unlikely (status))
4354
0
            goto BAIL;
4355
4356
0
        if (emit_alpha) {
4357
0
            status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
4358
0
                                                                     4,
4359
0
                                                                     pad_stops,
4360
0
                                                                     TRUE,
4361
0
                                                                     alpha_function);
4362
0
            if (unlikely (status))
4363
0
                goto BAIL;
4364
0
        }
4365
0
    } else if (n_stops == 2) {
4366
        /* no need for stitched function */
4367
0
        status = cairo_pdf_surface_emit_rgb_linear_function (surface,
4368
0
                                                             &stops[0],
4369
0
                                                             &stops[n_stops - 1],
4370
0
                                                             color_function);
4371
0
        if (unlikely (status))
4372
0
            goto BAIL;
4373
4374
0
        if (emit_alpha) {
4375
0
            status = cairo_pdf_surface_emit_alpha_linear_function (surface,
4376
0
                                                                   &stops[0],
4377
0
                                                                   &stops[n_stops - 1],
4378
0
                                                                   alpha_function);
4379
0
            if (unlikely (status))
4380
0
                goto BAIL;
4381
0
        }
4382
0
    } else {
4383
        /* multiple stops: stitch. XXX possible optimization: regularly spaced
4384
         * stops do not require stitching. XXX */
4385
0
        status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
4386
0
                                                                 n_stops,
4387
0
                                                                 stops,
4388
0
                                                                 FALSE,
4389
0
                                                                 color_function);
4390
0
        if (unlikely (status))
4391
0
            goto BAIL;
4392
4393
0
        if (emit_alpha) {
4394
0
            status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
4395
0
                                                                     n_stops,
4396
0
                                                                     stops,
4397
0
                                                                     TRUE,
4398
0
                                                                     alpha_function);
4399
0
            if (unlikely (status))
4400
0
                goto BAIL;
4401
0
        }
4402
0
    }
4403
4404
0
BAIL:
4405
0
    free (allstops);
4406
0
    return status;
4407
0
}
4408
4409
static cairo_int_status_t
4410
_cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t      *surface,
4411
              cairo_gradient_pattern_t *pattern,
4412
              cairo_pdf_resource_t     *function,
4413
              int                       begin,
4414
              int                       end)
4415
0
{
4416
0
    cairo_pdf_resource_t res;
4417
0
    int i;
4418
4419
0
    res = _cairo_pdf_surface_new_object (surface);
4420
0
    if (res.id == 0)
4421
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4422
4423
0
    _cairo_output_stream_printf (surface->output,
4424
0
         "%d 0 obj\n"
4425
0
         "<< /FunctionType 3\n"
4426
0
         "   /Domain [ %d %d ]\n",
4427
0
         res.id,
4428
0
                                 begin,
4429
0
                                 end);
4430
4431
0
    _cairo_output_stream_printf (surface->output,
4432
0
         "   /Functions [ ");
4433
0
    for (i = begin; i < end; i++)
4434
0
        _cairo_output_stream_printf (surface->output,
4435
0
                                     "%d 0 R ", function->id);
4436
0
    _cairo_output_stream_printf (surface->output,
4437
0
         "]\n");
4438
4439
0
    _cairo_output_stream_printf (surface->output,
4440
0
         "   /Bounds [ ");
4441
0
    for (i = begin + 1; i < end; i++)
4442
0
        _cairo_output_stream_printf (surface->output,
4443
0
             "%d ", i);
4444
0
    _cairo_output_stream_printf (surface->output,
4445
0
         "]\n");
4446
4447
0
    _cairo_output_stream_printf (surface->output,
4448
0
         "   /Encode [ ");
4449
0
    for (i = begin; i < end; i++) {
4450
0
  if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) {
4451
0
      _cairo_output_stream_printf (surface->output,
4452
0
           "1 0 ");
4453
0
  } else {
4454
0
      _cairo_output_stream_printf (surface->output,
4455
0
           "0 1 ");
4456
0
  }
4457
0
    }
4458
0
    _cairo_output_stream_printf (surface->output,
4459
0
         "]\n");
4460
4461
0
    _cairo_output_stream_printf (surface->output,
4462
0
         ">>\n"
4463
0
         "endobj\n");
4464
4465
0
    *function = res;
4466
4467
0
    return _cairo_output_stream_get_status (surface->output);
4468
0
}
4469
4470
static cairo_int_status_t
4471
cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t  *surface,
4472
             cairo_pdf_pattern_t  *pdf_pattern,
4473
             cairo_pdf_resource_t  gstate_resource,
4474
             cairo_pdf_resource_t  gradient_mask)
4475
0
{
4476
0
    cairo_pdf_resource_t smask_resource;
4477
0
    cairo_int_status_t status;
4478
0
    char buf[100];
4479
0
    double x1, y1, x2, y2;
4480
4481
0
    if (pdf_pattern->is_shading) {
4482
0
  snprintf(buf, sizeof(buf),
4483
0
     "         /Shading\n"
4484
0
     "            << /sh%d %d 0 R >>\n",
4485
0
     gradient_mask.id,
4486
0
     gradient_mask.id);
4487
0
    } else {
4488
0
  snprintf(buf, sizeof(buf),
4489
0
     "         /Pattern\n"
4490
0
     "            << /p%d %d 0 R >>\n",
4491
0
     gradient_mask.id,
4492
0
     gradient_mask.id);
4493
0
    }
4494
4495
0
    if (pdf_pattern->is_shading) {
4496
0
  cairo_box_t box;
4497
4498
  /* When emitting a shading operator we are in cairo pattern
4499
   * coordinates. _cairo_pdf_surface_paint_gradient has set the
4500
   * ctm to the pattern matrix (including the conversion from
4501
   * pdf to cairo coordinates) */
4502
0
  _cairo_box_from_rectangle (&box, &pdf_pattern->extents);
4503
0
  _cairo_box_to_doubles (&box, &x1, &y1, &x2, &y2);
4504
0
  _cairo_matrix_transform_bounding_box (&pdf_pattern->pattern->matrix, &x1, &y1, &x2, &y2, NULL);
4505
0
    } else {
4506
0
  cairo_box_double_t box;
4507
4508
  /* When emitting a shading pattern we are in pdf page
4509
   * coordinates. The color and alpha shading patterns painted
4510
   * in the XObject below contain the cairo pattern to pdf page
4511
   * matrix in the /Matrix entry of the pattern. */
4512
0
  _get_bbox_from_extents (&pdf_pattern->extents, &box);
4513
0
  x1 = box.p1.x;
4514
0
  y1 = box.p1.y;
4515
0
  x2 = box.p2.x;
4516
0
  y2 = box.p2.y;
4517
0
    }
4518
0
    status = _cairo_pdf_surface_open_stream (surface,
4519
0
               NULL,
4520
0
               surface->compress_streams,
4521
0
               "   /Type /XObject\n"
4522
0
               "   /Subtype /Form\n"
4523
0
               "   /FormType 1\n"
4524
0
               "   /BBox [ %f %f %f %f ]\n"
4525
0
               "   /Resources\n"
4526
0
               "      << /ExtGState\n"
4527
0
               "            << /a0 << /ca 1 /CA 1 >>"
4528
0
               "      >>\n"
4529
0
               "%s"
4530
0
               "      >>\n"
4531
0
               "   /Group\n"
4532
0
               "      << /Type /Group\n"
4533
0
               "         /S /Transparency\n"
4534
0
               "         /I true\n"
4535
0
               "         /CS /DeviceGray\n"
4536
0
               "      >>\n",
4537
0
               x1,y1,x2,y2,
4538
0
               buf);
4539
0
    if (unlikely (status))
4540
0
  return status;
4541
4542
0
    if (pdf_pattern->is_shading) {
4543
0
  _cairo_output_stream_printf (surface->output,
4544
0
             "/a0 gs /sh%d sh\n",
4545
0
             gradient_mask.id);
4546
0
    } else {
4547
0
  _cairo_output_stream_printf (surface->output,
4548
0
             "q\n"
4549
0
             "/a0 gs\n"
4550
0
             "/Pattern cs /p%d scn\n"
4551
0
             "0 0 %f %f re\n"
4552
0
             "f\n"
4553
0
             "Q\n",
4554
0
             gradient_mask.id,
4555
0
             surface->width,
4556
0
             surface->height);
4557
0
    }
4558
4559
0
    status = _cairo_pdf_surface_close_stream (surface);
4560
0
    if (unlikely (status))
4561
0
  return status;
4562
4563
0
    smask_resource = _cairo_pdf_surface_new_object (surface);
4564
0
    if (smask_resource.id == 0)
4565
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4566
4567
0
    _cairo_output_stream_printf (surface->output,
4568
0
                                 "%d 0 obj\n"
4569
0
                                 "<< /Type /Mask\n"
4570
0
                                 "   /S /Luminosity\n"
4571
0
                                 "   /G %d 0 R\n"
4572
0
                                 ">>\n"
4573
0
                                 "endobj\n",
4574
0
                                 smask_resource.id,
4575
0
                                 surface->pdf_stream.self.id);
4576
4577
    /* Create GState which uses the transparency group as an SMask. */
4578
0
    _cairo_pdf_surface_update_object (surface, gstate_resource);
4579
4580
0
    _cairo_output_stream_printf (surface->output,
4581
0
                                 "%d 0 obj\n"
4582
0
                                 "<< /Type /ExtGState\n"
4583
0
                                 "   /SMask %d 0 R\n"
4584
0
                                 "   /ca 1\n"
4585
0
                                 "   /CA 1\n"
4586
0
                                 "   /AIS false\n"
4587
0
                                 ">>\n"
4588
0
                                 "endobj\n",
4589
0
                                 gstate_resource.id,
4590
0
                                 smask_resource.id);
4591
4592
0
    return _cairo_output_stream_get_status (surface->output);
4593
0
}
4594
4595
static void
4596
_cairo_pdf_surface_output_gradient (cairo_pdf_surface_t        *surface,
4597
            const cairo_pdf_pattern_t  *pdf_pattern,
4598
            cairo_pdf_resource_t        pattern_resource,
4599
            const cairo_matrix_t       *pat_to_pdf,
4600
            const cairo_circle_double_t*start,
4601
            const cairo_circle_double_t*end,
4602
            const double               *domain,
4603
            const char                 *colorspace,
4604
            cairo_pdf_resource_t        color_function)
4605
0
{
4606
0
    _cairo_output_stream_printf (surface->output,
4607
0
                                 "%d 0 obj\n",
4608
0
         pattern_resource.id);
4609
4610
0
    if (!pdf_pattern->is_shading) {
4611
0
  _cairo_output_stream_printf (surface->output,
4612
0
             "<< /Type /Pattern\n"
4613
0
             "   /PatternType 2\n"
4614
0
             "   /Matrix [ ");
4615
0
  _cairo_output_stream_print_matrix (surface->output, pat_to_pdf);
4616
0
  _cairo_output_stream_printf (surface->output,
4617
0
             " ]\n"
4618
0
             "   /Shading\n");
4619
0
    }
4620
4621
0
    if (pdf_pattern->pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
4622
0
  _cairo_output_stream_printf (surface->output,
4623
0
             "      << /ShadingType 2\n"
4624
0
             "         /ColorSpace %s\n"
4625
0
             "         /Coords [ %f %f %f %f ]\n",
4626
0
             colorspace,
4627
0
             start->center.x, start->center.y,
4628
0
             end->center.x, end->center.y);
4629
0
    } else {
4630
0
  _cairo_output_stream_printf (surface->output,
4631
0
             "      << /ShadingType 3\n"
4632
0
             "         /ColorSpace %s\n"
4633
0
             "         /Coords [ %f %f %f %f %f %f ]\n",
4634
0
             colorspace,
4635
0
             start->center.x, start->center.y,
4636
0
             MAX (start->radius, 0),
4637
0
             end->center.x, end->center.y,
4638
0
             MAX (end->radius, 0));
4639
0
    }
4640
4641
0
    _cairo_output_stream_printf (surface->output,
4642
0
         "         /Domain [ %f %f ]\n",
4643
0
         domain[0], domain[1]);
4644
4645
0
    if (pdf_pattern->pattern->extend != CAIRO_EXTEND_NONE) {
4646
0
        _cairo_output_stream_printf (surface->output,
4647
0
                                     "         /Extend [ true true ]\n");
4648
0
    } else {
4649
0
        _cairo_output_stream_printf (surface->output,
4650
0
                                     "         /Extend [ false false ]\n");
4651
0
    }
4652
4653
0
    _cairo_output_stream_printf (surface->output,
4654
0
         "         /Function %d 0 R\n"
4655
0
                                 "      >>\n",
4656
0
         color_function.id);
4657
4658
0
    if (!pdf_pattern->is_shading) {
4659
0
  _cairo_output_stream_printf (surface->output,
4660
0
             ">>\n");
4661
0
    }
4662
4663
0
    _cairo_output_stream_printf (surface->output,
4664
0
             "endobj\n");
4665
0
}
4666
4667
static cairo_int_status_t
4668
_cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t    *surface,
4669
          cairo_pdf_pattern_t    *pdf_pattern)
4670
0
{
4671
0
    cairo_gradient_pattern_t *pattern = (cairo_gradient_pattern_t *) pdf_pattern->pattern;
4672
0
    cairo_pdf_resource_t color_function, alpha_function;
4673
0
    cairo_matrix_t pat_to_pdf;
4674
0
    cairo_circle_double_t start, end;
4675
0
    double domain[2];
4676
0
    cairo_int_status_t status;
4677
0
    cairo_matrix_t mat;
4678
4679
0
    assert (pattern->n_stops != 0);
4680
4681
0
    status = _cairo_pdf_surface_emit_pattern_stops (surface,
4682
0
                                                    pattern,
4683
0
                                                    &color_function,
4684
0
                                                    &alpha_function);
4685
0
    if (unlikely (status))
4686
0
  return status;
4687
4688
0
    pat_to_pdf = pattern->base.matrix;
4689
0
    status = cairo_matrix_invert (&pat_to_pdf);
4690
    /* cairo_pattern_set_matrix ensures the matrix is invertible */
4691
0
    assert (status == CAIRO_INT_STATUS_SUCCESS);
4692
4693
0
    if (pdf_pattern->inverted_y_axis)
4694
0
       cairo_matrix_init (&mat, 1, 0, 0, 1, 0, 0);
4695
0
    else
4696
0
       cairo_matrix_init (&mat, 1, 0, 0, -1, 0, surface->height);
4697
4698
0
    cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &mat);
4699
4700
0
    if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
4701
0
  pattern->base.extend == CAIRO_EXTEND_REFLECT)
4702
0
    {
4703
0
  double bounds_x1, bounds_x2, bounds_y1, bounds_y2;
4704
0
  double x_scale, y_scale, tolerance;
4705
4706
  /* TODO: use tighter extents */
4707
0
  bounds_x1 = 0;
4708
0
  bounds_y1 = 0;
4709
0
  bounds_x2 = surface->width;
4710
0
  bounds_y2 = surface->height;
4711
0
  _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
4712
0
                &bounds_x1, &bounds_y1,
4713
0
                &bounds_x2, &bounds_y2,
4714
0
                NULL);
4715
4716
0
  x_scale = surface->base.x_resolution / surface->base.x_fallback_resolution;
4717
0
  y_scale = surface->base.y_resolution / surface->base.y_fallback_resolution;
4718
4719
0
  tolerance = fabs (_cairo_matrix_compute_determinant (&pattern->base.matrix));
4720
0
  tolerance /= _cairo_matrix_transformed_circle_major_axis (&pattern->base.matrix, 1);
4721
0
  tolerance *= MIN (x_scale, y_scale);
4722
4723
0
  _cairo_gradient_pattern_box_to_parameter (pattern,
4724
0
              bounds_x1, bounds_y1,
4725
0
              bounds_x2, bounds_y2,
4726
0
              tolerance, domain);
4727
0
    } else if (pattern->stops[0].offset == pattern->stops[pattern->n_stops - 1].offset) {
4728
  /*
4729
   * If the first and the last stop offset are the same, then
4730
   * the color function is a step function.
4731
   * _cairo_ps_surface_emit_pattern_stops emits it as a stitched
4732
   * function no matter how many stops the pattern has.  The
4733
   * domain of the stitched function will be [0 1] in this case.
4734
   *
4735
   * This is done to avoid emitting degenerate gradients for
4736
   * EXTEND_PAD patterns having a step color function.
4737
   */
4738
0
  domain[0] = 0.0;
4739
0
  domain[1] = 1.0;
4740
4741
0
  assert (pattern->base.extend == CAIRO_EXTEND_PAD);
4742
0
    } else {
4743
0
  domain[0] = pattern->stops[0].offset;
4744
0
  domain[1] = pattern->stops[pattern->n_stops - 1].offset;
4745
0
    }
4746
4747
    /* PDF requires the first and last stop to be the same as the
4748
     * extreme coordinates. For repeating patterns this moves the
4749
     * extreme coordinates out to the begin/end of the repeating
4750
     * function. For non repeating patterns this may move the extreme
4751
     * coordinates in if there are not stops at offset 0 and 1. */
4752
0
    _cairo_gradient_pattern_interpolate (pattern, domain[0], &start);
4753
0
    _cairo_gradient_pattern_interpolate (pattern, domain[1], &end);
4754
4755
0
    if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
4756
0
  pattern->base.extend == CAIRO_EXTEND_REFLECT)
4757
0
    {
4758
0
  int repeat_begin, repeat_end;
4759
4760
0
  repeat_begin = floor (domain[0]);
4761
0
  repeat_end = ceil (domain[1]);
4762
4763
0
  status = _cairo_pdf_surface_emit_repeating_function (surface,
4764
0
                   pattern,
4765
0
                   &color_function,
4766
0
                   repeat_begin,
4767
0
                   repeat_end);
4768
0
  if (unlikely (status))
4769
0
      return status;
4770
4771
0
  if (alpha_function.id != 0) {
4772
0
      status = _cairo_pdf_surface_emit_repeating_function (surface,
4773
0
                 pattern,
4774
0
                 &alpha_function,
4775
0
                 repeat_begin,
4776
0
                 repeat_end);
4777
0
      if (unlikely (status))
4778
0
    return status;
4779
0
  }
4780
0
    } else if (pattern->n_stops <= 2) {
4781
  /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
4782
   * Type 2 function is used by itself without a stitching
4783
   * function. Type 2 functions always have the domain [0 1] */
4784
0
  domain[0] = 0.0;
4785
0
  domain[1] = 1.0;
4786
0
    }
4787
4788
0
    _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
4789
0
    _cairo_pdf_surface_output_gradient (surface, pdf_pattern,
4790
0
          pdf_pattern->pattern_res,
4791
0
          &pat_to_pdf, &start, &end, domain,
4792
0
          "/DeviceRGB", color_function);
4793
4794
0
    if (alpha_function.id != 0) {
4795
0
  cairo_pdf_resource_t mask_resource;
4796
4797
0
  assert (pdf_pattern->gstate_res.id != 0);
4798
4799
        /* Create pattern for SMask. */
4800
0
        mask_resource = _cairo_pdf_surface_new_object (surface);
4801
0
  if (mask_resource.id == 0)
4802
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4803
4804
0
  _cairo_pdf_surface_output_gradient (surface, pdf_pattern,
4805
0
              mask_resource,
4806
0
              &pat_to_pdf, &start, &end, domain,
4807
0
              "/DeviceGray", alpha_function);
4808
4809
0
  status = cairo_pdf_surface_emit_transparency_group (surface,
4810
0
                  pdf_pattern,
4811
0
                        pdf_pattern->gstate_res,
4812
0
                  mask_resource);
4813
0
  if (unlikely (status))
4814
0
      return status;
4815
0
    }
4816
4817
0
    return _cairo_output_stream_get_status (surface->output);
4818
0
}
4819
4820
static cairo_int_status_t
4821
_cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t    *surface,
4822
              cairo_pdf_pattern_t    *pdf_pattern)
4823
0
{
4824
0
    cairo_matrix_t pat_to_pdf;
4825
0
    cairo_int_status_t status;
4826
0
    cairo_pattern_t *pattern = pdf_pattern->pattern;
4827
0
    cairo_pdf_shading_t shading;
4828
0
    int i;
4829
0
    cairo_pdf_resource_t res;
4830
0
    cairo_matrix_t mat;
4831
4832
0
    pat_to_pdf = pattern->matrix;
4833
0
    status = cairo_matrix_invert (&pat_to_pdf);
4834
    /* cairo_pattern_set_matrix ensures the matrix is invertible */
4835
0
    assert (status == CAIRO_INT_STATUS_SUCCESS);
4836
4837
0
    if (pdf_pattern->inverted_y_axis)
4838
0
  cairo_matrix_init (&mat, 1, 0, 0, 1, 0, 0);
4839
0
    else
4840
0
  cairo_matrix_init (&mat, 1, 0, 0, -1, 0, surface->height);
4841
4842
0
    cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &mat);
4843
4844
0
    status = _cairo_pdf_shading_init_color (&shading, (cairo_mesh_pattern_t *) pattern);
4845
0
    if (unlikely (status))
4846
0
  return status;
4847
4848
0
    res = _cairo_pdf_surface_new_object (surface);
4849
0
    if (unlikely (res.id == 0))
4850
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4851
4852
0
    _cairo_output_stream_printf (surface->output,
4853
0
         "%d 0 obj\n"
4854
0
                                 "<< /ShadingType %d\n"
4855
0
                                 "   /ColorSpace /DeviceRGB\n"
4856
0
         "   /BitsPerCoordinate %d\n"
4857
0
         "   /BitsPerComponent %d\n"
4858
0
         "   /BitsPerFlag %d\n"
4859
0
         "   /Decode [",
4860
0
         res.id,
4861
0
         shading.shading_type,
4862
0
         shading.bits_per_coordinate,
4863
0
         shading.bits_per_component,
4864
0
         shading.bits_per_flag);
4865
4866
0
    for (i = 0; i < shading.decode_array_length; i++)
4867
0
  _cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
4868
4869
0
    _cairo_output_stream_printf (surface->output,
4870
0
         "]\n"
4871
0
         "   /Length %ld\n"
4872
0
         ">>\n"
4873
0
         "stream\n",
4874
0
         shading.data_length);
4875
4876
0
    _cairo_output_stream_write (surface->output, shading.data, shading.data_length);
4877
4878
0
    _cairo_output_stream_printf (surface->output,
4879
0
         "\nendstream\n"
4880
0
         "endobj\n");
4881
4882
0
    _cairo_pdf_shading_fini (&shading);
4883
4884
0
    _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
4885
0
    _cairo_output_stream_printf (surface->output,
4886
0
                                 "%d 0 obj\n"
4887
0
                                 "<< /Type /Pattern\n"
4888
0
                                 "   /PatternType 2\n"
4889
0
                                 "   /Matrix [ ",
4890
0
         pdf_pattern->pattern_res.id);
4891
0
    _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
4892
0
    _cairo_output_stream_printf (surface->output,
4893
0
                                 " ]\n"
4894
0
                                 "   /Shading %d 0 R\n"
4895
0
         ">>\n"
4896
0
         "endobj\n",
4897
0
         res.id);
4898
4899
0
    if (pdf_pattern->gstate_res.id != 0) {
4900
0
  cairo_pdf_resource_t mask_resource;
4901
4902
  /* Create pattern for SMask. */
4903
0
        res = _cairo_pdf_surface_new_object (surface);
4904
0
  if (unlikely (res.id == 0))
4905
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4906
4907
0
  status = _cairo_pdf_shading_init_alpha (&shading, (cairo_mesh_pattern_t *) pattern);
4908
0
  if (unlikely (status))
4909
0
      return status;
4910
4911
0
  _cairo_output_stream_printf (surface->output,
4912
0
         "%d 0 obj\n"
4913
0
                                 "<< /ShadingType %d\n"
4914
0
                                 "   /ColorSpace /DeviceGray\n"
4915
0
         "   /BitsPerCoordinate %d\n"
4916
0
         "   /BitsPerComponent %d\n"
4917
0
         "   /BitsPerFlag %d\n"
4918
0
         "   /Decode [",
4919
0
         res.id,
4920
0
         shading.shading_type,
4921
0
         shading.bits_per_coordinate,
4922
0
         shading.bits_per_component,
4923
0
         shading.bits_per_flag);
4924
4925
0
  for (i = 0; i < shading.decode_array_length; i++)
4926
0
      _cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
4927
4928
0
  _cairo_output_stream_printf (surface->output,
4929
0
             "]\n"
4930
0
             "   /Length %ld\n"
4931
0
             ">>\n"
4932
0
             "stream\n",
4933
0
             shading.data_length);
4934
4935
0
  _cairo_output_stream_write (surface->output, shading.data, shading.data_length);
4936
4937
0
  _cairo_output_stream_printf (surface->output,
4938
0
             "\nendstream\n"
4939
0
             "endobj\n");
4940
0
  _cairo_pdf_shading_fini (&shading);
4941
4942
0
        mask_resource = _cairo_pdf_surface_new_object (surface);
4943
0
  if (unlikely (mask_resource.id == 0))
4944
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4945
4946
0
  _cairo_output_stream_printf (surface->output,
4947
0
             "%d 0 obj\n"
4948
0
             "<< /Type /Pattern\n"
4949
0
             "   /PatternType 2\n"
4950
0
             "   /Matrix [ ",
4951
0
             mask_resource.id);
4952
0
  _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
4953
0
  _cairo_output_stream_printf (surface->output,
4954
0
             " ]\n"
4955
0
             "   /Shading %d 0 R\n"
4956
0
             ">>\n"
4957
0
             "endobj\n",
4958
0
             res.id);
4959
4960
0
  status = cairo_pdf_surface_emit_transparency_group (surface,
4961
0
                  pdf_pattern,
4962
0
                        pdf_pattern->gstate_res,
4963
0
                  mask_resource);
4964
0
  if (unlikely (status))
4965
0
      return status;
4966
0
    }
4967
4968
0
    return _cairo_output_stream_get_status (surface->output);
4969
0
}
4970
4971
static cairo_int_status_t
4972
_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
4973
0
{
4974
0
    cairo_int_status_t status;
4975
4976
0
    switch (pdf_pattern->pattern->type) {
4977
0
    case CAIRO_PATTERN_TYPE_SOLID:
4978
0
  ASSERT_NOT_REACHED;
4979
0
  status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4980
0
  break;
4981
4982
0
    case CAIRO_PATTERN_TYPE_SURFACE:
4983
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4984
0
  status = _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
4985
0
  break;
4986
4987
0
    case CAIRO_PATTERN_TYPE_LINEAR:
4988
0
    case CAIRO_PATTERN_TYPE_RADIAL:
4989
0
  status = _cairo_pdf_surface_emit_gradient (surface, pdf_pattern);
4990
0
  break;
4991
4992
0
    case CAIRO_PATTERN_TYPE_MESH:
4993
0
  status = _cairo_pdf_surface_emit_mesh_pattern (surface, pdf_pattern);
4994
0
  break;
4995
4996
0
    default:
4997
0
  ASSERT_NOT_REACHED;
4998
0
  status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4999
0
  break;
5000
0
    }
5001
5002
0
    return status;
5003
0
}
5004
5005
static cairo_int_status_t
5006
_cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t          *surface,
5007
            cairo_operator_t              op,
5008
            const cairo_pattern_t        *source,
5009
            const cairo_rectangle_int_t  *extents,
5010
            double                        alpha,
5011
            cairo_pdf_resource_t         *smask_res,
5012
            cairo_bool_t                  stencil_mask)
5013
0
{
5014
0
    cairo_matrix_t cairo_p2d, pdf_p2d;
5015
0
    cairo_int_status_t status;
5016
0
    int alpha_id;
5017
0
    double x_offset;
5018
0
    double y_offset;
5019
0
    cairo_pdf_source_surface_entry_t *pdf_source;
5020
5021
0
    if (source->extend == CAIRO_EXTEND_PAD &&
5022
0
  !(source->type == CAIRO_PATTERN_TYPE_SURFACE &&
5023
0
    ((cairo_surface_pattern_t *)source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING))
5024
0
    {
5025
0
  status = _cairo_pdf_surface_add_padded_image_surface (surface,
5026
0
                    source,
5027
0
                    extents,
5028
0
                    &pdf_source,
5029
0
                    &x_offset,
5030
0
                    &y_offset,
5031
0
                    NULL);
5032
0
    } else {
5033
0
  status = _cairo_pdf_surface_add_source_surface (surface,
5034
0
              NULL,
5035
0
              source,
5036
0
              op,
5037
0
              source->filter,
5038
0
              stencil_mask,
5039
0
              FALSE, /* smask */
5040
0
              alpha != 1.0, /* need_transp_group */
5041
0
              extents,
5042
0
              smask_res,
5043
0
              &pdf_source,
5044
0
              &x_offset,
5045
0
              &y_offset,
5046
0
              NULL);
5047
0
    }
5048
0
    if (unlikely (status))
5049
0
  return status;
5050
5051
0
    cairo_p2d = source->matrix;
5052
0
    status = cairo_matrix_invert (&cairo_p2d);
5053
    /* cairo_pattern_set_matrix ensures the matrix is invertible */
5054
0
    assert (status == CAIRO_INT_STATUS_SUCCESS);
5055
5056
0
    pdf_p2d = surface->cairo_to_pdf;
5057
0
    cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
5058
0
    cairo_matrix_translate (&pdf_p2d, x_offset, y_offset);
5059
0
    if (pdf_source->emit_image) {
5060
0
  int width, height;
5061
5062
0
  if (pdf_source->bounded) {
5063
0
      width = pdf_source->extents.width;
5064
0
      height = pdf_source->extents.height;
5065
0
  } else {
5066
      /* We can't scale an image to an unbounded surface size so just set the size to 1 */
5067
0
      width = 1;
5068
0
      height = 1;
5069
0
  }
5070
5071
0
  cairo_matrix_translate (&pdf_p2d, 0.0, height);
5072
0
  cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
5073
0
  cairo_matrix_scale (&pdf_p2d, width, height);
5074
0
    }
5075
5076
0
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5077
0
    if (unlikely (status))
5078
0
  return status;
5079
5080
0
    if (! _cairo_matrix_is_identity (&pdf_p2d)) {
5081
0
  _cairo_output_stream_print_matrix (surface->output, &pdf_p2d);
5082
0
  _cairo_output_stream_printf (surface->output, " cm\n");
5083
0
    }
5084
5085
0
    status = _cairo_pdf_surface_add_alpha (surface, alpha, &alpha_id);
5086
0
    if (unlikely (status))
5087
0
  return status;
5088
5089
0
    if (stencil_mask) {
5090
0
  _cairo_output_stream_printf (surface->output,
5091
0
             "/x%d Do\n",
5092
0
             pdf_source->surface_res.id);
5093
0
    } else {
5094
0
  _cairo_output_stream_printf (surface->output,
5095
0
             "/a%d gs /x%d Do\n",
5096
0
             alpha_id,
5097
0
             pdf_source->surface_res.id);
5098
0
    }
5099
5100
0
    return _cairo_pdf_surface_add_xobject (surface, pdf_source->surface_res);
5101
0
}
5102
5103
static cairo_int_status_t
5104
_cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t         *surface,
5105
           cairo_operator_t             op,
5106
           const cairo_pattern_t       *source,
5107
           const cairo_rectangle_int_t *extents,
5108
           double                       alpha)
5109
0
{
5110
0
    cairo_pdf_resource_t shading_res, gstate_res;
5111
0
    cairo_matrix_t pat_to_pdf;
5112
0
    cairo_int_status_t status;
5113
0
    int alpha_id;
5114
5115
0
    status = _cairo_pdf_surface_add_pdf_shading (surface, source,
5116
0
             op, extents,
5117
0
             &shading_res, &gstate_res);
5118
0
    if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
5119
0
  return CAIRO_INT_STATUS_SUCCESS;
5120
0
    if (unlikely (status))
5121
0
  return status;
5122
5123
0
    pat_to_pdf = source->matrix;
5124
0
    status = cairo_matrix_invert (&pat_to_pdf);
5125
    /* cairo_pattern_set_matrix ensures the matrix is invertible */
5126
0
    assert (status == CAIRO_INT_STATUS_SUCCESS);
5127
0
    cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
5128
5129
0
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5130
0
    if (unlikely (status))
5131
0
  return status;
5132
5133
0
    if (! _cairo_matrix_is_identity (&pat_to_pdf)) {
5134
0
  _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
5135
0
  _cairo_output_stream_printf (surface->output, " cm\n");
5136
0
    }
5137
5138
0
    status = _cairo_pdf_surface_add_shading (surface, shading_res);
5139
0
    if (unlikely (status))
5140
0
  return status;
5141
5142
0
    if (gstate_res.id != 0) {
5143
0
  status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5144
0
  if (unlikely (status))
5145
0
      return status;
5146
5147
0
  _cairo_output_stream_printf (surface->output,
5148
0
             "/s%d gs /sh%d sh\n",
5149
0
             gstate_res.id,
5150
0
             shading_res.id);
5151
0
    } else {
5152
0
  status = _cairo_pdf_surface_add_alpha (surface, alpha, &alpha_id);
5153
0
  if (unlikely (status))
5154
0
      return status;
5155
5156
0
  _cairo_output_stream_printf (surface->output,
5157
0
             "/a%d gs /sh%d sh\n",
5158
0
             alpha_id,
5159
0
             shading_res.id);
5160
0
    }
5161
5162
0
    return status;
5163
0
}
5164
5165
static cairo_int_status_t
5166
_cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t          *surface,
5167
          cairo_operator_t              op,
5168
          const cairo_pattern_t        *source,
5169
          const cairo_rectangle_int_t  *extents,
5170
          double                        alpha,
5171
          cairo_bool_t                  mask)
5172
0
{
5173
0
    switch (source->type) {
5174
0
    case CAIRO_PATTERN_TYPE_SURFACE:
5175
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
5176
0
  return _cairo_pdf_surface_paint_surface_pattern (surface,
5177
0
               op,
5178
0
               source,
5179
0
               extents,
5180
0
               alpha,
5181
0
               NULL,
5182
0
               mask);
5183
0
    case CAIRO_PATTERN_TYPE_LINEAR:
5184
0
    case CAIRO_PATTERN_TYPE_RADIAL:
5185
0
    case CAIRO_PATTERN_TYPE_MESH:
5186
0
  return _cairo_pdf_surface_paint_gradient (surface,
5187
0
              op,
5188
0
              source,
5189
0
              extents,
5190
0
              alpha);
5191
5192
0
    case CAIRO_PATTERN_TYPE_SOLID:
5193
0
    default:
5194
0
  ASSERT_NOT_REACHED;
5195
0
  return CAIRO_STATUS_SUCCESS;
5196
0
    }
5197
0
}
5198
5199
static cairo_bool_t
5200
_can_paint_pattern (const cairo_pattern_t *pattern)
5201
0
{
5202
0
    switch (pattern->type) {
5203
0
    case CAIRO_PATTERN_TYPE_SOLID:
5204
0
  return FALSE;
5205
5206
0
    case CAIRO_PATTERN_TYPE_SURFACE:
5207
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
5208
0
  return (pattern->extend == CAIRO_EXTEND_NONE ||
5209
0
    pattern->extend == CAIRO_EXTEND_PAD);
5210
5211
0
    case CAIRO_PATTERN_TYPE_LINEAR:
5212
0
    case CAIRO_PATTERN_TYPE_RADIAL:
5213
0
  return TRUE;
5214
5215
0
    case CAIRO_PATTERN_TYPE_MESH:
5216
0
  return FALSE;
5217
5218
0
    default:
5219
0
  ASSERT_NOT_REACHED;
5220
0
  return FALSE;
5221
0
    }
5222
0
}
5223
5224
static cairo_int_status_t
5225
_cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface,
5226
            cairo_operator_t     op)
5227
0
{
5228
0
    cairo_int_status_t status;
5229
5230
0
    if (op == surface->current_operator)
5231
0
  return CAIRO_STATUS_SUCCESS;
5232
5233
0
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5234
0
    if (unlikely (status))
5235
0
  return status;
5236
5237
0
    _cairo_output_stream_printf (surface->output,
5238
0
         "/b%d gs\n", op);
5239
0
    surface->current_operator = op;
5240
0
    _cairo_pdf_surface_add_operator (surface, op);
5241
5242
0
    return CAIRO_STATUS_SUCCESS;
5243
0
}
5244
5245
static cairo_int_status_t
5246
_cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
5247
           const cairo_pattern_t     *pattern,
5248
           cairo_pdf_resource_t pattern_res,
5249
           cairo_bool_t         is_stroke)
5250
0
{
5251
0
    cairo_int_status_t status;
5252
0
    int alpha;
5253
0
    const cairo_color_t *solid_color = NULL;
5254
5255
0
    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
5256
0
  const cairo_solid_pattern_t *solid = (const cairo_solid_pattern_t *) pattern;
5257
5258
0
  solid_color = &solid->color;
5259
0
    }
5260
5261
0
    if (solid_color != NULL) {
5262
0
  if (surface->current_pattern_is_solid_color == FALSE ||
5263
0
      surface->current_color_red != solid_color->red ||
5264
0
      surface->current_color_green != solid_color->green ||
5265
0
      surface->current_color_blue != solid_color->blue ||
5266
0
      surface->current_color_is_stroke != is_stroke)
5267
0
  {
5268
0
      status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5269
0
      if (unlikely (status))
5270
0
    return status;
5271
5272
0
      _cairo_output_stream_printf (surface->output,
5273
0
           "%f %f %f ",
5274
0
           solid_color->red,
5275
0
           solid_color->green,
5276
0
           solid_color->blue);
5277
5278
0
      if (is_stroke)
5279
0
    _cairo_output_stream_printf (surface->output, "RG ");
5280
0
      else
5281
0
    _cairo_output_stream_printf (surface->output, "rg ");
5282
5283
0
      surface->current_color_red = solid_color->red;
5284
0
      surface->current_color_green = solid_color->green;
5285
0
      surface->current_color_blue = solid_color->blue;
5286
0
      surface->current_color_is_stroke = is_stroke;
5287
0
  }
5288
5289
0
  if (surface->current_pattern_is_solid_color == FALSE ||
5290
0
      surface->current_color_alpha != solid_color->alpha)
5291
0
  {
5292
0
      status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha);
5293
0
      if (unlikely (status))
5294
0
    return status;
5295
5296
0
      status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5297
0
      if (unlikely (status))
5298
0
    return status;
5299
5300
0
      _cairo_output_stream_printf (surface->output,
5301
0
           "/a%d gs\n",
5302
0
           alpha);
5303
0
      surface->current_color_alpha = solid_color->alpha;
5304
0
  }
5305
5306
0
  surface->current_pattern_is_solid_color = TRUE;
5307
0
    } else {
5308
0
  status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
5309
0
  if (unlikely (status))
5310
0
      return status;
5311
5312
0
  status = _cairo_pdf_surface_add_pattern (surface, pattern_res);
5313
0
  if (unlikely (status))
5314
0
      return status;
5315
5316
0
  status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5317
0
  if (unlikely (status))
5318
0
      return status;
5319
5320
  /* fill-stroke calls select_pattern twice. Don't save if the
5321
   * gstate is already saved. */
5322
0
  if (!surface->select_pattern_gstate_saved)
5323
0
      _cairo_output_stream_printf (surface->output, "q ");
5324
5325
0
  if (is_stroke) {
5326
0
      _cairo_output_stream_printf (surface->output,
5327
0
           "/Pattern CS /p%d SCN ",
5328
0
           pattern_res.id);
5329
0
  } else {
5330
0
      _cairo_output_stream_printf (surface->output,
5331
0
           "/Pattern cs /p%d scn ",
5332
0
           pattern_res.id);
5333
0
  }
5334
0
  _cairo_output_stream_printf (surface->output,
5335
0
             "/a%d gs\n",
5336
0
             alpha);
5337
0
  surface->select_pattern_gstate_saved = TRUE;
5338
0
  surface->current_pattern_is_solid_color = FALSE;
5339
0
    }
5340
5341
0
    return _cairo_output_stream_get_status (surface->output);
5342
0
}
5343
5344
static cairo_int_status_t
5345
_cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
5346
0
{
5347
0
    cairo_int_status_t status;
5348
5349
0
    if (surface->select_pattern_gstate_saved) {
5350
0
  status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5351
0
  if (unlikely (status))
5352
0
      return status;
5353
5354
0
  _cairo_output_stream_printf (surface->output, "Q\n");
5355
0
  _cairo_pdf_operators_reset (&surface->pdf_operators);
5356
0
  surface->current_pattern_is_solid_color = FALSE;
5357
0
    }
5358
0
    surface->select_pattern_gstate_saved = FALSE;
5359
5360
0
    return CAIRO_STATUS_SUCCESS;
5361
0
}
5362
5363
static cairo_int_status_t
5364
_cairo_pdf_surface_show_page (void *abstract_surface)
5365
2
{
5366
2
    cairo_pdf_surface_t *surface = abstract_surface;
5367
2
    cairo_int_status_t status;
5368
5369
2
    status = _cairo_array_append (&surface->page_heights, &surface->height);
5370
2
    if (unlikely (status))
5371
0
  return status;
5372
5373
2
    status = _cairo_array_append (&surface->page_labels, &surface->current_page_label);
5374
2
    if (unlikely (status))
5375
0
  return status;
5376
5377
2
    surface->current_page_label = NULL;
5378
5379
2
    status = _cairo_pdf_interchange_end_page_content (surface);
5380
2
    if (unlikely (status))
5381
0
  return status;
5382
5383
2
    status = _cairo_pdf_surface_close_content_stream (surface);
5384
2
    if (unlikely (status))
5385
0
  return status;
5386
5387
2
    _cairo_surface_clipper_reset (&surface->clipper);
5388
5389
2
    status = _cairo_pdf_surface_write_page (surface);
5390
2
    if (unlikely (status))
5391
0
  return status;
5392
5393
2
    _cairo_pdf_surface_clear (surface);
5394
5395
2
    return CAIRO_STATUS_SUCCESS;
5396
2
}
5397
5398
static cairo_bool_t
5399
_cairo_pdf_surface_get_extents (void            *abstract_surface,
5400
        cairo_rectangle_int_t   *rectangle)
5401
4
{
5402
4
    cairo_pdf_surface_t *surface = abstract_surface;
5403
5404
4
    if (surface->surface_bounded)
5405
4
  *rectangle = surface->surface_extents;
5406
5407
4
    return surface->surface_bounded;
5408
4
}
5409
5410
static void
5411
_cairo_pdf_surface_get_font_options (void                  *abstract_surface,
5412
             cairo_font_options_t  *options)
5413
2
{
5414
2
    _cairo_font_options_init_default (options);
5415
5416
2
    cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
5417
2
    cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
5418
2
    cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
5419
2
    _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_OFF);
5420
2
}
5421
5422
static cairo_int_status_t
5423
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
5424
2
{
5425
2
    cairo_pdf_resource_t page;
5426
2
    int num_pages, i;
5427
2
    cairo_int_status_t status;
5428
5429
2
    status = _cairo_pdf_surface_object_begin (surface, surface->pages_resource);
5430
2
    if (unlikely (status))
5431
0
  return status;
5432
5433
2
    _cairo_output_stream_printf (surface->object_stream.stream,
5434
2
         "<< /Type /Pages\n"
5435
2
         "   /Kids [ ");
5436
5437
2
    num_pages = _cairo_array_num_elements (&surface->pages);
5438
4
    for (i = 0; i < num_pages; i++) {
5439
2
  _cairo_array_copy_element (&surface->pages, i, &page);
5440
2
  _cairo_output_stream_printf (surface->object_stream.stream, "%d 0 R ", page.id);
5441
2
    }
5442
5443
2
    _cairo_output_stream_printf (surface->object_stream.stream, "]\n");
5444
2
    _cairo_output_stream_printf (surface->object_stream.stream, "   /Count %d\n", num_pages);
5445
5446
5447
    /* TODO: Figure out which other defaults to be inherited by /Page
5448
     * objects. */
5449
2
    _cairo_output_stream_printf (surface->object_stream.stream,
5450
2
         ">>\n");
5451
2
    _cairo_pdf_surface_object_end (surface);
5452
5453
2
    return CAIRO_INT_STATUS_SUCCESS;
5454
2
}
5455
5456
cairo_int_status_t
5457
_cairo_utf8_to_pdf_string (const char *utf8, char **str_out)
5458
0
{
5459
0
    int i;
5460
0
    int len;
5461
0
    unsigned char *p;
5462
0
    cairo_bool_t ascii;
5463
0
    char *str;
5464
0
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
5465
5466
0
    ascii = TRUE;
5467
0
    p = (unsigned char *)utf8;
5468
0
    len = 0;
5469
0
    while (*p) {
5470
0
  if (*p < 32 || *p > 126) {
5471
0
      ascii = FALSE;
5472
0
      break;
5473
0
  }
5474
0
  if (*p == '(' || *p == ')' || *p == '\\')
5475
0
      len += 2;
5476
0
  else
5477
0
      len++;
5478
0
  p++;
5479
0
    }
5480
5481
0
    if (ascii) {
5482
0
  str = _cairo_malloc (len + 3);
5483
0
  if (str == NULL)
5484
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5485
5486
0
  str[0] = '(';
5487
0
  p = (unsigned char *)utf8;
5488
0
  i = 1;
5489
0
  while (*p) {
5490
0
      if (*p == '(' || *p == ')' || *p == '\\')
5491
0
    str[i++] = '\\';
5492
0
      str[i++] = *p;
5493
0
      p++;
5494
0
  }
5495
0
  str[i++] = ')';
5496
0
  str[i++] = 0;
5497
0
    } else {
5498
0
  uint16_t *utf16 = NULL;
5499
0
  int utf16_len = 0;
5500
5501
0
  status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
5502
0
  if (unlikely (status))
5503
0
      return status;
5504
5505
0
  str = _cairo_malloc (utf16_len*4 + 7);
5506
0
  if (str == NULL) {
5507
0
      free (utf16);
5508
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5509
0
  }
5510
5511
0
  strcpy (str, "<FEFF");
5512
0
  for (i = 0; i < utf16_len; i++)
5513
0
      snprintf (str + 4*i + 5, 5, "%04X", utf16[i]);
5514
5515
0
  strcat (str, ">");
5516
0
  free (utf16);
5517
0
    }
5518
0
    *str_out = str;
5519
5520
0
    return status;
5521
0
}
5522
5523
static cairo_int_status_t
5524
_cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t  *surface,
5525
             const char     *utf8)
5526
0
{
5527
0
    uint16_t *utf16 = NULL;
5528
0
    int utf16_len = 0;
5529
0
    cairo_int_status_t status;
5530
0
    int i;
5531
5532
0
    if (utf8 && *utf8) {
5533
0
  status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
5534
0
  if (unlikely (status == CAIRO_INT_STATUS_INVALID_STRING)) {
5535
0
      utf16 = NULL;
5536
0
      utf16_len = 0;
5537
0
  } else if (unlikely (status)) {
5538
0
      return status;
5539
0
  }
5540
0
    }
5541
5542
0
    _cairo_output_stream_printf (surface->output, "<");
5543
0
    if (utf16 == NULL || utf16_len == 0) {
5544
  /* According to the "ToUnicode Mapping File Tutorial"
5545
   * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
5546
   *
5547
   * Glyphs that do not map to a Unicode code point must be
5548
   * mapped to 0xfffd "REPLACEMENT CHARACTER".
5549
   */
5550
0
  _cairo_output_stream_printf (surface->output,
5551
0
             "fffd");
5552
0
    } else {
5553
0
  for (i = 0; i < utf16_len; i++)
5554
0
      _cairo_output_stream_printf (surface->output,
5555
0
           "%04x", (int) (utf16[i]));
5556
0
    }
5557
0
    _cairo_output_stream_printf (surface->output, ">");
5558
5559
0
    free (utf16);
5560
5561
0
    return CAIRO_STATUS_SUCCESS;
5562
0
}
5563
5564
/* Bob Jenkins hash
5565
 *
5566
 * Public domain code from:
5567
 *   http://burtleburtle.net/bob/hash/doobs.html
5568
 */
5569
5570
0
#define HASH_MIX(a,b,c)     \
5571
0
{           \
5572
0
    a -= b; a -= c; a ^= (c>>13); \
5573
0
    b -= c; b -= a; b ^= (a<<8);  \
5574
0
    c -= a; c -= b; c ^= (b>>13); \
5575
0
    a -= b; a -= c; a ^= (c>>12); \
5576
0
    b -= c; b -= a; b ^= (a<<16); \
5577
0
    c -= a; c -= b; c ^= (b>>5);  \
5578
0
    a -= b; a -= c; a ^= (c>>3);  \
5579
0
    b -= c; b -= a; b ^= (a<<10); \
5580
0
    c -= a; c -= b; c ^= (b>>15); \
5581
0
}
5582
5583
static uint32_t
5584
_hash_data (const unsigned char *data, int length, uint32_t initval)
5585
0
{
5586
0
    uint32_t a, b, c, len;
5587
5588
0
    len = length;
5589
0
    a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
5590
0
    c = initval;         /* the previous hash value */
5591
5592
0
    while (len >= 12) {
5593
0
  a += (data[0] + ((uint32_t)data[1]<<8) + ((uint32_t)data[2]<<16) + ((uint32_t)data[3]<<24));
5594
0
  b += (data[4] + ((uint32_t)data[5]<<8) + ((uint32_t)data[6]<<16) + ((uint32_t)data[7]<<24));
5595
0
  c += (data[8] + ((uint32_t)data[9]<<8) + ((uint32_t)data[10]<<16)+ ((uint32_t)data[11]<<24));
5596
0
  HASH_MIX (a,b,c);
5597
0
  data += 12;
5598
0
  len -= 12;
5599
0
    }
5600
5601
0
    c += length;
5602
0
    switch(len) {
5603
0
    case 11: c+= ((uint32_t) data[10] << 24); /* fall through */
5604
0
    case 10: c+= ((uint32_t) data[9] << 16);  /* fall through */
5605
0
    case 9 : c+= ((uint32_t) data[8] << 8);   /* fall through */
5606
0
    case 8 : b+= ((uint32_t) data[7] << 24);  /* fall through */
5607
0
    case 7 : b+= ((uint32_t) data[6] << 16);  /* fall through */
5608
0
    case 6 : b+= ((uint32_t) data[5] << 8);   /* fall through */
5609
0
    case 5 : b+= data[4];         /* fall through */
5610
0
    case 4 : a+= ((uint32_t) data[3] << 24);  /* fall through */
5611
0
    case 3 : a+= ((uint32_t) data[2] << 16);  /* fall through */
5612
0
    case 2 : a+= ((uint32_t) data[1] << 8);   /* fall through */
5613
0
    case 1 : a+= data[0];
5614
0
    }
5615
0
    HASH_MIX (a,b,c);
5616
5617
0
    return c;
5618
0
}
5619
5620
static void
5621
_create_font_subset_tag (cairo_scaled_font_subset_t *font_subset,
5622
       const char       *font_name,
5623
       char       *tag)
5624
0
{
5625
0
    uint32_t hash;
5626
0
    int i;
5627
5628
0
    hash = _hash_data ((unsigned char *) font_name, strlen(font_name), 0);
5629
0
    hash = _hash_data ((unsigned char *) (font_subset->glyphs),
5630
0
           font_subset->num_glyphs * sizeof(unsigned long), hash);
5631
5632
0
    for (i = 0; i < 6; i++) {
5633
0
  tag[i] = 'A' + (hash % 26);
5634
0
  hash /= 26;
5635
0
    }
5636
0
    tag[i] = 0;
5637
0
}
5638
5639
static cairo_int_status_t
5640
_cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t    *surface,
5641
             cairo_scaled_font_subset_t *font_subset,
5642
             cairo_pdf_resource_t         *stream)
5643
0
{
5644
0
    unsigned int i, num_bfchar;
5645
0
    cairo_int_status_t status;
5646
5647
0
    stream->id = 0;
5648
5649
0
    status = _cairo_pdf_surface_open_stream (surface,
5650
0
                NULL,
5651
0
                surface->compress_streams,
5652
0
                NULL);
5653
0
    if (unlikely (status))
5654
0
  return status;
5655
5656
0
    _cairo_output_stream_printf (surface->output,
5657
0
                                 "/CIDInit /ProcSet findresource begin\n"
5658
0
                                 "12 dict begin\n"
5659
0
                                 "begincmap\n"
5660
0
                                 "/CIDSystemInfo\n"
5661
0
                                 "<< /Registry (Adobe)\n"
5662
0
                                 "   /Ordering (UCS)\n"
5663
0
                                 "   /Supplement 0\n"
5664
0
                                 ">> def\n"
5665
0
                                 "/CMapName /Adobe-Identity-UCS def\n"
5666
0
                                 "/CMapType 2 def\n"
5667
0
                                 "1 begincodespacerange\n");
5668
5669
0
    if (font_subset->is_composite && !font_subset->is_latin) {
5670
0
        _cairo_output_stream_printf (surface->output,
5671
0
                                     "<0000> <ffff>\n");
5672
0
    } else {
5673
0
        _cairo_output_stream_printf (surface->output,
5674
0
                                     "<00> <ff>\n");
5675
0
    }
5676
5677
0
    _cairo_output_stream_printf (surface->output,
5678
0
                                  "endcodespacerange\n");
5679
5680
0
    if (font_subset->is_scaled) {
5681
  /* Type 3 fonts include glyph 0 in the subset */
5682
0
  num_bfchar = font_subset->num_glyphs;
5683
5684
  /* The CMap specification has a limit of 100 characters per beginbfchar operator */
5685
0
  _cairo_output_stream_printf (surface->output,
5686
0
             "%d beginbfchar\n",
5687
0
             num_bfchar > 100 ? 100 : num_bfchar);
5688
5689
0
  for (i = 0; i < num_bfchar; i++) {
5690
0
      if (i != 0 && i % 100 == 0) {
5691
0
    _cairo_output_stream_printf (surface->output,
5692
0
               "endbfchar\n"
5693
0
               "%d beginbfchar\n",
5694
0
               num_bfchar - i > 100 ? 100 : num_bfchar - i);
5695
0
      }
5696
0
      _cairo_output_stream_printf (surface->output, "<%02x> ", i);
5697
0
      status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
5698
0
                font_subset->utf8[i]);
5699
0
      if (unlikely (status))
5700
0
    return status;
5701
5702
0
      _cairo_output_stream_printf (surface->output,
5703
0
           "\n");
5704
0
  }
5705
0
    } else {
5706
  /* Other fonts reserve glyph 0 for .notdef. Omit glyph 0 from the /ToUnicode map */
5707
0
  num_bfchar = font_subset->num_glyphs - 1;
5708
5709
  /* The CMap specification has a limit of 100 characters per beginbfchar operator */
5710
0
  _cairo_output_stream_printf (surface->output,
5711
0
             "%d beginbfchar\n",
5712
0
             num_bfchar > 100 ? 100 : num_bfchar);
5713
5714
0
  for (i = 0; i < num_bfchar; i++) {
5715
0
      if (i != 0 && i % 100 == 0) {
5716
0
    _cairo_output_stream_printf (surface->output,
5717
0
               "endbfchar\n"
5718
0
               "%d beginbfchar\n",
5719
0
               num_bfchar - i > 100 ? 100 : num_bfchar - i);
5720
0
      }
5721
0
      if (font_subset->is_latin)
5722
0
    _cairo_output_stream_printf (surface->output, "<%02x> ", font_subset->to_latin_char[i + 1]);
5723
0
      else if (font_subset->is_composite)
5724
0
    _cairo_output_stream_printf (surface->output, "<%04x> ", i + 1);
5725
0
      else
5726
0
    _cairo_output_stream_printf (surface->output, "<%02x> ", i + 1);
5727
5728
0
      status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
5729
0
                font_subset->utf8[i + 1]);
5730
0
      if (unlikely (status))
5731
0
    return status;
5732
5733
0
      _cairo_output_stream_printf (surface->output,
5734
0
           "\n");
5735
0
  }
5736
0
    }
5737
5738
0
    _cairo_output_stream_printf (surface->output,
5739
0
                                 "endbfchar\n");
5740
5741
0
    _cairo_output_stream_printf (surface->output,
5742
0
                                 "endcmap\n"
5743
0
                                 "CMapName currentdict /CMap defineresource pop\n"
5744
0
                                 "end\n"
5745
0
                                 "end\n");
5746
5747
0
    *stream = surface->pdf_stream.self;
5748
0
    return _cairo_pdf_surface_close_stream (surface);
5749
0
}
5750
5751
0
#define PDF_UNITS_PER_EM 1000
5752
5753
static cairo_int_status_t
5754
_cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t   *surface,
5755
                                  cairo_scaled_font_subset_t  *font_subset,
5756
                                  cairo_cff_subset_t            *subset)
5757
0
{
5758
0
    cairo_pdf_resource_t stream, descriptor, cidfont_dict;
5759
0
    cairo_pdf_resource_t subset_resource, to_unicode_stream;
5760
0
    cairo_pdf_font_t font;
5761
0
    unsigned int i, last_glyph;
5762
0
    cairo_int_status_t status;
5763
0
    char tag[10];
5764
5765
0
    _create_font_subset_tag (font_subset, subset->ps_name, tag);
5766
5767
0
    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
5768
0
                  font_subset->font_id,
5769
0
                  font_subset->subset_id);
5770
0
    if (subset_resource.id == 0)
5771
0
  return CAIRO_STATUS_SUCCESS;
5772
5773
0
    status = _cairo_pdf_surface_open_stream (surface,
5774
0
               NULL,
5775
0
               TRUE,
5776
0
               font_subset->is_latin ?
5777
0
               "   /Subtype /Type1C\n" :
5778
0
               "   /Subtype /CIDFontType0C\n");
5779
0
    if (unlikely (status))
5780
0
  return status;
5781
5782
0
    stream = surface->pdf_stream.self;
5783
0
    _cairo_output_stream_write (surface->output,
5784
0
        subset->data, subset->data_length);
5785
0
    status = _cairo_pdf_surface_close_stream (surface);
5786
0
    if (unlikely (status))
5787
0
  return status;
5788
5789
0
    status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
5790
0
                                                  font_subset,
5791
0
              &to_unicode_stream);
5792
0
    if (_cairo_int_status_is_error (status))
5793
0
  return status;
5794
5795
0
    descriptor = _cairo_pdf_surface_new_object (surface);
5796
0
    if (descriptor.id == 0)
5797
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5798
5799
0
    _cairo_output_stream_printf (surface->output,
5800
0
         "%d 0 obj\n"
5801
0
         "<< /Type /FontDescriptor\n"
5802
0
         "   /FontName /%s+%s\n",
5803
0
         descriptor.id,
5804
0
         tag,
5805
0
         subset->ps_name);
5806
5807
0
    if (subset->family_name_utf8) {
5808
0
  char *pdf_str;
5809
5810
0
  status = _cairo_utf8_to_pdf_string (subset->family_name_utf8, &pdf_str);
5811
0
  if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
5812
0
      _cairo_output_stream_printf (surface->output,
5813
0
           "   /FontFamily %s\n",
5814
0
           pdf_str);
5815
0
      free (pdf_str);
5816
0
  } else if (status != CAIRO_INT_STATUS_INVALID_STRING) {
5817
0
      return status;
5818
0
  }
5819
0
    }
5820
5821
0
    _cairo_output_stream_printf (surface->output,
5822
0
         "   /Flags 4\n"
5823
0
         "   /FontBBox [ %ld %ld %ld %ld ]\n"
5824
0
         "   /ItalicAngle 0\n"
5825
0
         "   /Ascent %ld\n"
5826
0
         "   /Descent %ld\n"
5827
0
         "   /CapHeight %ld\n"
5828
0
         "   /StemV 80\n"
5829
0
         "   /StemH 80\n"
5830
0
         "   /FontFile3 %u 0 R\n"
5831
0
         ">>\n"
5832
0
         "endobj\n",
5833
0
         (long)(subset->x_min*PDF_UNITS_PER_EM),
5834
0
         (long)(subset->y_min*PDF_UNITS_PER_EM),
5835
0
         (long)(subset->x_max*PDF_UNITS_PER_EM),
5836
0
         (long)(subset->y_max*PDF_UNITS_PER_EM),
5837
0
         (long)(subset->ascent*PDF_UNITS_PER_EM),
5838
0
         (long)(subset->descent*PDF_UNITS_PER_EM),
5839
0
         (long)(subset->y_max*PDF_UNITS_PER_EM),
5840
0
         stream.id);
5841
5842
0
    if (font_subset->is_latin) {
5843
  /* find last glyph used */
5844
0
  for (i = 255; i >= 32; i--)
5845
0
      if (font_subset->latin_to_subset_glyph_index[i] > 0)
5846
0
    break;
5847
5848
0
  last_glyph = i;
5849
0
  _cairo_pdf_surface_update_object (surface, subset_resource);
5850
0
  _cairo_output_stream_printf (surface->output,
5851
0
             "%d 0 obj\n"
5852
0
             "<< /Type /Font\n"
5853
0
             "   /Subtype /Type1\n"
5854
0
             "   /BaseFont /%s+%s\n"
5855
0
             "   /FirstChar 32\n"
5856
0
             "   /LastChar %d\n"
5857
0
             "   /FontDescriptor %d 0 R\n"
5858
0
             "   /Encoding /WinAnsiEncoding\n"
5859
0
             "   /Widths [",
5860
0
             subset_resource.id,
5861
0
             tag,
5862
0
             subset->ps_name,
5863
0
             last_glyph,
5864
0
             descriptor.id);
5865
5866
0
  for (i = 32; i < last_glyph + 1; i++) {
5867
0
      int glyph = font_subset->latin_to_subset_glyph_index[i];
5868
0
      if (glyph > 0) {
5869
0
    _cairo_output_stream_printf (surface->output,
5870
0
               " %f",
5871
0
               (subset->widths[glyph]*PDF_UNITS_PER_EM));
5872
0
      } else {
5873
0
    _cairo_output_stream_printf (surface->output, " 0");
5874
0
      }
5875
0
  }
5876
5877
0
  _cairo_output_stream_printf (surface->output,
5878
0
             " ]\n");
5879
5880
0
  if (to_unicode_stream.id != 0)
5881
0
      _cairo_output_stream_printf (surface->output,
5882
0
           "    /ToUnicode %d 0 R\n",
5883
0
           to_unicode_stream.id);
5884
5885
0
  _cairo_output_stream_printf (surface->output,
5886
0
             ">>\n"
5887
0
             "endobj\n");
5888
0
    } else {
5889
0
  cidfont_dict = _cairo_pdf_surface_new_object (surface);
5890
0
  if (cidfont_dict.id == 0)
5891
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5892
5893
0
  _cairo_output_stream_printf (surface->output,
5894
0
             "%d 0 obj\n"
5895
0
             "<< /Type /Font\n"
5896
0
             "   /Subtype /CIDFontType0\n"
5897
0
             "   /BaseFont /%s+%s\n"
5898
0
             "   /CIDSystemInfo\n"
5899
0
             "   << /Registry (Adobe)\n"
5900
0
             "      /Ordering (Identity)\n"
5901
0
             "      /Supplement 0\n"
5902
0
             "   >>\n"
5903
0
             "   /FontDescriptor %d 0 R\n"
5904
0
             "   /W [0 [",
5905
0
             cidfont_dict.id,
5906
0
             tag,
5907
0
             subset->ps_name,
5908
0
             descriptor.id);
5909
5910
0
  for (i = 0; i < font_subset->num_glyphs; i++)
5911
0
      _cairo_output_stream_printf (surface->output,
5912
0
           " %f",
5913
0
           (subset->widths[i]*PDF_UNITS_PER_EM));
5914
5915
0
  _cairo_output_stream_printf (surface->output,
5916
0
             " ]]\n"
5917
0
             ">>\n"
5918
0
             "endobj\n");
5919
5920
0
  _cairo_pdf_surface_update_object (surface, subset_resource);
5921
0
  _cairo_output_stream_printf (surface->output,
5922
0
             "%d 0 obj\n"
5923
0
             "<< /Type /Font\n"
5924
0
             "   /Subtype /Type0\n"
5925
0
             "   /BaseFont /%s+%s\n"
5926
0
             "   /Encoding /Identity-H\n"
5927
0
             "   /DescendantFonts [ %d 0 R]\n",
5928
0
             subset_resource.id,
5929
0
             tag,
5930
0
             subset->ps_name,
5931
0
             cidfont_dict.id);
5932
5933
0
  if (to_unicode_stream.id != 0)
5934
0
      _cairo_output_stream_printf (surface->output,
5935
0
           "   /ToUnicode %d 0 R\n",
5936
0
           to_unicode_stream.id);
5937
5938
0
  _cairo_output_stream_printf (surface->output,
5939
0
             ">>\n"
5940
0
             "endobj\n");
5941
0
    }
5942
5943
0
    font.font_id = font_subset->font_id;
5944
0
    font.subset_id = font_subset->subset_id;
5945
0
    font.subset_resource = subset_resource;
5946
0
    status = _cairo_array_append (&surface->fonts, &font);
5947
5948
0
    return status;
5949
0
}
5950
5951
static cairo_int_status_t
5952
_cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t       *surface,
5953
                                         cairo_scaled_font_subset_t  *font_subset)
5954
0
{
5955
0
    cairo_int_status_t status;
5956
0
    cairo_cff_subset_t subset;
5957
0
    char name[64];
5958
5959
0
    snprintf (name, sizeof name, "CairoFont-%d-%d",
5960
0
              font_subset->font_id, font_subset->subset_id);
5961
0
    status = _cairo_cff_subset_init (&subset, name, font_subset);
5962
0
    if (unlikely (status))
5963
0
        return status;
5964
5965
0
    status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
5966
5967
0
    _cairo_cff_subset_fini (&subset);
5968
5969
0
    return status;
5970
0
}
5971
5972
static cairo_int_status_t
5973
_cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t         *surface,
5974
                                           cairo_scaled_font_subset_t  *font_subset)
5975
0
{
5976
0
    cairo_int_status_t status;
5977
0
    cairo_cff_subset_t subset;
5978
0
    char name[64];
5979
5980
    /* CFF fallback subsetting does not work with 8-bit glyphs unless
5981
     * they are a latin subset */
5982
0
    if (!font_subset->is_composite && !font_subset->is_latin)
5983
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
5984
5985
0
    snprintf (name, sizeof name, "CairoFont-%d-%d",
5986
0
              font_subset->font_id, font_subset->subset_id);
5987
0
    status = _cairo_cff_fallback_init (&subset, name, font_subset);
5988
0
    if (unlikely (status))
5989
0
        return status;
5990
5991
0
    status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
5992
5993
0
    _cairo_cff_fallback_fini (&subset);
5994
5995
0
    return status;
5996
0
}
5997
5998
static cairo_int_status_t
5999
_cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t   *surface,
6000
                                    cairo_scaled_font_subset_t  *font_subset,
6001
                                    cairo_type1_subset_t        *subset)
6002
0
{
6003
0
    cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
6004
0
    cairo_pdf_font_t font;
6005
0
    cairo_int_status_t status;
6006
0
    unsigned long length;
6007
0
    unsigned int i, last_glyph;
6008
0
    char tag[10];
6009
6010
0
    _create_font_subset_tag (font_subset, subset->base_font, tag);
6011
6012
0
    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
6013
0
                  font_subset->font_id,
6014
0
                  font_subset->subset_id);
6015
0
    if (subset_resource.id == 0)
6016
0
  return CAIRO_STATUS_SUCCESS;
6017
6018
0
    length = subset->header_length + subset->data_length + subset->trailer_length;
6019
0
    status = _cairo_pdf_surface_open_stream (surface,
6020
0
               NULL,
6021
0
               TRUE,
6022
0
               "   /Length1 %lu\n"
6023
0
               "   /Length2 %lu\n"
6024
0
               "   /Length3 %lu\n",
6025
0
               subset->header_length,
6026
0
               subset->data_length,
6027
0
               subset->trailer_length);
6028
0
    if (unlikely (status))
6029
0
  return status;
6030
6031
0
    stream = surface->pdf_stream.self;
6032
0
    _cairo_output_stream_write (surface->output, subset->data, length);
6033
0
    status = _cairo_pdf_surface_close_stream (surface);
6034
0
    if (unlikely (status))
6035
0
  return status;
6036
6037
0
    status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
6038
0
                                                  font_subset,
6039
0
              &to_unicode_stream);
6040
0
    if (_cairo_int_status_is_error (status))
6041
0
  return status;
6042
6043
0
    last_glyph = font_subset->num_glyphs - 1;
6044
0
    if (font_subset->is_latin) {
6045
  /* find last glyph used */
6046
0
  for (i = 255; i >= 32; i--)
6047
0
      if (font_subset->latin_to_subset_glyph_index[i] > 0)
6048
0
    break;
6049
6050
0
  last_glyph = i;
6051
0
    }
6052
6053
0
    descriptor = _cairo_pdf_surface_new_object (surface);
6054
0
    if (descriptor.id == 0)
6055
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6056
6057
0
    _cairo_output_stream_printf (surface->output,
6058
0
         "%d 0 obj\n"
6059
0
         "<< /Type /FontDescriptor\n"
6060
0
         "   /FontName /%s+%s\n"
6061
0
         "   /Flags 4\n"
6062
0
         "   /FontBBox [ %ld %ld %ld %ld ]\n"
6063
0
         "   /ItalicAngle 0\n"
6064
0
         "   /Ascent %ld\n"
6065
0
         "   /Descent %ld\n"
6066
0
         "   /CapHeight %ld\n"
6067
0
         "   /StemV 80\n"
6068
0
         "   /StemH 80\n"
6069
0
         "   /FontFile %u 0 R\n"
6070
0
         ">>\n"
6071
0
         "endobj\n",
6072
0
         descriptor.id,
6073
0
         tag,
6074
0
         subset->base_font,
6075
0
         (long)(subset->x_min*PDF_UNITS_PER_EM),
6076
0
         (long)(subset->y_min*PDF_UNITS_PER_EM),
6077
0
         (long)(subset->x_max*PDF_UNITS_PER_EM),
6078
0
         (long)(subset->y_max*PDF_UNITS_PER_EM),
6079
0
         (long)(subset->ascent*PDF_UNITS_PER_EM),
6080
0
         (long)(subset->descent*PDF_UNITS_PER_EM),
6081
0
         (long)(subset->y_max*PDF_UNITS_PER_EM),
6082
0
         stream.id);
6083
6084
0
    _cairo_pdf_surface_update_object (surface, subset_resource);
6085
0
    _cairo_output_stream_printf (surface->output,
6086
0
         "%d 0 obj\n"
6087
0
         "<< /Type /Font\n"
6088
0
         "   /Subtype /Type1\n"
6089
0
         "   /BaseFont /%s+%s\n"
6090
0
         "   /FirstChar %d\n"
6091
0
         "   /LastChar %d\n"
6092
0
         "   /FontDescriptor %d 0 R\n",
6093
0
         subset_resource.id,
6094
0
         tag,
6095
0
         subset->base_font,
6096
0
         font_subset->is_latin ? 32 : 0,
6097
0
         last_glyph,
6098
0
         descriptor.id);
6099
6100
0
    if (font_subset->is_latin)
6101
0
  _cairo_output_stream_printf (surface->output, "   /Encoding /WinAnsiEncoding\n");
6102
6103
0
    _cairo_output_stream_printf (surface->output, "   /Widths [");
6104
0
    if (font_subset->is_latin) {
6105
0
  for (i = 32; i < last_glyph + 1; i++) {
6106
0
      int glyph = font_subset->latin_to_subset_glyph_index[i];
6107
0
      if (glyph > 0) {
6108
0
    _cairo_output_stream_printf (surface->output,
6109
0
               " %f",
6110
0
               (subset->widths[glyph]*PDF_UNITS_PER_EM));
6111
0
      } else {
6112
0
    _cairo_output_stream_printf (surface->output, " 0");
6113
0
      }
6114
0
  }
6115
0
    } else {
6116
0
  for (i = 0; i < font_subset->num_glyphs; i++)
6117
0
      _cairo_output_stream_printf (surface->output,
6118
0
           " %f",
6119
0
           (subset->widths[i]*PDF_UNITS_PER_EM));
6120
0
    }
6121
6122
0
    _cairo_output_stream_printf (surface->output,
6123
0
         " ]\n");
6124
6125
0
    if (to_unicode_stream.id != 0)
6126
0
        _cairo_output_stream_printf (surface->output,
6127
0
                                     "    /ToUnicode %d 0 R\n",
6128
0
                                     to_unicode_stream.id);
6129
6130
0
    _cairo_output_stream_printf (surface->output,
6131
0
         ">>\n"
6132
0
         "endobj\n");
6133
6134
0
    font.font_id = font_subset->font_id;
6135
0
    font.subset_id = font_subset->subset_id;
6136
0
    font.subset_resource = subset_resource;
6137
0
    return _cairo_array_append (&surface->fonts, &font);
6138
0
}
6139
6140
static cairo_int_status_t
6141
_cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t    *surface,
6142
             cairo_scaled_font_subset_t *font_subset)
6143
0
{
6144
0
    cairo_int_status_t status;
6145
0
    cairo_type1_subset_t subset;
6146
0
    char name[64];
6147
6148
    /* 16-bit glyphs not compatible with Type 1 fonts */
6149
0
    if (font_subset->is_composite && !font_subset->is_latin)
6150
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
6151
6152
0
    snprintf (name, sizeof name, "CairoFont-%d-%d",
6153
0
        font_subset->font_id, font_subset->subset_id);
6154
0
    status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE);
6155
0
    if (unlikely (status))
6156
0
  return status;
6157
6158
0
    status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
6159
6160
0
    _cairo_type1_subset_fini (&subset);
6161
0
    return status;
6162
0
}
6163
6164
static cairo_int_status_t
6165
_cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t  *surface,
6166
                                             cairo_scaled_font_subset_t *font_subset)
6167
0
{
6168
0
    cairo_int_status_t status;
6169
0
    cairo_type1_subset_t subset;
6170
0
    char name[64];
6171
6172
    /* 16-bit glyphs not compatible with Type 1 fonts */
6173
0
    if (font_subset->is_composite && !font_subset->is_latin)
6174
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
6175
6176
0
    snprintf (name, sizeof name, "CairoFont-%d-%d",
6177
0
        font_subset->font_id, font_subset->subset_id);
6178
0
    status = _cairo_type1_fallback_init_binary (&subset, name, font_subset);
6179
0
    if (unlikely (status))
6180
0
  return status;
6181
6182
0
    status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
6183
6184
0
    _cairo_type1_fallback_fini (&subset);
6185
0
    return status;
6186
0
}
6187
6188
static cairo_int_status_t
6189
_cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t   *surface,
6190
                cairo_scaled_font_subset_t  *font_subset)
6191
0
{
6192
0
    cairo_pdf_resource_t stream, descriptor, cidfont_dict;
6193
0
    cairo_pdf_resource_t subset_resource, to_unicode_stream;
6194
0
    cairo_int_status_t status;
6195
0
    cairo_pdf_font_t font;
6196
0
    cairo_truetype_subset_t subset;
6197
0
    unsigned int i, last_glyph;
6198
0
    char tag[10];
6199
6200
0
    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
6201
0
                  font_subset->font_id,
6202
0
                  font_subset->subset_id);
6203
0
    if (subset_resource.id == 0)
6204
0
  return CAIRO_STATUS_SUCCESS;
6205
6206
0
    status = _cairo_truetype_subset_init_pdf (&subset, font_subset);
6207
0
    if (unlikely (status))
6208
0
  return status;
6209
6210
0
    _create_font_subset_tag (font_subset, subset.ps_name, tag);
6211
6212
0
    status = _cairo_pdf_surface_open_stream (surface,
6213
0
               NULL,
6214
0
               TRUE,
6215
0
               "   /Length1 %lu\n",
6216
0
               subset.data_length);
6217
0
    if (unlikely (status)) {
6218
0
  _cairo_truetype_subset_fini (&subset);
6219
0
  return status;
6220
0
    }
6221
6222
0
    stream = surface->pdf_stream.self;
6223
0
    _cairo_output_stream_write (surface->output,
6224
0
        subset.data, subset.data_length);
6225
0
    status = _cairo_pdf_surface_close_stream (surface);
6226
0
    if (unlikely (status)) {
6227
0
  _cairo_truetype_subset_fini (&subset);
6228
0
  return status;
6229
0
    }
6230
6231
0
    status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
6232
0
                                                  font_subset,
6233
0
              &to_unicode_stream);
6234
0
    if (_cairo_int_status_is_error (status)) {
6235
0
  _cairo_truetype_subset_fini (&subset);
6236
0
  return status;
6237
0
    }
6238
6239
0
    descriptor = _cairo_pdf_surface_new_object (surface);
6240
0
    if (descriptor.id == 0) {
6241
0
  _cairo_truetype_subset_fini (&subset);
6242
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6243
0
    }
6244
6245
0
    _cairo_output_stream_printf (surface->output,
6246
0
         "%d 0 obj\n"
6247
0
         "<< /Type /FontDescriptor\n"
6248
0
         "   /FontName /%s+%s\n",
6249
0
         descriptor.id,
6250
0
         tag,
6251
0
         subset.ps_name);
6252
6253
0
    if (subset.family_name_utf8) {
6254
0
  char *pdf_str;
6255
6256
0
  status = _cairo_utf8_to_pdf_string (subset.family_name_utf8, &pdf_str);
6257
0
  if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
6258
0
      _cairo_output_stream_printf (surface->output,
6259
0
           "   /FontFamily %s\n",
6260
0
           pdf_str);
6261
0
      free (pdf_str);
6262
0
  } else if (status != CAIRO_INT_STATUS_INVALID_STRING) {
6263
0
      return status;
6264
0
  }
6265
0
    }
6266
6267
0
    _cairo_output_stream_printf (surface->output,
6268
0
         "   /Flags %d\n"
6269
0
         "   /FontBBox [ %ld %ld %ld %ld ]\n"
6270
0
         "   /ItalicAngle 0\n"
6271
0
         "   /Ascent %ld\n"
6272
0
         "   /Descent %ld\n"
6273
0
         "   /CapHeight %ld\n"
6274
0
         "   /StemV 80\n"
6275
0
         "   /StemH 80\n"
6276
0
         "   /FontFile2 %u 0 R\n"
6277
0
         ">>\n"
6278
0
         "endobj\n",
6279
0
         font_subset->is_latin ? 32 : 4,
6280
0
         (long)(subset.x_min*PDF_UNITS_PER_EM),
6281
0
         (long)(subset.y_min*PDF_UNITS_PER_EM),
6282
0
                                 (long)(subset.x_max*PDF_UNITS_PER_EM),
6283
0
         (long)(subset.y_max*PDF_UNITS_PER_EM),
6284
0
         (long)(subset.ascent*PDF_UNITS_PER_EM),
6285
0
         (long)(subset.descent*PDF_UNITS_PER_EM),
6286
0
         (long)(subset.y_max*PDF_UNITS_PER_EM),
6287
0
         stream.id);
6288
6289
0
    if (font_subset->is_latin) {
6290
  /* find last glyph used */
6291
0
  for (i = 255; i >= 32; i--)
6292
0
      if (font_subset->latin_to_subset_glyph_index[i] > 0)
6293
0
    break;
6294
6295
0
  last_glyph = i;
6296
0
  _cairo_pdf_surface_update_object (surface, subset_resource);
6297
0
  _cairo_output_stream_printf (surface->output,
6298
0
             "%d 0 obj\n"
6299
0
             "<< /Type /Font\n"
6300
0
             "   /Subtype /TrueType\n"
6301
0
             "   /BaseFont /%s+%s\n"
6302
0
             "   /FirstChar 32\n"
6303
0
             "   /LastChar %d\n"
6304
0
             "   /FontDescriptor %d 0 R\n"
6305
0
             "   /Encoding /WinAnsiEncoding\n"
6306
0
             "   /Widths [",
6307
0
             subset_resource.id,
6308
0
             tag,
6309
0
             subset.ps_name,
6310
0
             last_glyph,
6311
0
             descriptor.id);
6312
6313
0
  for (i = 32; i < last_glyph + 1; i++) {
6314
0
      int glyph = font_subset->latin_to_subset_glyph_index[i];
6315
0
      if (glyph > 0) {
6316
0
    _cairo_output_stream_printf (surface->output,
6317
0
               " %f",
6318
0
               (subset.widths[glyph]*PDF_UNITS_PER_EM));
6319
0
      } else {
6320
0
    _cairo_output_stream_printf (surface->output, " 0");
6321
0
      }
6322
0
  }
6323
6324
0
  _cairo_output_stream_printf (surface->output,
6325
0
             " ]\n");
6326
6327
0
  if (to_unicode_stream.id != 0)
6328
0
      _cairo_output_stream_printf (surface->output,
6329
0
           "    /ToUnicode %d 0 R\n",
6330
0
           to_unicode_stream.id);
6331
6332
0
  _cairo_output_stream_printf (surface->output,
6333
0
             ">>\n"
6334
0
             "endobj\n");
6335
0
    } else {
6336
0
  cidfont_dict = _cairo_pdf_surface_new_object (surface);
6337
0
  if (cidfont_dict.id == 0) {
6338
0
      _cairo_truetype_subset_fini (&subset);
6339
0
      return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6340
0
  }
6341
6342
0
  _cairo_output_stream_printf (surface->output,
6343
0
             "%d 0 obj\n"
6344
0
             "<< /Type /Font\n"
6345
0
             "   /Subtype /CIDFontType2\n"
6346
0
             "   /BaseFont /%s+%s\n"
6347
0
             "   /CIDSystemInfo\n"
6348
0
             "   << /Registry (Adobe)\n"
6349
0
             "      /Ordering (Identity)\n"
6350
0
             "      /Supplement 0\n"
6351
0
             "   >>\n"
6352
0
             "   /FontDescriptor %d 0 R\n"
6353
0
             "   /W [0 [",
6354
0
             cidfont_dict.id,
6355
0
             tag,
6356
0
             subset.ps_name,
6357
0
             descriptor.id);
6358
6359
0
  for (i = 0; i < font_subset->num_glyphs; i++)
6360
0
      _cairo_output_stream_printf (surface->output,
6361
0
           " %f",
6362
0
           (subset.widths[i]*PDF_UNITS_PER_EM));
6363
6364
0
  _cairo_output_stream_printf (surface->output,
6365
0
             " ]]\n"
6366
0
             ">>\n"
6367
0
             "endobj\n");
6368
6369
0
  _cairo_pdf_surface_update_object (surface, subset_resource);
6370
0
  _cairo_output_stream_printf (surface->output,
6371
0
             "%d 0 obj\n"
6372
0
             "<< /Type /Font\n"
6373
0
             "   /Subtype /Type0\n"
6374
0
             "   /BaseFont /%s+%s\n"
6375
0
             "   /Encoding /Identity-H\n"
6376
0
             "   /DescendantFonts [ %d 0 R]\n",
6377
0
             subset_resource.id,
6378
0
             tag,
6379
0
             subset.ps_name,
6380
0
             cidfont_dict.id);
6381
6382
0
  if (to_unicode_stream.id != 0)
6383
0
      _cairo_output_stream_printf (surface->output,
6384
0
           "   /ToUnicode %d 0 R\n",
6385
0
           to_unicode_stream.id);
6386
6387
0
  _cairo_output_stream_printf (surface->output,
6388
0
             ">>\n"
6389
0
             "endobj\n");
6390
0
    }
6391
6392
0
    font.font_id = font_subset->font_id;
6393
0
    font.subset_id = font_subset->subset_id;
6394
0
    font.subset_resource = subset_resource;
6395
0
    status = _cairo_array_append (&surface->fonts, &font);
6396
6397
0
    _cairo_truetype_subset_fini (&subset);
6398
6399
0
    return status;
6400
0
}
6401
6402
static cairo_int_status_t
6403
_cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
6404
           cairo_output_stream_t *stream)
6405
0
{
6406
0
    uint8_t *byte, output_byte;
6407
0
    int row, col, num_cols;
6408
6409
    /* The only image type supported by Type 3 fonts are 1-bit image
6410
     * masks */
6411
0
    assert (image->format == CAIRO_FORMAT_A1);
6412
6413
0
    _cairo_output_stream_printf (stream,
6414
0
         "BI\n"
6415
0
         "/IM true\n"
6416
0
         "/W %d\n"
6417
0
         "/H %d\n"
6418
0
         "/BPC 1\n"
6419
0
         "/D [1 0]\n",
6420
0
         image->width,
6421
0
         image->height);
6422
6423
0
    _cairo_output_stream_printf (stream,
6424
0
         "ID ");
6425
6426
0
    num_cols = (image->width + 7) / 8;
6427
0
    for (row = 0; row < image->height; row++) {
6428
0
  byte = image->data + row * image->stride;
6429
0
  for (col = 0; col < num_cols; col++) {
6430
0
      output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
6431
0
      _cairo_output_stream_write (stream, &output_byte, 1);
6432
0
      byte++;
6433
0
  }
6434
0
    }
6435
6436
0
    _cairo_output_stream_printf (stream,
6437
0
         "\nEI\n");
6438
6439
0
    return _cairo_output_stream_get_status (stream);
6440
0
}
6441
6442
static cairo_int_status_t
6443
_cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
6444
               void           *closure)
6445
0
{
6446
0
    cairo_pdf_surface_t *surface = closure;
6447
0
    cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
6448
0
    cairo_int_status_t status2;
6449
0
    unsigned int i;
6450
0
    cairo_surface_t *type3_surface;
6451
0
    cairo_output_stream_t *null_stream;
6452
6453
0
    null_stream = _cairo_null_stream_create ();
6454
0
    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
6455
0
                   null_stream,
6456
0
                   _cairo_pdf_emit_imagemask,
6457
0
                   surface->font_subsets,
6458
0
                   FALSE);
6459
0
    if (unlikely (type3_surface->status)) {
6460
0
  status2 = _cairo_output_stream_destroy (null_stream);
6461
0
  return type3_surface->status;
6462
0
    }
6463
6464
0
    _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
6465
0
                _cairo_pdf_surface_add_font,
6466
0
                surface);
6467
6468
0
    for (i = 0; i < font_subset->num_glyphs; i++) {
6469
0
  status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
6470
0
                 font_subset->glyphs[i]);
6471
0
  if (unlikely (status))
6472
0
      break;
6473
0
    }
6474
6475
0
    cairo_surface_destroy (type3_surface);
6476
0
    status2 = _cairo_output_stream_destroy (null_stream);
6477
0
    if (status == CAIRO_INT_STATUS_SUCCESS)
6478
0
  status = status2;
6479
6480
0
    return status;
6481
0
}
6482
6483
static cairo_int_status_t
6484
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t    *surface,
6485
             cairo_scaled_font_subset_t *font_subset)
6486
0
{
6487
0
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
6488
0
    cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
6489
0
    cairo_pdf_font_t font;
6490
0
    double *widths;
6491
0
    unsigned int i;
6492
0
    cairo_box_t font_bbox = {{0,0},{0,0}};
6493
0
    cairo_box_t bbox = {{0,0},{0,0}};
6494
0
    cairo_surface_t *type3_surface;
6495
6496
0
    if (font_subset->num_glyphs == 0)
6497
0
  return CAIRO_STATUS_SUCCESS;
6498
6499
0
    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
6500
0
                  font_subset->font_id,
6501
0
                  font_subset->subset_id);
6502
0
    if (subset_resource.id == 0)
6503
0
  return CAIRO_STATUS_SUCCESS;
6504
6505
0
    glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
6506
0
    if (unlikely (glyphs == NULL))
6507
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6508
6509
0
    widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
6510
0
    if (unlikely (widths == NULL)) {
6511
0
        free (glyphs);
6512
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6513
0
    }
6514
6515
0
    _cairo_pdf_group_resources_clear (&surface->resources);
6516
0
    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
6517
0
                   NULL,
6518
0
                   _cairo_pdf_emit_imagemask,
6519
0
                   surface->font_subsets,
6520
0
                   FALSE);
6521
0
    if (unlikely (type3_surface->status)) {
6522
0
        free (glyphs);
6523
0
        free (widths);
6524
0
  return type3_surface->status;
6525
0
    }
6526
6527
0
    _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
6528
0
                _cairo_pdf_surface_add_font,
6529
0
                surface);
6530
6531
0
    for (i = 0; i < font_subset->num_glyphs; i++) {
6532
0
  status = _cairo_pdf_surface_open_stream (surface,
6533
0
             NULL,
6534
0
             surface->compress_streams,
6535
0
             NULL);
6536
0
  if (unlikely (status))
6537
0
      break;
6538
6539
0
  glyphs[i] = surface->pdf_stream.self;
6540
0
  status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
6541
0
              surface->output,
6542
0
              font_subset->glyphs[i],
6543
0
              &bbox,
6544
0
              &widths[i]);
6545
0
  if (unlikely (status))
6546
0
      break;
6547
6548
0
  status = _cairo_pdf_surface_close_stream (surface);
6549
0
  if (unlikely (status))
6550
0
      break;
6551
6552
0
        if (i == 0) {
6553
0
            font_bbox.p1.x = bbox.p1.x;
6554
0
            font_bbox.p1.y = bbox.p1.y;
6555
0
            font_bbox.p2.x = bbox.p2.x;
6556
0
            font_bbox.p2.y = bbox.p2.y;
6557
0
        } else {
6558
0
            if (bbox.p1.x < font_bbox.p1.x)
6559
0
                font_bbox.p1.x = bbox.p1.x;
6560
0
            if (bbox.p1.y < font_bbox.p1.y)
6561
0
                font_bbox.p1.y = bbox.p1.y;
6562
0
            if (bbox.p2.x > font_bbox.p2.x)
6563
0
                font_bbox.p2.x = bbox.p2.x;
6564
0
            if (bbox.p2.y > font_bbox.p2.y)
6565
0
                font_bbox.p2.y = bbox.p2.y;
6566
0
        }
6567
0
    }
6568
0
    cairo_surface_destroy (type3_surface);
6569
0
    if (unlikely (status)) {
6570
0
  free (glyphs);
6571
0
  free (widths);
6572
0
  return status;
6573
0
    }
6574
6575
0
    encoding = _cairo_pdf_surface_new_object (surface);
6576
0
    if (encoding.id == 0) {
6577
0
  free (glyphs);
6578
0
  free (widths);
6579
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6580
0
    }
6581
6582
0
    _cairo_output_stream_printf (surface->output,
6583
0
         "%d 0 obj\n"
6584
0
         "<< /Type /Encoding\n"
6585
0
         "   /Differences [0", encoding.id);
6586
0
    for (i = 0; i < font_subset->num_glyphs; i++)
6587
0
  _cairo_output_stream_printf (surface->output,
6588
0
             " /%d", i);
6589
0
    _cairo_output_stream_printf (surface->output,
6590
0
         "]\n"
6591
0
         ">>\n"
6592
0
         "endobj\n");
6593
6594
0
    char_procs = _cairo_pdf_surface_new_object (surface);
6595
0
    if (char_procs.id == 0) {
6596
0
  free (glyphs);
6597
0
  free (widths);
6598
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6599
0
    }
6600
6601
0
    _cairo_output_stream_printf (surface->output,
6602
0
         "%d 0 obj\n"
6603
0
         "<<\n", char_procs.id);
6604
0
    for (i = 0; i < font_subset->num_glyphs; i++)
6605
0
  _cairo_output_stream_printf (surface->output,
6606
0
             " /%d %d 0 R\n",
6607
0
             i, glyphs[i].id);
6608
0
    _cairo_output_stream_printf (surface->output,
6609
0
         ">>\n"
6610
0
         "endobj\n");
6611
6612
0
    free (glyphs);
6613
6614
0
    status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
6615
0
                                                  font_subset,
6616
0
              &to_unicode_stream);
6617
0
    if (_cairo_int_status_is_error (status)) {
6618
0
  free (widths);
6619
0
  return status;
6620
0
    }
6621
6622
0
    _cairo_pdf_surface_update_object (surface, subset_resource);
6623
0
    _cairo_output_stream_printf (surface->output,
6624
0
         "%d 0 obj\n"
6625
0
         "<< /Type /Font\n"
6626
0
         "   /Subtype /Type3\n"
6627
0
         "   /FontBBox [%f %f %f %f]\n"
6628
0
         "   /FontMatrix [ 1 0 0 -1 0 0 ]\n"
6629
0
         "   /Encoding %d 0 R\n"
6630
0
         "   /CharProcs %d 0 R\n"
6631
0
         "   /FirstChar 0\n"
6632
0
         "   /LastChar %d\n",
6633
0
         subset_resource.id,
6634
0
         _cairo_fixed_to_double (font_bbox.p1.x),
6635
0
         _cairo_fixed_to_double (font_bbox.p1.y),
6636
0
         _cairo_fixed_to_double (font_bbox.p2.x),
6637
0
         _cairo_fixed_to_double (font_bbox.p2.y),
6638
0
         encoding.id,
6639
0
         char_procs.id,
6640
0
         font_subset->num_glyphs - 1);
6641
6642
0
    _cairo_output_stream_printf (surface->output,
6643
0
         "   /Widths [");
6644
0
    for (i = 0; i < font_subset->num_glyphs; i++)
6645
0
  _cairo_output_stream_printf (surface->output, " %f", widths[i]);
6646
0
    _cairo_output_stream_printf (surface->output,
6647
0
         "]\n");
6648
0
    free (widths);
6649
6650
0
    _cairo_output_stream_printf (surface->output,
6651
0
         "   /Resources\n");
6652
0
    _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
6653
6654
0
    if (to_unicode_stream.id != 0)
6655
0
        _cairo_output_stream_printf (surface->output,
6656
0
                                     "    /ToUnicode %d 0 R\n",
6657
0
                                     to_unicode_stream.id);
6658
6659
0
    _cairo_output_stream_printf (surface->output,
6660
0
         ">>\n"
6661
0
         "endobj\n");
6662
6663
0
    font.font_id = font_subset->font_id;
6664
0
    font.subset_id = font_subset->subset_id;
6665
0
    font.subset_resource = subset_resource;
6666
0
    return _cairo_array_append (&surface->fonts, &font);
6667
0
}
6668
6669
static cairo_int_status_t
6670
_cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
6671
                                              void       *closure)
6672
0
{
6673
0
    cairo_pdf_surface_t *surface = closure;
6674
0
    cairo_int_status_t status;
6675
6676
0
    status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
6677
0
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
6678
0
  return status;
6679
6680
0
    status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
6681
0
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
6682
0
  return status;
6683
6684
0
    status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
6685
0
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
6686
0
  return status;
6687
6688
0
    status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
6689
0
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
6690
0
  return status;
6691
6692
0
    status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
6693
0
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
6694
0
  return status;
6695
6696
0
    ASSERT_NOT_REACHED;
6697
0
    return CAIRO_INT_STATUS_SUCCESS;
6698
0
}
6699
6700
static cairo_int_status_t
6701
_cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
6702
                                            void           *closure)
6703
0
{
6704
0
    cairo_pdf_surface_t *surface = closure;
6705
0
    cairo_int_status_t status;
6706
6707
0
    status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
6708
0
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
6709
0
  return status;
6710
6711
0
    ASSERT_NOT_REACHED;
6712
0
    return CAIRO_INT_STATUS_SUCCESS;
6713
0
}
6714
6715
static cairo_int_status_t
6716
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
6717
2
{
6718
2
    cairo_int_status_t status;
6719
6720
2
    status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
6721
2
                  _cairo_pdf_surface_analyze_user_font_subset,
6722
2
                  surface);
6723
2
    if (unlikely (status))
6724
0
  goto BAIL;
6725
6726
2
    status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
6727
2
                                                          _cairo_pdf_surface_emit_unscaled_font_subset,
6728
2
                                                          surface);
6729
2
    if (unlikely (status))
6730
0
  goto BAIL;
6731
6732
2
    status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
6733
2
                                                        _cairo_pdf_surface_emit_scaled_font_subset,
6734
2
                                                        surface);
6735
2
    if (unlikely (status))
6736
0
  goto BAIL;
6737
6738
2
    status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
6739
2
                  _cairo_pdf_surface_emit_scaled_font_subset,
6740
2
                  surface);
6741
6742
2
BAIL:
6743
2
    _cairo_scaled_font_subsets_destroy (surface->font_subsets);
6744
2
    surface->font_subsets = NULL;
6745
6746
2
    return status;
6747
2
}
6748
6749
static cairo_int_status_t
6750
_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface,
6751
          cairo_pdf_resource_t catalog)
6752
2
{
6753
2
    cairo_status_t status;
6754
6755
2
    status = _cairo_pdf_surface_object_begin (surface, catalog);
6756
2
    if (unlikely (status))
6757
0
  return status;
6758
6759
2
    _cairo_output_stream_printf (surface->object_stream.stream,
6760
2
         "<< /Type /Catalog\n"
6761
2
         "   /Pages %d 0 R\n",
6762
2
         surface->pages_resource.id);
6763
6764
2
    if (surface->struct_tree_root.id != 0) {
6765
0
  _cairo_output_stream_printf (surface->object_stream.stream,
6766
0
             "   /StructTreeRoot %d 0 R\n",
6767
0
             surface->struct_tree_root.id);
6768
0
  if (surface->tagged) {
6769
0
      _cairo_output_stream_printf (surface->object_stream.stream,
6770
0
           "   /MarkInfo << /Marked true >>\n");
6771
0
  }
6772
0
    }
6773
6774
2
    if (surface->outlines_dict_res.id != 0) {
6775
0
  _cairo_output_stream_printf (surface->object_stream.stream,
6776
0
             "   /Outlines %d 0 R\n",
6777
0
             surface->outlines_dict_res.id);
6778
0
    }
6779
6780
2
    if (surface->page_labels_res.id != 0) {
6781
0
  _cairo_output_stream_printf (surface->object_stream.stream,
6782
0
             "   /PageLabels %d 0 R\n",
6783
0
             surface->page_labels_res.id);
6784
0
    }
6785
6786
2
    if (surface->names_dict_res.id != 0) {
6787
0
  _cairo_output_stream_printf (surface->object_stream.stream,
6788
0
             "   /Names %d 0 R\n",
6789
0
             surface->names_dict_res.id);
6790
0
    }
6791
6792
2
    _cairo_output_stream_printf (surface->object_stream.stream,
6793
2
         ">>\n");
6794
2
    _cairo_pdf_surface_object_end (surface);
6795
6796
2
    return status;
6797
2
}
6798
6799
static long long
6800
_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
6801
0
{
6802
0
    cairo_pdf_object_t *object;
6803
0
    int num_objects, i;
6804
0
    long long offset;
6805
0
    char buffer[11];
6806
6807
0
    num_objects = _cairo_array_num_elements (&surface->objects);
6808
6809
0
    offset = _cairo_output_stream_get_position (surface->output);
6810
0
    _cairo_output_stream_printf (surface->output,
6811
0
         "xref\n"
6812
0
         "%d %d\n",
6813
0
         0, num_objects + 1);
6814
6815
0
    _cairo_output_stream_printf (surface->output,
6816
0
         "0000000000 65535 f \n");
6817
0
    for (i = 0; i < num_objects; i++) {
6818
0
  object = _cairo_array_index (&surface->objects, i);
6819
0
  snprintf (buffer, sizeof buffer, "%010lld", object->u.offset);
6820
0
  _cairo_output_stream_printf (surface->output,
6821
0
             "%s 00000 n \n", buffer);
6822
0
    }
6823
6824
0
    return offset;
6825
0
}
6826
6827
static void
6828
_cairo_write_xref_stream_entry (cairo_output_stream_t *stream,
6829
        int                    id,
6830
        int                    type,
6831
        int                    field2_size,
6832
        long long              field2,
6833
        int                    field3,
6834
        cairo_bool_t           write_as_comments)
6835
26
{
6836
26
    char buf[20];
6837
26
    int i;
6838
6839
26
    if (write_as_comments) {
6840
0
  _cairo_output_stream_printf (stream, "%% %5d %2d %10lld  %d\n", id, type, field2, field3);
6841
26
    } else {
6842
  /* Each field is big endian */
6843
26
  buf[0] = type; /* field 1 */
6844
78
  for (i = field2_size - 1; i >= 0; i--) {
6845
52
      buf[i + 1] = field2 & 0xff;
6846
52
      field2 >>= 8;
6847
52
  }
6848
26
  buf[field2_size + 1] = field3 >> 8;
6849
26
  buf[field2_size + 2] = field3 & 0xff;
6850
26
  _cairo_output_stream_write (stream, buf, field2_size + 3);
6851
26
    }
6852
26
}
6853
6854
static void
6855
_cairo_write_xref_stream_entries (cairo_pdf_surface_t   *surface,
6856
          cairo_output_stream_t *stream,
6857
          int                    field2_size,
6858
          cairo_bool_t           write_as_comments)
6859
2
{
6860
2
    cairo_pdf_object_t *object;
6861
2
    int num_objects, i;
6862
6863
    /* PDF requires this to be first entry */
6864
2
    _cairo_write_xref_stream_entry (stream,
6865
2
            0,
6866
2
            PDF_OBJECT_FREE,
6867
2
            field2_size,
6868
2
            0, /* next free object number */
6869
2
            0xffff, /* next generation number */
6870
2
            write_as_comments);
6871
6872
2
    num_objects = _cairo_array_num_elements (&surface->objects);
6873
26
    for (i = 0; i < num_objects; i++) {
6874
24
  object = _cairo_array_index (&surface->objects, i);
6875
24
  if (object->type == PDF_OBJECT_UNCOMPRESSED) {
6876
16
      _cairo_write_xref_stream_entry (stream,
6877
16
              i + 1,
6878
16
              object->type,
6879
16
              field2_size,
6880
16
              object->u.offset,
6881
16
              0, /* generation number */
6882
16
              write_as_comments);
6883
16
  } else if (object->type == PDF_OBJECT_COMPRESSED) {
6884
8
      _cairo_write_xref_stream_entry (stream,
6885
8
              i + 1,
6886
8
              object->type,
6887
8
              field2_size,
6888
8
              object->u.compressed_obj.xref_stream.id,
6889
8
              object->u.compressed_obj.index,
6890
8
              write_as_comments);
6891
8
  } else {
6892
0
      _cairo_write_xref_stream_entry (stream,
6893
0
              i + 1,
6894
0
              PDF_OBJECT_FREE,
6895
0
              field2_size,
6896
0
              0,
6897
0
              0xffff,
6898
0
              write_as_comments);
6899
0
  }
6900
24
    }
6901
2
}
6902
6903
static cairo_int_status_t
6904
_cairo_pdf_surface_write_xref_stream (cairo_pdf_surface_t  *surface,
6905
              cairo_pdf_resource_t  xref_res,
6906
              cairo_pdf_resource_t  root_res,
6907
              cairo_pdf_resource_t  info_res,
6908
              long long            *xref_offset)
6909
2
{
6910
2
    cairo_output_stream_t *mem_stream;
6911
2
    cairo_output_stream_t *xref_stream;
6912
2
    long long offset;
6913
2
    int offset_bytes;
6914
2
    cairo_status_t status;
6915
6916
2
    *xref_offset = _cairo_output_stream_get_position (surface->output);
6917
6918
    /* Find the minimum number of bytes required to represent offsets in the generated file (up to this point). */
6919
2
    offset_bytes = 0;
6920
2
    offset = *xref_offset;
6921
6
    while (offset > 0) {
6922
4
  offset >>= 8;
6923
4
  offset_bytes++;
6924
4
    }
6925
6926
2
    mem_stream = _cairo_memory_stream_create ();
6927
2
    xref_stream = _cairo_deflate_stream_create (mem_stream);
6928
2
    _cairo_write_xref_stream_entries (surface, xref_stream, offset_bytes, FALSE);
6929
6930
2
    status = _cairo_output_stream_destroy (xref_stream);
6931
2
    if (unlikely (status))
6932
0
  return status;
6933
6934
2
    _cairo_pdf_surface_update_object (surface, xref_res);
6935
2
    _cairo_output_stream_printf (surface->output,
6936
2
         "%d 0 obj\n"
6937
2
         "<< /Type /XRef\n"
6938
2
         "   /Length %d\n"
6939
2
         "   /Filter /FlateDecode\n"
6940
2
         "   /Size %d\n"
6941
2
         "   /W [1 %d 2]\n"
6942
2
         "   /Root %d 0 R\n"
6943
2
         "   /Info %d 0 R\n"
6944
2
         ">>\n",
6945
2
         xref_res.id,
6946
2
         _cairo_memory_stream_length (mem_stream),
6947
2
         surface->next_available_resource.id,
6948
2
         offset_bytes,
6949
2
         root_res.id,
6950
2
         info_res.id);
6951
6952
2
    if (!surface->compress_streams) {
6953
  /* Adobe Reader requires xref streams to be flate encoded (PDF
6954
   * Reference 1.7, implementation note 20). This means
6955
   * compression must always be enabled on this stream. To
6956
   * facilitate debugging when compress_stream is disabled, emit
6957
   * a human readable format of the xref stream as PDF comments.
6958
   */
6959
0
  _cairo_output_stream_printf (surface->output,
6960
0
             "%%   id   type  offset/obj  gen/index\n");
6961
0
  _cairo_write_xref_stream_entries (surface, surface->output, offset_bytes, TRUE);
6962
0
    }
6963
6964
2
    _cairo_output_stream_printf (surface->output,
6965
2
         "stream\n");
6966
2
    _cairo_memory_stream_copy (mem_stream, surface->output);
6967
2
    status = _cairo_output_stream_destroy (mem_stream);
6968
2
    if (unlikely (status))
6969
0
  return status;
6970
6971
2
    _cairo_output_stream_printf (surface->output,
6972
2
         "\n"
6973
2
         "endstream\n"
6974
2
         "endobj\n");
6975
6976
2
    return _cairo_output_stream_get_status (surface->output);
6977
2
}
6978
6979
static cairo_int_status_t
6980
_cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t  *surface,
6981
             cairo_pdf_smask_group_t  *group)
6982
0
{
6983
0
    cairo_pdf_resource_t mask_group;
6984
0
    cairo_pdf_resource_t smask;
6985
0
    cairo_pdf_smask_group_t *smask_group;
6986
0
    cairo_pdf_resource_t pattern_res, gstate_res;
6987
0
    cairo_int_status_t status;
6988
0
    cairo_box_double_t bbox;
6989
6990
    /* Create mask group */
6991
0
    _get_bbox_from_extents (&group->extents, &bbox);
6992
0
    status = _cairo_pdf_surface_open_group (surface, &bbox, NULL);
6993
0
    if (unlikely (status))
6994
0
  return status;
6995
6996
0
    if (_can_paint_pattern (group->mask)) {
6997
0
  _cairo_output_stream_printf (surface->output, "q\n");
6998
0
  status = _cairo_pdf_surface_paint_pattern (surface,
6999
0
               CAIRO_OPERATOR_OVER,
7000
0
               group->mask,
7001
0
               &group->extents,
7002
0
               1.0, /* alpha */
7003
0
               FALSE); /* mask */
7004
0
  if (unlikely (status))
7005
0
      return status;
7006
7007
0
  _cairo_output_stream_printf (surface->output, "Q\n");
7008
0
    } else {
7009
0
  pattern_res.id = 0;
7010
0
  gstate_res.id = 0;
7011
0
  status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask,
7012
0
                 CAIRO_OPERATOR_OVER,
7013
0
                 NULL,
7014
0
                 &pattern_res, &gstate_res);
7015
0
  if (unlikely (status))
7016
0
      return status;
7017
7018
0
  if (gstate_res.id != 0) {
7019
0
      smask_group = _cairo_pdf_surface_create_smask_group (surface, &group->extents);
7020
0
      if (unlikely (smask_group == NULL))
7021
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
7022
7023
0
      smask_group->width = group->width;
7024
0
      smask_group->height = group->height;
7025
0
      smask_group->operation = PDF_PAINT;
7026
0
      smask_group->source = cairo_pattern_reference (group->mask);
7027
0
      smask_group->source_res = pattern_res;
7028
0
      status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
7029
0
      if (unlikely (status)) {
7030
0
    _cairo_pdf_smask_group_destroy (smask_group);
7031
0
    return status;
7032
0
      }
7033
7034
0
      status = _cairo_pdf_surface_add_smask (surface, gstate_res);
7035
0
      if (unlikely (status))
7036
0
    return status;
7037
7038
0
      status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
7039
0
      if (unlikely (status))
7040
0
    return status;
7041
7042
0
      _cairo_output_stream_printf (surface->output,
7043
0
           "q /s%d gs /x%d Do Q\n",
7044
0
           gstate_res.id,
7045
0
           smask_group->group_res.id);
7046
0
  } else {
7047
0
      status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE);
7048
0
      if (unlikely (status))
7049
0
    return status;
7050
7051
0
      _cairo_output_stream_printf (surface->output,
7052
0
           "%f %f %f %f re f\n",
7053
0
           bbox.p1.x,
7054
0
           bbox.p1.y,
7055
0
           bbox.p2.x - bbox.p1.x,
7056
0
           bbox.p2.y - bbox.p1.y);
7057
7058
0
      status = _cairo_pdf_surface_unselect_pattern (surface);
7059
0
      if (unlikely (status))
7060
0
    return status;
7061
0
  }
7062
0
    }
7063
7064
0
    status = _cairo_pdf_surface_close_group (surface, &mask_group);
7065
0
    if (unlikely (status))
7066
0
  return status;
7067
7068
    /* Create source group */
7069
0
    status = _cairo_pdf_surface_open_group (surface, &bbox, &group->source_res);
7070
0
    if (unlikely (status))
7071
0
  return status;
7072
7073
0
    if (_can_paint_pattern (group->source)) {
7074
0
  _cairo_output_stream_printf (surface->output, "q\n");
7075
0
  status = _cairo_pdf_surface_paint_pattern (surface,
7076
0
               CAIRO_OPERATOR_OVER,
7077
0
               group->source,
7078
0
               &group->extents,
7079
0
               1.0, /* alpha */
7080
0
               FALSE); /* mask */
7081
0
  if (unlikely (status))
7082
0
      return status;
7083
7084
0
  _cairo_output_stream_printf (surface->output, "Q\n");
7085
0
    } else {
7086
0
  pattern_res.id = 0;
7087
0
  gstate_res.id = 0;
7088
0
  status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source,
7089
0
                 CAIRO_OPERATOR_OVER,
7090
0
                 NULL,
7091
0
                 &pattern_res, &gstate_res);
7092
0
  if (unlikely (status))
7093
0
      return status;
7094
7095
0
  if (gstate_res.id != 0) {
7096
0
      smask_group = _cairo_pdf_surface_create_smask_group (surface, &group->extents);
7097
0
      if (unlikely (smask_group == NULL))
7098
0
    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
7099
7100
0
      smask_group->operation = PDF_PAINT;
7101
0
      smask_group->source = cairo_pattern_reference (group->source);
7102
0
      smask_group->source_res = pattern_res;
7103
0
      status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
7104
0
      if (unlikely (status)) {
7105
0
    _cairo_pdf_smask_group_destroy (smask_group);
7106
0
    return status;
7107
0
      }
7108
7109
0
      status = _cairo_pdf_surface_add_smask (surface, gstate_res);
7110
0
      if (unlikely (status))
7111
0
    return status;
7112
7113
0
      status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
7114
0
      if (unlikely (status))
7115
0
    return status;
7116
7117
0
      _cairo_output_stream_printf (surface->output,
7118
0
           "q /s%d gs /x%d Do Q\n",
7119
0
           gstate_res.id,
7120
0
           smask_group->group_res.id);
7121
0
  } else {
7122
0
      status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE);
7123
0
      if (unlikely (status))
7124
0
    return status;
7125
7126
0
      _cairo_output_stream_printf (surface->output,
7127
0
           "%f %f %f %f re f\n",
7128
0
           bbox.p1.x,
7129
0
           bbox.p1.y,
7130
0
           bbox.p2.x - bbox.p1.x,
7131
0
           bbox.p2.y - bbox.p1.y);
7132
7133
0
      status = _cairo_pdf_surface_unselect_pattern (surface);
7134
0
      if (unlikely (status))
7135
0
    return status;
7136
0
  }
7137
0
    }
7138
7139
0
    status = _cairo_pdf_surface_close_group (surface, NULL);
7140
0
    if (unlikely (status))
7141
0
  return status;
7142
7143
    /* Create an smask based on the alpha component of mask_group */
7144
0
    smask = _cairo_pdf_surface_new_object (surface);
7145
0
    if (smask.id == 0)
7146
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
7147
7148
0
    _cairo_output_stream_printf (surface->output,
7149
0
         "%d 0 obj\n"
7150
0
         "<< /Type /Mask\n"
7151
0
         "   /S /Alpha\n"
7152
0
         "   /G %d 0 R\n"
7153
0
         ">>\n"
7154
0
         "endobj\n",
7155
0
         smask.id,
7156
0
         mask_group.id);
7157
7158
    /* Create a GState that uses the smask */
7159
0
    _cairo_pdf_surface_update_object (surface, group->group_res);
7160
0
    _cairo_output_stream_printf (surface->output,
7161
0
         "%d 0 obj\n"
7162
0
         "<< /Type /ExtGState\n"
7163
0
         "   /SMask %d 0 R\n"
7164
0
         "   /ca 1\n"
7165
0
         "   /CA 1\n"
7166
0
         "   /AIS false\n"
7167
0
         ">>\n"
7168
0
         "endobj\n",
7169
0
         group->group_res.id,
7170
0
         smask.id);
7171
7172
0
    return _cairo_output_stream_get_status (surface->output);
7173
0
}
7174
7175
static cairo_int_status_t
7176
_cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t     *surface,
7177
              cairo_pdf_smask_group_t *group)
7178
0
{
7179
0
    double old_width, old_height;
7180
0
    cairo_bool_t old_in_xobject;
7181
0
    cairo_int_status_t status;
7182
0
    cairo_box_double_t bbox;
7183
0
    cairo_rectangle_int_t old_surface_extents;
7184
7185
0
    old_width = surface->width;
7186
0
    old_height = surface->height;
7187
0
    old_surface_extents = surface->surface_extents;
7188
0
    old_in_xobject = surface->in_xobject;
7189
0
    surface->in_xobject = TRUE;
7190
0
    _cairo_pdf_surface_set_size_internal (surface,
7191
0
            group->width,
7192
0
            group->height);
7193
0
    _cairo_pdf_operators_reset (&surface->pdf_operators);
7194
    /* _mask is a special case that requires two groups - source
7195
     * and mask as well as a smask and gstate dictionary */
7196
0
    if (group->operation == PDF_MASK) {
7197
0
  status = _cairo_pdf_surface_write_mask_group (surface, group);
7198
0
  goto RESTORE_SIZE;
7199
0
    }
7200
7201
0
    _get_bbox_from_extents (&group->extents, &bbox);
7202
0
    status = _cairo_pdf_surface_open_group (surface, &bbox, &group->group_res);
7203
0
    if (unlikely (status))
7204
0
  return status;
7205
7206
0
    status = _cairo_pdf_surface_select_pattern (surface,
7207
0
            group->source,
7208
0
            group->source_res,
7209
0
            group->operation == PDF_STROKE);
7210
0
    if (unlikely (status))
7211
0
  return status;
7212
7213
0
    switch (group->operation) {
7214
0
    case PDF_PAINT:
7215
0
  _cairo_output_stream_printf (surface->output,
7216
0
             "0 0 %f %f re f\n",
7217
0
             surface->width, surface->height);
7218
0
  break;
7219
0
    case PDF_MASK:
7220
0
  ASSERT_NOT_REACHED;
7221
0
  break;
7222
0
    case PDF_FILL:
7223
0
  status = _cairo_pdf_operators_fill (&surface->pdf_operators,
7224
0
              &group->path,
7225
0
              group->fill_rule);
7226
0
  break;
7227
0
    case PDF_STROKE:
7228
0
  status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
7229
0
                &group->path,
7230
0
                &group->style,
7231
0
                &group->ctm,
7232
0
                &group->ctm_inverse);
7233
0
  break;
7234
0
    case PDF_SHOW_GLYPHS:
7235
0
  status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
7236
0
              group->utf8, group->utf8_len,
7237
0
              group->glyphs, group->num_glyphs,
7238
0
              group->clusters, group->num_clusters,
7239
0
              group->cluster_flags,
7240
0
              group->scaled_font);
7241
0
  break;
7242
0
    }
7243
0
    if (unlikely (status))
7244
0
  return status;
7245
7246
0
    status = _cairo_pdf_surface_unselect_pattern (surface);
7247
0
    if (unlikely (status))
7248
0
  return status;
7249
7250
0
    status = _cairo_pdf_surface_close_group (surface, NULL);
7251
7252
0
RESTORE_SIZE:
7253
0
    surface->in_xobject = old_in_xobject;
7254
0
    _cairo_pdf_surface_set_size_internal (surface,
7255
0
            old_width,
7256
0
            old_height);
7257
0
    surface->surface_extents = old_surface_extents;
7258
0
    _cairo_pdf_operators_reset (&surface->pdf_operators);
7259
7260
0
    return status;
7261
0
}
7262
7263
static cairo_int_status_t
7264
_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface,
7265
                cairo_bool_t         finish)
7266
4
{
7267
4
    cairo_pdf_pattern_t pattern;
7268
4
    cairo_pdf_smask_group_t *group;
7269
4
    cairo_pdf_source_surface_t src_surface;
7270
4
    unsigned int pattern_index, group_index, surface_index, doc_surface_index;
7271
4
    cairo_int_status_t status;
7272
4
    cairo_bool_t is_image;
7273
7274
    /* Writing out PDF_MASK groups will cause additional smask groups
7275
     * to be appended to surface->smask_groups. Additional patterns
7276
     * may also be appended to surface->patterns.
7277
     *
7278
     * Writing recording surface patterns will cause additional patterns
7279
     * and groups to be appended.
7280
     */
7281
4
    pattern_index = 0;
7282
4
    group_index = 0;
7283
4
    surface_index = 0;
7284
4
    doc_surface_index = 0;
7285
4
    while ((pattern_index < _cairo_array_num_elements (&surface->page_patterns)) ||
7286
4
     (group_index < _cairo_array_num_elements (&surface->smask_groups)) ||
7287
4
     (surface_index < _cairo_array_num_elements (&surface->page_surfaces)) ||
7288
4
     (finish && (doc_surface_index < _cairo_array_num_elements (&surface->doc_surfaces))))
7289
0
    {
7290
0
  for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) {
7291
0
      _cairo_array_copy_element (&surface->smask_groups, group_index, &group);
7292
0
      status = _cairo_pdf_surface_write_smask_group (surface, group);
7293
0
      if (unlikely (status))
7294
0
    return status;
7295
0
  }
7296
7297
0
  for (; pattern_index < _cairo_array_num_elements (&surface->page_patterns); pattern_index++) {
7298
0
      _cairo_array_copy_element (&surface->page_patterns, pattern_index, &pattern);
7299
0
      status = _cairo_pdf_surface_emit_pattern (surface, &pattern);
7300
0
      if (unlikely (status))
7301
0
    return status;
7302
0
  }
7303
7304
0
  for (; surface_index < _cairo_array_num_elements (&surface->page_surfaces); surface_index++) {
7305
0
      _cairo_array_copy_element (&surface->page_surfaces, surface_index, &src_surface);
7306
0
      status = _cairo_pdf_surface_emit_surface (surface, &src_surface, FALSE, &is_image);
7307
0
      if (unlikely (status))
7308
0
    return status;
7309
0
  }
7310
7311
0
  if (finish) {
7312
0
      for (; doc_surface_index < _cairo_array_num_elements (&surface->doc_surfaces); doc_surface_index++) {
7313
0
    _cairo_array_copy_element (&surface->doc_surfaces, doc_surface_index, &src_surface);
7314
0
    status = _cairo_pdf_surface_emit_surface (surface, &src_surface, FALSE, &is_image);
7315
0
    if (unlikely (status))
7316
0
        return status;
7317
0
      }
7318
0
  }
7319
0
    }
7320
7321
4
    return CAIRO_STATUS_SUCCESS;
7322
4
}
7323
7324
static cairo_int_status_t
7325
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
7326
2
{
7327
2
    cairo_pdf_resource_t knockout, res, thumbnail_res;
7328
2
    cairo_pdf_resource_t *page;
7329
2
    cairo_int_status_t status;
7330
2
    unsigned int i, len, page_num, num_annots;
7331
7332
2
    status = _cairo_pdf_surface_open_object_stream (surface);
7333
2
    if (unlikely (status))
7334
0
  return status;
7335
7336
2
    status = _cairo_pdf_interchange_write_page_objects (surface);
7337
2
    if (unlikely (status))
7338
0
  return status;
7339
7340
2
    _cairo_pdf_group_resources_clear (&surface->resources);
7341
2
    if (surface->has_fallback_images) {
7342
0
  cairo_rectangle_int_t extents;
7343
0
  cairo_box_double_t    bbox;
7344
7345
0
  extents.x = 0;
7346
0
  extents.y = 0;
7347
0
  extents.width = ceil (surface->width);
7348
0
  extents.height = ceil (surface->height);
7349
0
  _get_bbox_from_extents (&extents, &bbox);
7350
0
  status = _cairo_pdf_surface_open_knockout_group (surface, &bbox);
7351
0
  if (unlikely (status))
7352
0
      return status;
7353
7354
0
  len = _cairo_array_num_elements (&surface->knockout_group);
7355
0
  for (i = 0; i < len; i++) {
7356
0
      _cairo_array_copy_element (&surface->knockout_group, i, &res);
7357
0
      _cairo_output_stream_printf (surface->output,
7358
0
           "/x%d Do\n",
7359
0
           res.id);
7360
0
      status = _cairo_pdf_surface_add_xobject (surface, res);
7361
0
      if (unlikely (status))
7362
0
    return status;
7363
0
  }
7364
0
  _cairo_output_stream_printf (surface->output,
7365
0
             "/x%d Do\n",
7366
0
             surface->content.id);
7367
0
  status = _cairo_pdf_surface_add_xobject (surface, surface->content);
7368
0
  if (unlikely (status))
7369
0
      return status;
7370
7371
0
  status = _cairo_pdf_surface_close_group (surface, &knockout);
7372
0
  if (unlikely (status))
7373
0
      return status;
7374
7375
0
  _cairo_pdf_group_resources_clear (&surface->resources);
7376
0
  status = _cairo_pdf_surface_open_content_stream (surface, NULL, NULL, FALSE, FALSE);
7377
0
  if (unlikely (status))
7378
0
      return status;
7379
7380
0
  _cairo_output_stream_printf (surface->output,
7381
0
             "/x%d Do\n",
7382
0
             knockout.id);
7383
0
  status = _cairo_pdf_surface_add_xobject (surface, knockout);
7384
0
  if (unlikely (status))
7385
0
      return status;
7386
7387
0
  status = _cairo_pdf_surface_close_content_stream (surface);
7388
0
  if (unlikely (status))
7389
0
      return status;
7390
0
    }
7391
7392
2
    thumbnail_res.id = 0;
7393
2
    if (surface->thumbnail_image) {
7394
0
  cairo_pdf_source_surface_entry_t entry;
7395
7396
0
  memset (&entry, 0, sizeof (entry));
7397
0
  thumbnail_res = _cairo_pdf_surface_new_object (surface);
7398
0
  entry.surface_res = thumbnail_res;
7399
0
  _cairo_pdf_surface_emit_image (surface, surface->thumbnail_image, &entry);
7400
0
    }
7401
7402
2
    page_num = _cairo_array_num_elements (&surface->pages);
7403
2
    page = _cairo_array_index (&surface->pages, page_num - 1);
7404
7405
2
    status = _cairo_pdf_surface_object_begin (surface, *page);
7406
2
    if (unlikely (status))
7407
0
  return status;
7408
7409
2
    _cairo_output_stream_printf (surface->object_stream.stream,
7410
2
         "<< /Type /Page %% %d\n"
7411
2
         "   /Parent %d 0 R\n"
7412
2
         "   /MediaBox [ 0 0 %f %f ]\n"
7413
2
         "   /Contents %d 0 R\n"
7414
2
         "   /Group <<\n"
7415
2
         "      /Type /Group\n"
7416
2
         "      /S /Transparency\n"
7417
2
         "      /I true\n"
7418
2
         "      /CS /DeviceRGB\n"
7419
2
         "   >>\n"
7420
2
         "   /Resources %d 0 R\n",
7421
2
         page_num,
7422
2
         surface->pages_resource.id,
7423
2
         surface->width,
7424
2
         surface->height,
7425
2
         surface->content.id,
7426
2
         surface->content_resources.id);
7427
7428
2
    if (surface->page_parent_tree >= 0) {
7429
0
  _cairo_output_stream_printf (surface->object_stream.stream,
7430
0
             "   /StructParents %d\n",
7431
0
             surface->page_parent_tree);
7432
0
    }
7433
7434
2
    num_annots = _cairo_array_num_elements (&surface->page_annots);
7435
2
    if (num_annots > 0) {
7436
0
  _cairo_output_stream_printf (surface->object_stream.stream,
7437
0
             "   /Annots [ ");
7438
0
  for (i = 0; i < num_annots; i++) {
7439
0
      _cairo_array_copy_element (&surface->page_annots, i, &res);
7440
0
      _cairo_output_stream_printf (surface->object_stream.stream,
7441
0
           "%d 0 R ",
7442
0
           res.id);
7443
0
  }
7444
0
  _cairo_output_stream_printf (surface->object_stream.stream, "]\n");
7445
0
    }
7446
7447
2
    if (thumbnail_res.id) {
7448
0
  _cairo_output_stream_printf (surface->object_stream.stream,
7449
0
             "   /Thumb %d 0 R\n",
7450
0
             thumbnail_res.id);
7451
0
    }
7452
7453
2
    _cairo_output_stream_printf (surface->object_stream.stream,
7454
2
         ">>\n");
7455
2
    _cairo_pdf_surface_object_end (surface);
7456
7457
2
    status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface, FALSE);
7458
2
    if (unlikely (status))
7459
0
  return status;
7460
7461
2
    return _cairo_pdf_surface_close_object_stream (surface);
7462
2
}
7463
7464
static cairo_int_status_t
7465
_cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t      *surface,
7466
               cairo_surface_pattern_t  *pattern)
7467
0
{
7468
0
    cairo_image_surface_t  *image;
7469
0
    void       *image_extra;
7470
0
    cairo_int_status_t      status;
7471
0
    cairo_image_transparency_t transparency;
7472
7473
0
    status = _cairo_surface_acquire_source_image (pattern->surface,
7474
0
              &image,
7475
0
              &image_extra);
7476
0
    if (unlikely (status))
7477
0
  return status;
7478
7479
0
    if (image->base.status)
7480
0
  return image->base.status;
7481
7482
0
    transparency = _cairo_image_analyze_transparency (image);
7483
0
    if (transparency == CAIRO_IMAGE_IS_OPAQUE)
7484
0
  status = CAIRO_STATUS_SUCCESS;
7485
0
    else
7486
0
  status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
7487
7488
0
    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
7489
7490
0
    return status;
7491
0
}
7492
7493
static cairo_bool_t
7494
_surface_pattern_supported (cairo_surface_pattern_t *pattern)
7495
0
{
7496
0
    cairo_extend_t extend;
7497
7498
0
    if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
7499
0
  return TRUE;
7500
7501
0
    if (pattern->surface->backend->acquire_source_image == NULL)
7502
0
  return FALSE;
7503
7504
    /* Does an ALPHA-only source surface even make sense? Maybe, but I
7505
     * don't think it's worth the extra code to support it. */
7506
7507
/* XXX: Need to write this function here...
7508
    if (pattern->surface->content == CAIRO_CONTENT_ALPHA)
7509
  return FALSE;
7510
*/
7511
7512
0
    extend = cairo_pattern_get_extend (&pattern->base);
7513
0
    switch (extend) {
7514
0
    case CAIRO_EXTEND_NONE:
7515
0
    case CAIRO_EXTEND_REPEAT:
7516
0
    case CAIRO_EXTEND_REFLECT:
7517
    /* There's no point returning FALSE for EXTEND_PAD, as the image
7518
     * surface does not currently implement it either */
7519
0
    case CAIRO_EXTEND_PAD:
7520
0
  return TRUE;
7521
0
    }
7522
7523
0
    ASSERT_NOT_REACHED;
7524
0
    return FALSE;
7525
0
}
7526
7527
static cairo_bool_t
7528
_pattern_supported (const cairo_pattern_t *pattern)
7529
0
{
7530
0
    switch (pattern->type) {
7531
0
    case CAIRO_PATTERN_TYPE_SOLID:
7532
0
    case CAIRO_PATTERN_TYPE_LINEAR:
7533
0
    case CAIRO_PATTERN_TYPE_RADIAL:
7534
0
    case CAIRO_PATTERN_TYPE_MESH:
7535
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
7536
0
  return TRUE;
7537
7538
0
    case CAIRO_PATTERN_TYPE_SURFACE:
7539
0
  return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
7540
7541
0
    default:
7542
0
  ASSERT_NOT_REACHED;
7543
0
  return FALSE;
7544
0
    }
7545
0
}
7546
7547
static cairo_bool_t
7548
_pdf_operator_supported (cairo_operator_t op)
7549
0
{
7550
0
    switch (op) {
7551
0
    case CAIRO_OPERATOR_OVER:
7552
0
    case CAIRO_OPERATOR_MULTIPLY:
7553
0
    case CAIRO_OPERATOR_SCREEN:
7554
0
    case CAIRO_OPERATOR_OVERLAY:
7555
0
    case CAIRO_OPERATOR_DARKEN:
7556
0
    case CAIRO_OPERATOR_LIGHTEN:
7557
0
    case CAIRO_OPERATOR_COLOR_DODGE:
7558
0
    case CAIRO_OPERATOR_COLOR_BURN:
7559
0
    case CAIRO_OPERATOR_HARD_LIGHT:
7560
0
    case CAIRO_OPERATOR_SOFT_LIGHT:
7561
0
    case CAIRO_OPERATOR_DIFFERENCE:
7562
0
    case CAIRO_OPERATOR_EXCLUSION:
7563
0
    case CAIRO_OPERATOR_HSL_HUE:
7564
0
    case CAIRO_OPERATOR_HSL_SATURATION:
7565
0
    case CAIRO_OPERATOR_HSL_COLOR:
7566
0
    case CAIRO_OPERATOR_HSL_LUMINOSITY:
7567
0
  return TRUE;
7568
7569
0
    default:
7570
0
    case CAIRO_OPERATOR_CLEAR:
7571
0
    case CAIRO_OPERATOR_SOURCE:
7572
0
    case CAIRO_OPERATOR_IN:
7573
0
    case CAIRO_OPERATOR_OUT:
7574
0
    case CAIRO_OPERATOR_ATOP:
7575
0
    case CAIRO_OPERATOR_DEST:
7576
0
    case CAIRO_OPERATOR_DEST_OVER:
7577
0
    case CAIRO_OPERATOR_DEST_IN:
7578
0
    case CAIRO_OPERATOR_DEST_OUT:
7579
0
    case CAIRO_OPERATOR_DEST_ATOP:
7580
0
    case CAIRO_OPERATOR_XOR:
7581
0
    case CAIRO_OPERATOR_ADD:
7582
0
    case CAIRO_OPERATOR_SATURATE:
7583
0
  return FALSE;
7584
0
    }
7585
0
}
7586
7587
static cairo_int_status_t
7588
_cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t  *surface,
7589
              cairo_operator_t      op,
7590
              const cairo_pattern_t      *pattern,
7591
              const cairo_rectangle_int_t  *extents)
7592
0
{
7593
0
    if (surface->force_fallbacks &&
7594
0
  surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
7595
0
    {
7596
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
7597
0
    }
7598
7599
0
    if (! _pattern_supported (pattern))
7600
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
7601
7602
0
    if (_pdf_operator_supported (op)) {
7603
0
  if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
7604
0
      cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
7605
7606
0
      if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
7607
0
    if (pattern->extend == CAIRO_EXTEND_PAD) {
7608
0
        cairo_box_t box;
7609
0
        cairo_rectangle_int_t rect;
7610
0
        cairo_rectangle_int_t rec_extents;
7611
7612
        /* get the operation extents in pattern space */
7613
0
        _cairo_box_from_rectangle (&box, extents);
7614
0
        _cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &box, NULL);
7615
0
        _cairo_box_round_to_rectangle (&box, &rect);
7616
7617
        /* Check if surface needs padding to fill extents */
7618
0
        if (_cairo_surface_get_extents (surface_pattern->surface, &rec_extents)) {
7619
0
      if (_cairo_fixed_integer_ceil(box.p1.x) < rec_extents.x ||
7620
0
          _cairo_fixed_integer_ceil(box.p1.y) < rec_extents.y ||
7621
0
          _cairo_fixed_integer_floor(box.p2.y) > rec_extents.x + rec_extents.width ||
7622
0
          _cairo_fixed_integer_floor(box.p2.y) > rec_extents.y + rec_extents.height)
7623
0
      {
7624
0
          return CAIRO_INT_STATUS_UNSUPPORTED;
7625
0
      }
7626
0
        }
7627
0
    }
7628
0
    return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
7629
0
      }
7630
0
  }
7631
7632
0
  return CAIRO_STATUS_SUCCESS;
7633
0
    }
7634
7635
7636
    /* The SOURCE operator is supported if the pattern is opaque or if
7637
     * there is nothing painted underneath. */
7638
0
    if (op == CAIRO_OPERATOR_SOURCE) {
7639
0
  if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
7640
0
      cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
7641
7642
0
      if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
7643
0
    if (_cairo_pattern_is_opaque (pattern, extents)) {
7644
0
        return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
7645
0
    } else {
7646
        /* FIXME: The analysis surface does not yet have
7647
         * the capability to analyze a non opaque recording
7648
         * surface and mark it supported if there is
7649
         * nothing underneath. For now recording surfaces of
7650
         * type CONTENT_COLOR_ALPHA painted with
7651
         * OPERATOR_SOURCE will result in a fallback
7652
         * image. */
7653
7654
0
        return CAIRO_INT_STATUS_UNSUPPORTED;
7655
0
    }
7656
0
      } else {
7657
0
    return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
7658
0
                    surface_pattern);
7659
0
      }
7660
0
  }
7661
7662
0
  if (_cairo_pattern_is_opaque (pattern, extents))
7663
0
      return CAIRO_STATUS_SUCCESS;
7664
0
  else
7665
0
      return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
7666
0
    }
7667
7668
0
    return CAIRO_INT_STATUS_UNSUPPORTED;
7669
0
}
7670
7671
static cairo_bool_t
7672
_cairo_pdf_surface_operation_supported (cairo_pdf_surface_t  *surface,
7673
          cairo_operator_t      op,
7674
          const cairo_pattern_t      *pattern,
7675
          const cairo_rectangle_int_t *extents)
7676
0
{
7677
0
    return _cairo_pdf_surface_analyze_operation (surface, op, pattern, extents) != CAIRO_INT_STATUS_UNSUPPORTED;
7678
0
}
7679
7680
static cairo_int_status_t
7681
_cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
7682
0
{
7683
0
    cairo_box_double_t bbox;
7684
0
    cairo_int_status_t status;
7685
7686
0
    status = _cairo_pdf_surface_close_content_stream (surface);
7687
0
    if (unlikely (status))
7688
0
  return status;
7689
7690
0
    status = _cairo_array_append (&surface->knockout_group, &surface->content);
7691
0
    if (unlikely (status))
7692
0
  return status;
7693
7694
0
    _cairo_pdf_group_resources_clear (&surface->resources);
7695
0
    bbox.p1.x = 0;
7696
0
    bbox.p1.y = 0;
7697
0
    bbox.p2.x = surface->width;
7698
0
    bbox.p2.y = surface->height;
7699
0
    status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, TRUE, TRUE);
7700
0
    if (unlikely (status))
7701
0
  return status;
7702
7703
0
    return _cairo_pdf_interchange_begin_page_content (surface);
7704
0
}
7705
7706
/* If source is an opaque image and mask is an image and both images
7707
 * have the same bounding box we can emit them as a image/smask pair.
7708
 */
7709
static cairo_int_status_t
7710
_cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t         *surface,
7711
          cairo_operator_t       op,
7712
          const cairo_pattern_t       *source,
7713
          const cairo_pattern_t       *mask,
7714
          const cairo_rectangle_int_t *extents)
7715
0
{
7716
0
    cairo_int_status_t status;
7717
0
    cairo_image_surface_t  *image;
7718
0
    void       *image_extra;
7719
0
    cairo_image_transparency_t transparency;
7720
0
    int src_width, src_height;
7721
0
    int mask_width, mask_height;
7722
0
    double src_x_offset, src_y_offset;
7723
0
    double mask_x_offset, mask_y_offset;
7724
0
    double src_x1, src_y1, src_x2, src_y2;
7725
0
    double mask_x1, mask_y1, mask_x2, mask_y2;
7726
0
    cairo_matrix_t p2u;
7727
0
    double src_radius, mask_radius, e;
7728
0
    cairo_bool_t need_smask;
7729
0
    cairo_pdf_source_surface_entry_t *pdf_source;
7730
7731
    /* Check that source and mask are images */
7732
7733
0
    if (!((source->type == CAIRO_PATTERN_TYPE_SURFACE || source->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) &&
7734
0
    (mask->type == CAIRO_PATTERN_TYPE_SURFACE || mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)))
7735
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
7736
7737
0
    if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
7738
0
  ((cairo_surface_pattern_t *) source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
7739
0
    {
7740
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
7741
0
    }
7742
7743
0
    if (mask->type == CAIRO_PATTERN_TYPE_SURFACE &&
7744
0
  ((cairo_surface_pattern_t *) mask)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
7745
0
    {
7746
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
7747
0
    }
7748
7749
0
    if (source->extend != CAIRO_EXTEND_NONE || mask->extend != CAIRO_EXTEND_NONE)
7750
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
7751
7752
    /* Check that source is opaque and get image sizes */
7753
7754
0
    status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source,
7755
0
                   &image, &image_extra);
7756
0
    if (unlikely (status))
7757
0
  return status;
7758
7759
0
    if (image->base.status)
7760
0
  return image->base.status;
7761
7762
0
    src_width = image->width;
7763
0
    src_height = image->height;
7764
0
    if (source->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
7765
0
  cairo_surface_get_device_offset (&image->base, &src_x_offset, &src_y_offset);
7766
0
    } else {
7767
0
  src_x_offset = 0;
7768
0
  src_y_offset = 0;
7769
0
    }
7770
7771
0
    transparency = _cairo_image_analyze_transparency (image);
7772
0
    _cairo_pdf_surface_release_source_image_from_pattern (surface, source, image, image_extra);
7773
7774
0
    if (transparency != CAIRO_IMAGE_IS_OPAQUE)
7775
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
7776
7777
0
    status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, mask,
7778
0
                   &image, &image_extra);
7779
0
    if (unlikely (status))
7780
0
  return status;
7781
7782
0
    if (image->base.status)
7783
0
  return image->base.status;
7784
7785
0
    mask_width = image->width;
7786
0
    mask_height = image->height;
7787
0
    if (mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
7788
0
  cairo_surface_get_device_offset (&image->base, &mask_x_offset, &mask_y_offset);
7789
0
    } else {
7790
0
  mask_x_offset = 0;
7791
0
  mask_y_offset = 0;
7792
0
    }
7793
7794
0
    transparency = _cairo_image_analyze_transparency (image);
7795
0
    need_smask = transparency != CAIRO_IMAGE_IS_OPAQUE;
7796
7797
0
    _cairo_pdf_surface_release_source_image_from_pattern (surface, mask, image, image_extra);
7798
7799
    /* Check that both images have the same extents with a tolerance
7800
     * of half the smallest source pixel. */
7801
7802
0
    p2u = source->matrix;
7803
0
    status = cairo_matrix_invert (&p2u);
7804
    /* cairo_pattern_set_matrix ensures the matrix is invertible */
7805
0
    assert (status == CAIRO_INT_STATUS_SUCCESS);
7806
0
    src_x1 = 0;
7807
0
    src_y1 = 0;
7808
0
    src_x2 = src_width;
7809
0
    src_y2 = src_height;
7810
0
    cairo_matrix_transform_point (&p2u, &src_x1, &src_y1);
7811
0
    cairo_matrix_transform_point (&p2u, &src_x2, &src_y2);
7812
0
    src_radius = _cairo_matrix_transformed_circle_major_axis (&p2u, 0.5);
7813
7814
0
    p2u = mask->matrix;
7815
0
    status = cairo_matrix_invert (&p2u);
7816
    /* cairo_pattern_set_matrix ensures the matrix is invertible */
7817
0
    assert (status == CAIRO_INT_STATUS_SUCCESS);
7818
0
    mask_x1 = 0;
7819
0
    mask_y1 = 0;
7820
0
    mask_x2 = mask_width;
7821
0
    mask_y2 = mask_height;
7822
0
    cairo_matrix_transform_point (&p2u, &mask_x1, &mask_y1);
7823
0
    cairo_matrix_transform_point (&p2u, &mask_x2, &mask_y2);
7824
0
    mask_radius = _cairo_matrix_transformed_circle_major_axis (&p2u, 0.5);
7825
7826
0
    if (src_radius < mask_radius)
7827
0
  e = src_radius;
7828
0
    else
7829
0
  e = mask_radius;
7830
7831
0
    if (fabs(src_x1 - mask_x1) > e ||
7832
0
  fabs(src_x2 - mask_x2) > e ||
7833
0
  fabs(src_y1 - mask_y1) > e ||
7834
0
  fabs(src_y2 - mask_y2) > e)
7835
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
7836
7837
    /* Check both images have same device offset */
7838
0
    if (fabs(src_x_offset - mask_x_offset) > e ||
7839
0
  fabs(src_y_offset - mask_y_offset) > e)
7840
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
7841
7842
0
    if (need_smask) {
7843
0
  status = _cairo_pdf_surface_add_source_surface (surface,
7844
0
              NULL,
7845
0
              mask,
7846
0
              op,
7847
0
              source->filter,
7848
0
              FALSE, /* stencil mask */
7849
0
              TRUE, /* smask */
7850
0
              FALSE, /* need_transp_group */
7851
0
              extents,
7852
0
              NULL, /* smask_res */
7853
0
              &pdf_source,
7854
0
              NULL,
7855
0
              NULL,
7856
0
              NULL);
7857
0
  if (unlikely (status))
7858
0
      return status;
7859
0
    }
7860
7861
0
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7862
0
    if (unlikely (status))
7863
0
  return status;
7864
7865
0
    _cairo_output_stream_printf (surface->output, "q\n");
7866
0
    status = _cairo_pdf_surface_paint_surface_pattern (surface, op, source, extents,
7867
0
                   1.0, /* alpha */
7868
0
                   need_smask ? &pdf_source->surface_res : NULL,
7869
0
                   FALSE);
7870
0
    if (unlikely (status))
7871
0
  return status;
7872
7873
0
    _cairo_output_stream_printf (surface->output, "Q\n");
7874
7875
0
    status = _cairo_output_stream_get_status (surface->output);
7876
7877
7878
0
    return status;
7879
0
}
7880
7881
/* A PDF stencil mask is an A1 mask used with the current color */
7882
static cairo_int_status_t
7883
_cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t         *surface,
7884
              cairo_operator_t             op,
7885
              const cairo_pattern_t       *source,
7886
              const cairo_pattern_t       *mask,
7887
              const cairo_rectangle_int_t *extents)
7888
0
{
7889
0
    cairo_int_status_t status;
7890
0
    cairo_image_surface_t  *image;
7891
0
    void       *image_extra;
7892
0
    cairo_image_transparency_t transparency;
7893
0
    cairo_pdf_resource_t pattern_res = {0};
7894
7895
0
    if (! (source->type == CAIRO_PATTERN_TYPE_SOLID &&
7896
0
     (mask->type == CAIRO_PATTERN_TYPE_SURFACE || mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)))
7897
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
7898
7899
0
    if (mask->type == CAIRO_PATTERN_TYPE_SURFACE &&
7900
0
  ((cairo_surface_pattern_t *) mask)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
7901
0
    {
7902
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
7903
0
    }
7904
7905
0
    status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, mask,
7906
0
                   &image, &image_extra);
7907
0
    if (unlikely (status))
7908
0
  return status;
7909
7910
0
    if (image->base.status)
7911
0
  return image->base.status;
7912
7913
0
    transparency = _cairo_image_analyze_transparency (image);
7914
0
    if (transparency != CAIRO_IMAGE_IS_OPAQUE &&
7915
0
  transparency != CAIRO_IMAGE_HAS_BILEVEL_ALPHA)
7916
0
    {
7917
0
  status = CAIRO_INT_STATUS_UNSUPPORTED;
7918
0
  goto cleanup;
7919
0
    }
7920
7921
0
    status = _cairo_pdf_surface_select_pattern (surface, source,
7922
0
            pattern_res, FALSE);
7923
0
    if (unlikely (status))
7924
0
  return status;
7925
7926
0
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
7927
0
    if (unlikely (status))
7928
0
  return status;
7929
7930
0
    _cairo_output_stream_printf (surface->output, "q\n");
7931
0
    status = _cairo_pdf_surface_paint_surface_pattern (surface, op, mask, extents, 1.0, NULL, TRUE);
7932
0
    if (unlikely (status))
7933
0
  return status;
7934
7935
0
    _cairo_output_stream_printf (surface->output, "Q\n");
7936
7937
0
    status = _cairo_output_stream_get_status (surface->output);
7938
7939
0
cleanup:
7940
0
    _cairo_pdf_surface_release_source_image_from_pattern (surface, mask, image, image_extra);
7941
7942
0
    return status;
7943
0
}
7944
7945
static cairo_int_status_t
7946
_cairo_pdf_surface_set_clip (cairo_pdf_surface_t *surface,
7947
           cairo_composite_rectangles_t *composite)
7948
0
{
7949
0
    cairo_clip_t *clip = composite->clip;
7950
7951
0
    if (_cairo_composite_rectangles_can_reduce_clip (composite, clip))
7952
0
  clip = NULL;
7953
7954
0
    if (clip == NULL) {
7955
0
  if (_cairo_composite_rectangles_can_reduce_clip (composite,
7956
0
               surface->clipper.clip))
7957
0
      return CAIRO_STATUS_SUCCESS;
7958
0
    }
7959
7960
0
    return _cairo_surface_clipper_set_clip (&surface->clipper, clip);
7961
0
}
7962
7963
static cairo_int_status_t
7964
_cairo_pdf_surface_paint (void      *abstract_surface,
7965
        cairo_operator_t   op,
7966
        const cairo_pattern_t *source,
7967
        const cairo_clip_t  *clip)
7968
0
{
7969
0
    cairo_pdf_surface_t *surface = abstract_surface;
7970
0
    cairo_pdf_smask_group_t *group;
7971
0
    cairo_pdf_resource_t pattern_res, gstate_res;
7972
0
    cairo_composite_rectangles_t extents;
7973
0
    cairo_int_status_t status;
7974
7975
0
    status = _cairo_composite_rectangles_init_for_paint (&extents,
7976
0
               &surface->base,
7977
0
               op, source, clip);
7978
0
    if (unlikely (status))
7979
0
  return status;
7980
7981
0
    status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
7982
0
    if (unlikely (status))
7983
0
  return status;
7984
7985
0
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
7986
0
  status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
7987
0
  goto cleanup;
7988
0
    } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
7989
0
  status = _cairo_pdf_surface_start_fallback  (surface);
7990
0
  if (unlikely (status))
7991
0
      goto cleanup;
7992
0
    }
7993
7994
0
    assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
7995
7996
0
    status = _cairo_pdf_surface_set_clip (surface, &extents);
7997
0
    if (unlikely (status))
7998
0
  goto cleanup;
7999
8000
0
    status = _cairo_pdf_surface_select_operator (surface, op);
8001
0
    if (unlikely (status))
8002
0
  goto cleanup;
8003
8004
0
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8005
0
    if (unlikely (status))
8006
0
  goto cleanup;
8007
8008
0
    if (_can_paint_pattern (source)) {
8009
0
  _cairo_output_stream_printf (surface->output, "q\n");
8010
0
  status = _cairo_pdf_surface_paint_pattern (surface,
8011
0
               op,
8012
0
               source,
8013
0
               &extents.bounded,
8014
0
               1.0, /* alpha */
8015
0
               FALSE); /* mask */
8016
0
  if (unlikely (status))
8017
0
      goto cleanup;
8018
8019
0
  _cairo_output_stream_printf (surface->output, "Q\n");
8020
0
  _cairo_composite_rectangles_fini (&extents);
8021
0
  return _cairo_output_stream_get_status (surface->output);
8022
0
    }
8023
8024
0
    pattern_res.id = 0;
8025
0
    gstate_res.id = 0;
8026
0
    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
8027
0
             &extents.bounded,
8028
0
             &pattern_res, &gstate_res);
8029
0
    if (unlikely (status))
8030
0
  goto cleanup;
8031
8032
0
    if (gstate_res.id != 0) {
8033
0
  group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
8034
0
  if (unlikely (group == NULL)) {
8035
0
      status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8036
0
      goto cleanup;
8037
0
  }
8038
8039
0
  group->operation = PDF_PAINT;
8040
0
  status = _cairo_pattern_create_copy (&group->source, source);
8041
0
  if (unlikely (status)) {
8042
0
      _cairo_pdf_smask_group_destroy (group);
8043
0
      goto cleanup;
8044
0
  }
8045
0
  group->source_res = pattern_res;
8046
0
  status = _cairo_pdf_surface_add_smask_group (surface, group);
8047
0
  if (unlikely (status)) {
8048
0
      _cairo_pdf_smask_group_destroy (group);
8049
0
      goto cleanup;
8050
0
  }
8051
8052
0
  status = _cairo_pdf_surface_add_smask (surface, gstate_res);
8053
0
  if (unlikely (status))
8054
0
      goto cleanup;
8055
8056
0
  status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
8057
0
  if (unlikely (status))
8058
0
      goto cleanup;
8059
8060
0
  _cairo_output_stream_printf (surface->output,
8061
0
             "q /s%d gs /x%d Do Q\n",
8062
0
             gstate_res.id,
8063
0
             group->group_res.id);
8064
0
    } else {
8065
0
  status = _cairo_pdf_surface_select_pattern (surface, source,
8066
0
                pattern_res, FALSE);
8067
0
  if (unlikely (status))
8068
0
      goto cleanup;
8069
8070
0
  _cairo_output_stream_printf (surface->output,
8071
0
             "%d %d %d %d re f\n",
8072
0
             surface->surface_extents.x,
8073
0
             surface->surface_extents.y,
8074
0
             surface->surface_extents.width,
8075
0
             surface->surface_extents.height);
8076
8077
0
  status = _cairo_pdf_surface_unselect_pattern (surface);
8078
0
  if (unlikely (status))
8079
0
      goto cleanup;
8080
0
    }
8081
8082
0
    _cairo_composite_rectangles_fini (&extents);
8083
0
    return _cairo_output_stream_get_status (surface->output);
8084
8085
0
cleanup:
8086
0
    _cairo_composite_rectangles_fini (&extents);
8087
0
    return status;
8088
0
}
8089
8090
static cairo_int_status_t
8091
_cairo_pdf_surface_mask (void     *abstract_surface,
8092
       cairo_operator_t  op,
8093
       const cairo_pattern_t  *source,
8094
       const cairo_pattern_t  *mask,
8095
       const cairo_clip_t *clip)
8096
0
{
8097
0
    cairo_pdf_surface_t *surface = abstract_surface;
8098
0
    cairo_pdf_smask_group_t *group;
8099
0
    cairo_composite_rectangles_t extents;
8100
0
    cairo_int_status_t status;
8101
0
    cairo_rectangle_int_t r;
8102
0
    cairo_box_t box;
8103
0
    double alpha;
8104
8105
0
    status = _cairo_composite_rectangles_init_for_mask (&extents,
8106
0
              &surface->base,
8107
0
              op, source, mask, clip);
8108
0
    if (unlikely (status))
8109
0
  return status;
8110
8111
0
    status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
8112
0
    if (unlikely (status))
8113
0
  return status;
8114
8115
0
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
8116
0
  cairo_int_status_t source_status, mask_status;
8117
8118
0
  status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
8119
0
  if (_cairo_int_status_is_error (status))
8120
0
      goto cleanup;
8121
0
  source_status = status;
8122
8123
0
  if (mask->has_component_alpha) {
8124
0
      status = CAIRO_INT_STATUS_UNSUPPORTED;
8125
0
  } else {
8126
0
      status = _cairo_pdf_surface_analyze_operation (surface, op, mask, &extents.bounded);
8127
0
      if (_cairo_int_status_is_error (status))
8128
0
    goto cleanup;
8129
0
  }
8130
0
  mask_status = status;
8131
8132
0
  _cairo_composite_rectangles_fini (&extents);
8133
0
  return _cairo_analysis_surface_merge_status (source_status,
8134
0
                 mask_status);
8135
0
    } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
8136
0
  status = _cairo_pdf_surface_start_fallback (surface);
8137
0
  if (unlikely (status))
8138
0
      goto cleanup;
8139
0
    }
8140
8141
0
    assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
8142
0
    assert (_cairo_pdf_surface_operation_supported (surface, op, mask, &extents.bounded));
8143
8144
    /* get the accurate extents */
8145
0
    status = _cairo_pattern_get_ink_extents (source, &r);
8146
0
    if (unlikely (status))
8147
0
  goto cleanup;
8148
8149
    /* XXX slight impedance mismatch */
8150
0
    _cairo_box_from_rectangle (&box, &r);
8151
0
    status = _cairo_composite_rectangles_intersect_source_extents (&extents,
8152
0
                   &box);
8153
0
    if (unlikely (status))
8154
0
  goto cleanup;
8155
8156
0
    status = _cairo_pattern_get_ink_extents (mask, &r);
8157
0
    if (unlikely (status))
8158
0
  goto cleanup;
8159
8160
0
    _cairo_box_from_rectangle (&box, &r);
8161
0
    status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
8162
0
                 &box);
8163
0
    if (unlikely (status))
8164
0
  goto cleanup;
8165
8166
0
    status = _cairo_pdf_surface_set_clip (surface, &extents);
8167
0
    if (unlikely (status))
8168
0
  goto cleanup;
8169
8170
0
    status = _cairo_pdf_surface_select_operator (surface, op);
8171
0
    if (unlikely (status))
8172
0
  goto cleanup;
8173
8174
    /* Check if we can combine source and mask into a smask image */
8175
0
    status = _cairo_pdf_surface_emit_combined_smask (surface, op, source, mask, &extents.bounded);
8176
0
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
8177
0
  goto cleanup;
8178
8179
    /* Check if we can use a stencil mask */
8180
0
    status = _cairo_pdf_surface_emit_stencil_mask (surface, op, source, mask, &extents.bounded);
8181
0
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
8182
0
  goto cleanup;
8183
8184
    /* Check if we can set ca/CA instead of an smask. We could handle
8185
     * other source patterns as well but for now this is the easiest,
8186
     * and most common, case to handle. */
8187
0
    if (_cairo_pattern_is_constant_alpha (mask, &extents.bounded, &alpha) &&
8188
0
  _can_paint_pattern (source)) {
8189
8190
0
  status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8191
0
  if (unlikely (status))
8192
0
      goto cleanup;
8193
8194
0
  _cairo_output_stream_printf (surface->output, "q\n");
8195
0
  status = _cairo_pdf_surface_paint_pattern (surface,
8196
0
               op,
8197
0
               source,
8198
0
               &extents.bounded,
8199
0
               alpha,
8200
0
               FALSE); /* mask */
8201
0
  if (unlikely (status))
8202
0
      goto cleanup;
8203
8204
0
  _cairo_output_stream_printf (surface->output, "Q\n");
8205
0
  _cairo_composite_rectangles_fini (&extents);
8206
0
  return _cairo_output_stream_get_status (surface->output);
8207
0
    }
8208
8209
0
    group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
8210
0
    if (unlikely (group == NULL)) {
8211
0
  status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8212
0
  goto cleanup;
8213
0
    }
8214
8215
0
    group->operation = PDF_MASK;
8216
0
    status = _cairo_pattern_create_copy (&group->source, source);
8217
0
    if (unlikely (status)) {
8218
0
  _cairo_pdf_smask_group_destroy (group);
8219
0
  goto cleanup;
8220
0
    }
8221
0
    status = _cairo_pattern_create_copy (&group->mask, mask);
8222
0
    if (unlikely (status)) {
8223
0
  _cairo_pdf_smask_group_destroy (group);
8224
0
  goto cleanup;
8225
0
    }
8226
0
    group->source_res = _cairo_pdf_surface_new_object (surface);
8227
0
    if (group->source_res.id == 0) {
8228
0
  _cairo_pdf_smask_group_destroy (group);
8229
0
  status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8230
0
  goto cleanup;
8231
0
    }
8232
8233
0
    status = _cairo_pdf_surface_add_smask_group (surface, group);
8234
0
    if (unlikely (status)) {
8235
0
  _cairo_pdf_smask_group_destroy (group);
8236
0
  goto cleanup;
8237
0
    }
8238
8239
0
    status = _cairo_pdf_surface_add_smask (surface, group->group_res);
8240
0
    if (unlikely (status))
8241
0
  goto cleanup;
8242
8243
0
    status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
8244
0
    if (unlikely (status))
8245
0
  goto cleanup;
8246
8247
0
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8248
0
    if (unlikely (status))
8249
0
  goto cleanup;
8250
8251
0
    _cairo_output_stream_printf (surface->output,
8252
0
         "q /s%d gs /x%d Do Q\n",
8253
0
         group->group_res.id,
8254
0
         group->source_res.id);
8255
8256
0
    _cairo_composite_rectangles_fini (&extents);
8257
0
    return _cairo_output_stream_get_status (surface->output);
8258
8259
0
cleanup:
8260
0
    _cairo_composite_rectangles_fini (&extents);
8261
0
    return status;
8262
0
}
8263
8264
static cairo_int_status_t
8265
_cairo_pdf_surface_stroke (void     *abstract_surface,
8266
         cairo_operator_t  op,
8267
         const cairo_pattern_t *source,
8268
         const cairo_path_fixed_t *path,
8269
         const cairo_stroke_style_t *style,
8270
         const cairo_matrix_t *ctm,
8271
         const cairo_matrix_t *ctm_inverse,
8272
         double    tolerance,
8273
         cairo_antialias_t   antialias,
8274
         const cairo_clip_t *clip)
8275
0
{
8276
0
    cairo_pdf_surface_t *surface = abstract_surface;
8277
0
    cairo_pdf_smask_group_t *group;
8278
0
    cairo_pdf_resource_t pattern_res, gstate_res;
8279
0
    cairo_composite_rectangles_t extents;
8280
0
    cairo_int_status_t status;
8281
8282
0
    status = _cairo_composite_rectangles_init_for_stroke (&extents,
8283
0
                &surface->base,
8284
0
                op, source,
8285
0
                path, style, ctm,
8286
0
                clip);
8287
0
    if (unlikely (status))
8288
0
  return status;
8289
8290
    /* use the more accurate extents */
8291
0
    if (extents.is_bounded) {
8292
0
  cairo_rectangle_int_t mask;
8293
0
  cairo_box_t box;
8294
8295
0
  status = _cairo_path_fixed_stroke_extents (path, style,
8296
0
               ctm, ctm_inverse,
8297
0
               tolerance,
8298
0
               &mask);
8299
0
  if (unlikely (status))
8300
0
      goto cleanup;
8301
8302
0
  _cairo_box_from_rectangle (&box, &mask);
8303
0
  status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
8304
0
                     &box);
8305
0
  if (unlikely (status))
8306
0
      goto cleanup;
8307
0
    }
8308
8309
0
    status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
8310
0
    if (unlikely (status))
8311
0
  goto cleanup;
8312
8313
0
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
8314
0
  status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
8315
0
  goto cleanup;
8316
0
    }
8317
8318
0
    assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
8319
8320
0
    status = _cairo_pdf_surface_set_clip (surface, &extents);
8321
0
    if (unlikely (status))
8322
0
  goto cleanup;
8323
8324
0
    pattern_res.id = 0;
8325
0
    gstate_res.id = 0;
8326
0
    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
8327
0
             &extents.bounded,
8328
0
             &pattern_res, &gstate_res);
8329
0
    if (unlikely (status))
8330
0
  goto cleanup;
8331
8332
0
    status = _cairo_pdf_surface_select_operator (surface, op);
8333
0
    if (unlikely (status))
8334
0
  goto cleanup;
8335
8336
0
    if (gstate_res.id != 0) {
8337
0
  group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
8338
0
  if (unlikely (group == NULL)) {
8339
0
      status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8340
0
      goto cleanup;
8341
0
  }
8342
8343
0
  group->operation = PDF_STROKE;
8344
0
  status = _cairo_pattern_create_copy (&group->source, source);
8345
0
  if (unlikely (status)) {
8346
0
      _cairo_pdf_smask_group_destroy (group);
8347
0
      goto cleanup;
8348
0
  }
8349
0
  group->source_res = pattern_res;
8350
0
  status = _cairo_path_fixed_init_copy (&group->path, path);
8351
0
  if (unlikely (status)) {
8352
0
      _cairo_pdf_smask_group_destroy (group);
8353
0
      goto cleanup;
8354
0
  }
8355
8356
0
  group->style = *style;
8357
0
  group->ctm = *ctm;
8358
0
  group->ctm_inverse = *ctm_inverse;
8359
0
  status = _cairo_pdf_surface_add_smask_group (surface, group);
8360
0
  if (unlikely (status)) {
8361
0
      _cairo_pdf_smask_group_destroy (group);
8362
0
      goto cleanup;
8363
0
  }
8364
8365
0
  status = _cairo_pdf_surface_add_smask (surface, gstate_res);
8366
0
  if (unlikely (status))
8367
0
      goto cleanup;
8368
8369
0
  status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
8370
0
  if (unlikely (status))
8371
0
      goto cleanup;
8372
8373
0
  status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8374
0
  if (unlikely (status))
8375
0
      goto cleanup;
8376
8377
0
  _cairo_output_stream_printf (surface->output,
8378
0
             "q /s%d gs /x%d Do Q\n",
8379
0
             gstate_res.id,
8380
0
             group->group_res.id);
8381
0
    } else {
8382
0
  status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
8383
0
  if (unlikely (status))
8384
0
      goto cleanup;
8385
8386
0
  status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
8387
0
                path,
8388
0
                style,
8389
0
                ctm,
8390
0
                ctm_inverse);
8391
0
  if (unlikely (status))
8392
0
      goto cleanup;
8393
8394
0
  status = _cairo_pdf_surface_unselect_pattern (surface);
8395
0
  if (unlikely (status))
8396
0
      goto cleanup;
8397
0
    }
8398
8399
0
    _cairo_composite_rectangles_fini (&extents);
8400
0
    return _cairo_output_stream_get_status (surface->output);
8401
8402
0
cleanup:
8403
0
    _cairo_composite_rectangles_fini (&extents);
8404
0
    return status;
8405
0
}
8406
8407
static cairo_int_status_t
8408
_cairo_pdf_surface_fill (void     *abstract_surface,
8409
       cairo_operator_t  op,
8410
       const cairo_pattern_t  *source,
8411
       const cairo_path_fixed_t*path,
8412
       cairo_fill_rule_t   fill_rule,
8413
       double      tolerance,
8414
       cairo_antialias_t   antialias,
8415
       const cairo_clip_t *clip)
8416
0
{
8417
0
    cairo_pdf_surface_t *surface = abstract_surface;
8418
0
    cairo_int_status_t status;
8419
0
    cairo_pdf_smask_group_t *group;
8420
0
    cairo_pdf_resource_t pattern_res, gstate_res;
8421
0
    cairo_composite_rectangles_t extents;
8422
8423
0
    status = _cairo_composite_rectangles_init_for_fill (&extents,
8424
0
              &surface->base,
8425
0
              op, source, path,
8426
0
              clip);
8427
0
    if (unlikely (status))
8428
0
  return status;
8429
8430
    /* use the more accurate extents */
8431
0
    if (extents.is_bounded) {
8432
0
  cairo_rectangle_int_t mask;
8433
0
  cairo_box_t box;
8434
8435
0
  _cairo_path_fixed_fill_extents (path,
8436
0
          fill_rule,
8437
0
          tolerance,
8438
0
          &mask);
8439
8440
0
  _cairo_box_from_rectangle (&box, &mask);
8441
0
  status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
8442
0
                     &box);
8443
0
  if (unlikely (status))
8444
0
      goto cleanup;
8445
0
    }
8446
8447
0
    status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
8448
0
    if (unlikely (status))
8449
0
  goto cleanup;
8450
8451
0
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
8452
0
  status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
8453
0
  goto cleanup;
8454
0
    } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
8455
0
  status = _cairo_pdf_surface_start_fallback (surface);
8456
0
  if (unlikely (status))
8457
0
      goto cleanup;
8458
0
    }
8459
8460
0
    assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
8461
8462
0
    status = _cairo_pdf_surface_set_clip (surface, &extents);
8463
0
    if (unlikely (status))
8464
0
  goto cleanup;
8465
8466
0
    status = _cairo_pdf_surface_select_operator (surface, op);
8467
0
    if (unlikely (status))
8468
0
  goto cleanup;
8469
8470
0
    if (_can_paint_pattern (source)) {
8471
0
  status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8472
0
  if (unlikely (status))
8473
0
      goto cleanup;
8474
8475
0
  _cairo_output_stream_printf (surface->output, "q\n");
8476
0
  status =  _cairo_pdf_operators_clip (&surface->pdf_operators,
8477
0
               path,
8478
0
               fill_rule);
8479
0
  if (unlikely (status))
8480
0
      goto cleanup;
8481
8482
0
  status = _cairo_pdf_surface_paint_pattern (surface,
8483
0
               op,
8484
0
               source,
8485
0
               &extents.bounded,
8486
0
               1.0, /* alpha */
8487
0
               FALSE); /* mask */
8488
0
  if (unlikely (status))
8489
0
      goto cleanup;
8490
8491
0
  _cairo_output_stream_printf (surface->output, "Q\n");
8492
0
  status = _cairo_output_stream_get_status (surface->output);
8493
0
  goto cleanup;
8494
0
    }
8495
8496
0
    pattern_res.id = 0;
8497
0
    gstate_res.id = 0;
8498
0
    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
8499
0
             &extents.bounded,
8500
0
             &pattern_res, &gstate_res);
8501
0
    if (unlikely (status))
8502
0
  goto cleanup;
8503
8504
0
    if (gstate_res.id != 0) {
8505
0
  group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
8506
0
  if (unlikely (group == NULL)) {
8507
0
      status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8508
0
      goto cleanup;
8509
0
  }
8510
8511
0
  group->operation = PDF_FILL;
8512
0
  status = _cairo_pattern_create_copy (&group->source, source);
8513
0
  if (unlikely (status)) {
8514
0
      _cairo_pdf_smask_group_destroy (group);
8515
0
      goto cleanup;
8516
0
  }
8517
0
  group->source_res = pattern_res;
8518
0
  status = _cairo_path_fixed_init_copy (&group->path, path);
8519
0
  if (unlikely (status)) {
8520
0
      _cairo_pdf_smask_group_destroy (group);
8521
0
      goto cleanup;
8522
0
  }
8523
8524
0
  group->fill_rule = fill_rule;
8525
0
  status = _cairo_pdf_surface_add_smask_group (surface, group);
8526
0
  if (unlikely (status)) {
8527
0
      _cairo_pdf_smask_group_destroy (group);
8528
0
      goto cleanup;
8529
0
  }
8530
8531
0
  status = _cairo_pdf_surface_add_smask (surface, gstate_res);
8532
0
  if (unlikely (status))
8533
0
      goto cleanup;
8534
8535
0
  status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
8536
0
  if (unlikely (status))
8537
0
      goto cleanup;
8538
8539
0
  status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8540
0
  if (unlikely (status))
8541
0
      goto cleanup;
8542
8543
0
  _cairo_output_stream_printf (surface->output,
8544
0
             "q /s%d gs /x%d Do Q\n",
8545
0
             gstate_res.id,
8546
0
             group->group_res.id);
8547
0
    } else {
8548
0
  status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
8549
0
  if (unlikely (status))
8550
0
      goto cleanup;
8551
8552
0
  status = _cairo_pdf_operators_fill (&surface->pdf_operators,
8553
0
              path,
8554
0
              fill_rule);
8555
0
  if (unlikely (status))
8556
0
      goto cleanup;
8557
8558
0
  status = _cairo_pdf_surface_unselect_pattern (surface);
8559
0
  if (unlikely (status))
8560
0
      goto cleanup;
8561
0
    }
8562
8563
0
    _cairo_composite_rectangles_fini (&extents);
8564
0
    return _cairo_output_stream_get_status (surface->output);
8565
8566
0
cleanup:
8567
0
    _cairo_composite_rectangles_fini (&extents);
8568
0
    return status;
8569
0
}
8570
8571
static cairo_int_status_t
8572
_cairo_pdf_surface_fill_stroke (void      *abstract_surface,
8573
        cairo_operator_t   fill_op,
8574
        const cairo_pattern_t *fill_source,
8575
        cairo_fill_rule_t  fill_rule,
8576
        double       fill_tolerance,
8577
        cairo_antialias_t  fill_antialias,
8578
        const cairo_path_fixed_t*path,
8579
        cairo_operator_t   stroke_op,
8580
        const cairo_pattern_t *stroke_source,
8581
        const cairo_stroke_style_t *stroke_style,
8582
        const cairo_matrix_t  *stroke_ctm,
8583
        const cairo_matrix_t  *stroke_ctm_inverse,
8584
        double       stroke_tolerance,
8585
        cairo_antialias_t  stroke_antialias,
8586
        const cairo_clip_t  *clip)
8587
0
{
8588
0
    cairo_pdf_surface_t *surface = abstract_surface;
8589
0
    cairo_int_status_t status;
8590
0
    cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res;
8591
0
    cairo_composite_rectangles_t extents;
8592
8593
    /* During analysis we return unsupported and let the _fill and
8594
     * _stroke functions that are on the fallback path do the analysis
8595
     * for us. During render we may still encounter unsupported
8596
     * combinations of fill/stroke patterns. However we can return
8597
     * unsupported anytime to let the _fill and _stroke functions take
8598
     * over.
8599
     */
8600
0
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
8601
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
8602
8603
    /* PDF rendering of fill-stroke is not the same as cairo when
8604
     * either the fill or stroke is not opaque.
8605
     */
8606
0
    if ( !_cairo_pattern_is_opaque (fill_source, NULL) ||
8607
0
   !_cairo_pattern_is_opaque (stroke_source, NULL))
8608
0
    {
8609
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
8610
0
    }
8611
8612
0
    if (fill_op != stroke_op)
8613
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
8614
8615
    /* Compute the operation extents using the stroke which will naturally
8616
     * be larger than the fill extents.
8617
     */
8618
0
    status = _cairo_composite_rectangles_init_for_stroke (&extents,
8619
0
                &surface->base,
8620
0
                stroke_op, stroke_source,
8621
0
                path, stroke_style, stroke_ctm,
8622
0
                clip);
8623
0
    if (unlikely (status))
8624
0
  return status;
8625
8626
    /* use the more accurate extents */
8627
0
    if (extents.is_bounded) {
8628
0
  cairo_rectangle_int_t mask;
8629
0
  cairo_box_t box;
8630
8631
0
  status = _cairo_path_fixed_stroke_extents (path, stroke_style,
8632
0
               stroke_ctm, stroke_ctm_inverse,
8633
0
               stroke_tolerance,
8634
0
               &mask);
8635
0
  if (unlikely (status))
8636
0
      goto cleanup;
8637
8638
0
  _cairo_box_from_rectangle (&box, &mask);
8639
0
  status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
8640
0
                     &box);
8641
0
  if (unlikely (status))
8642
0
      goto cleanup;
8643
0
    }
8644
8645
0
    status = _cairo_pdf_surface_set_clip (surface, &extents);
8646
0
    if (unlikely (status))
8647
0
  goto cleanup;
8648
8649
0
    status = _cairo_pdf_surface_select_operator (surface, fill_op);
8650
0
    if (unlikely (status))
8651
0
  goto cleanup;
8652
8653
    /* use the more accurate extents */
8654
0
    if (extents.is_bounded) {
8655
0
  cairo_rectangle_int_t mask;
8656
0
  cairo_box_t box;
8657
8658
0
  _cairo_path_fixed_fill_extents (path,
8659
0
          fill_rule,
8660
0
          fill_tolerance,
8661
0
          &mask);
8662
8663
0
  _cairo_box_from_rectangle (&box, &mask);
8664
0
  status = _cairo_composite_rectangles_intersect_mask_extents (&extents,
8665
0
                     &box);
8666
0
  if (unlikely (status))
8667
0
      goto cleanup;
8668
0
    }
8669
8670
0
    status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
8671
0
    if (unlikely (status))
8672
0
  goto cleanup;
8673
8674
0
    fill_pattern_res.id = 0;
8675
0
    gstate_res.id = 0;
8676
0
    status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
8677
0
             fill_op,
8678
0
             &extents.bounded,
8679
0
             &fill_pattern_res,
8680
0
             &gstate_res);
8681
0
    if (unlikely (status))
8682
0
  goto cleanup;
8683
8684
0
    assert (gstate_res.id == 0);
8685
8686
0
    stroke_pattern_res.id = 0;
8687
0
    gstate_res.id = 0;
8688
0
    status = _cairo_pdf_surface_add_pdf_pattern (surface,
8689
0
             stroke_source,
8690
0
             stroke_op,
8691
0
             &extents.bounded,
8692
0
             &stroke_pattern_res,
8693
0
             &gstate_res);
8694
0
    if (unlikely (status))
8695
0
  goto cleanup;
8696
8697
0
    assert (gstate_res.id == 0);
8698
8699
    /* As PDF has separate graphics state for fill and stroke we can
8700
     * select both at the same time */
8701
0
    status = _cairo_pdf_surface_select_pattern (surface, fill_source,
8702
0
            fill_pattern_res, FALSE);
8703
0
    if (unlikely (status))
8704
0
  goto cleanup;
8705
8706
0
    status = _cairo_pdf_surface_select_pattern (surface, stroke_source,
8707
0
            stroke_pattern_res, TRUE);
8708
0
    if (unlikely (status))
8709
0
  goto cleanup;
8710
8711
0
    status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators,
8712
0
                 path,
8713
0
                 fill_rule,
8714
0
                 stroke_style,
8715
0
                 stroke_ctm,
8716
0
                 stroke_ctm_inverse);
8717
0
    if (unlikely (status))
8718
0
  goto cleanup;
8719
8720
0
    status = _cairo_pdf_surface_unselect_pattern (surface);
8721
0
    if (unlikely (status))
8722
0
  goto cleanup;
8723
8724
0
    _cairo_composite_rectangles_fini (&extents);
8725
0
    return _cairo_output_stream_get_status (surface->output);
8726
8727
0
cleanup:
8728
0
    _cairo_composite_rectangles_fini (&extents);
8729
0
    return status;
8730
0
}
8731
8732
static cairo_bool_t
8733
_cairo_pdf_surface_has_show_text_glyphs (void     *abstract_surface)
8734
0
{
8735
0
    return TRUE;
8736
0
}
8737
8738
static cairo_int_status_t
8739
_cairo_pdf_surface_show_text_glyphs (void     *abstract_surface,
8740
             cairo_operator_t    op,
8741
             const cairo_pattern_t  *source,
8742
             const char                 *utf8,
8743
             int                         utf8_len,
8744
             cairo_glyph_t    *glyphs,
8745
             int       num_glyphs,
8746
             const cairo_text_cluster_t *clusters,
8747
             int                         num_clusters,
8748
             cairo_text_cluster_flags_t  cluster_flags,
8749
             cairo_scaled_font_t  *scaled_font,
8750
             const cairo_clip_t   *clip)
8751
0
{
8752
0
    cairo_pdf_surface_t *surface = abstract_surface;
8753
0
    cairo_pdf_smask_group_t *group;
8754
0
    cairo_pdf_resource_t pattern_res, gstate_res;
8755
0
    cairo_composite_rectangles_t extents;
8756
0
    cairo_bool_t overlap;
8757
0
    cairo_int_status_t status;
8758
8759
0
    status = _cairo_composite_rectangles_init_for_glyphs (&extents,
8760
0
                &surface->base,
8761
0
                op, source,
8762
0
                scaled_font,
8763
0
                glyphs, num_glyphs,
8764
0
                clip,
8765
0
                &overlap);
8766
0
    if (unlikely (status))
8767
0
  return status;
8768
8769
0
    status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded);
8770
0
    if (unlikely (status))
8771
0
  return status;
8772
8773
0
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
8774
0
  status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
8775
0
  goto cleanup;
8776
0
    }
8777
8778
0
    assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
8779
8780
0
    status = _cairo_pdf_surface_set_clip (surface, &extents);
8781
0
    if (unlikely (status))
8782
0
  goto cleanup;
8783
8784
0
    pattern_res.id = 0;
8785
0
    gstate_res.id = 0;
8786
0
    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
8787
0
             &extents.bounded,
8788
0
             &pattern_res, &gstate_res);
8789
0
    if (unlikely (status))
8790
0
  goto cleanup;
8791
8792
0
    status = _cairo_pdf_surface_select_operator (surface, op);
8793
0
    if (unlikely (status))
8794
0
  goto cleanup;
8795
8796
0
    if (gstate_res.id != 0) {
8797
0
  group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded);
8798
0
  if (unlikely (group == NULL)) {
8799
0
      status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8800
0
      goto cleanup;
8801
0
  }
8802
8803
0
  group->operation = PDF_SHOW_GLYPHS;
8804
0
  status = _cairo_pattern_create_copy (&group->source, source);
8805
0
  if (unlikely (status)) {
8806
0
      _cairo_pdf_smask_group_destroy (group);
8807
0
      goto cleanup;
8808
0
  }
8809
0
  group->source_res = pattern_res;
8810
8811
0
  if (utf8_len) {
8812
0
      group->utf8 = _cairo_malloc (utf8_len);
8813
0
      if (unlikely (group->utf8 == NULL)) {
8814
0
    _cairo_pdf_smask_group_destroy (group);
8815
0
    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8816
0
    goto cleanup;
8817
0
      }
8818
0
      memcpy (group->utf8, utf8, utf8_len);
8819
0
  }
8820
0
  group->utf8_len = utf8_len;
8821
8822
0
  if (num_glyphs) {
8823
0
      group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
8824
0
      if (unlikely (group->glyphs == NULL)) {
8825
0
    _cairo_pdf_smask_group_destroy (group);
8826
0
    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8827
0
    goto cleanup;
8828
0
      }
8829
0
      memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
8830
0
  }
8831
0
  group->num_glyphs = num_glyphs;
8832
8833
0
  if (num_clusters) {
8834
0
      group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
8835
0
      if (unlikely (group->clusters == NULL)) {
8836
0
    _cairo_pdf_smask_group_destroy (group);
8837
0
    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
8838
0
    goto cleanup;
8839
0
      }
8840
0
      memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
8841
0
  }
8842
0
  group->num_clusters = num_clusters;
8843
8844
0
  group->scaled_font = cairo_scaled_font_reference (scaled_font);
8845
0
  status = _cairo_pdf_surface_add_smask_group (surface, group);
8846
0
  if (unlikely (status)) {
8847
0
      _cairo_pdf_smask_group_destroy (group);
8848
0
      goto cleanup;
8849
0
  }
8850
8851
0
  status = _cairo_pdf_surface_add_smask (surface, gstate_res);
8852
0
  if (unlikely (status))
8853
0
      goto cleanup;
8854
8855
0
  status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
8856
0
  if (unlikely (status))
8857
0
      goto cleanup;
8858
8859
0
  status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8860
0
  if (unlikely (status))
8861
0
      goto cleanup;
8862
8863
0
  _cairo_output_stream_printf (surface->output,
8864
0
             "q /s%d gs /x%d Do Q\n",
8865
0
             gstate_res.id,
8866
0
             group->group_res.id);
8867
0
    } else {
8868
0
  status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
8869
0
  if (unlikely (status))
8870
0
      goto cleanup;
8871
8872
  /* Each call to show_glyphs() with a transclucent pattern must
8873
   * be in a separate text object otherwise overlapping text
8874
   * from separate calls to show_glyphs will not composite with
8875
   * each other. */
8876
0
  if (! _cairo_pattern_is_opaque (source, &extents.bounded)) {
8877
0
      status = _cairo_pdf_operators_flush (&surface->pdf_operators);
8878
0
      if (unlikely (status))
8879
0
    goto cleanup;
8880
0
  }
8881
8882
0
  status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
8883
0
              utf8, utf8_len,
8884
0
              glyphs, num_glyphs,
8885
0
              clusters, num_clusters,
8886
0
              cluster_flags,
8887
0
              scaled_font);
8888
0
  if (unlikely (status))
8889
0
      goto cleanup;
8890
8891
0
  status = _cairo_pdf_surface_unselect_pattern (surface);
8892
0
  if (unlikely (status))
8893
0
      goto cleanup;
8894
0
    }
8895
8896
0
    _cairo_composite_rectangles_fini (&extents);
8897
0
    return _cairo_output_stream_get_status (surface->output);
8898
8899
0
cleanup:
8900
0
    _cairo_composite_rectangles_fini (&extents);
8901
0
    return status;
8902
0
}
8903
8904
static const char **
8905
_cairo_pdf_surface_get_supported_mime_types (void    *abstract_surface)
8906
0
{
8907
0
    return _cairo_pdf_supported_mime_types;
8908
0
}
8909
8910
static cairo_int_status_t
8911
_cairo_pdf_surface_tag (void         *abstract_surface,
8912
      cairo_bool_t                begin,
8913
      const char                 *tag_name,
8914
      const char                 *attributes)
8915
0
{
8916
0
    cairo_pdf_surface_t *surface = abstract_surface;
8917
0
    cairo_int_status_t status = 0;
8918
8919
0
    if (begin)
8920
0
  status = _cairo_pdf_interchange_tag_begin (surface, tag_name, attributes);
8921
0
    else
8922
0
  status = _cairo_pdf_interchange_tag_end (surface, tag_name);
8923
8924
0
    return status;
8925
0
}
8926
8927
static cairo_int_status_t
8928
_cairo_pdf_surface_set_paginated_mode (void     *abstract_surface,
8929
               cairo_paginated_mode_t  paginated_mode)
8930
2
{
8931
2
    cairo_pdf_surface_t *surface = abstract_surface;
8932
2
    cairo_int_status_t status;
8933
8934
2
    surface->paginated_mode = paginated_mode;
8935
2
    status = _cairo_pdf_interchange_begin_page_content (surface);
8936
2
    if (unlikely (status))
8937
0
  return status;
8938
8939
2
    if (paginated_mode == CAIRO_PAGINATED_MODE_RENDER) {
8940
0
  surface->surface_extents.x = 0;
8941
0
  surface->surface_extents.y = 0;
8942
0
  surface->surface_extents.width  = ceil (surface->width);
8943
0
  surface->surface_extents.height = ceil (surface->height);
8944
0
    }
8945
8946
2
    return CAIRO_INT_STATUS_SUCCESS;
8947
2
}
8948
8949
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
8950
    CAIRO_SURFACE_TYPE_PDF,
8951
    _cairo_pdf_surface_finish,
8952
8953
    _cairo_default_context_create,
8954
8955
    NULL, /* create similar: handled by wrapper */
8956
    NULL, /* create similar image */
8957
    NULL, /* map to image */
8958
    NULL, /* unmap image */
8959
8960
    _cairo_surface_default_source,
8961
    NULL, /* acquire_source_image */
8962
    NULL, /* release_source_image */
8963
    NULL, /* snapshot */
8964
8965
    NULL,  /* _cairo_pdf_surface_copy_page */
8966
    _cairo_pdf_surface_show_page,
8967
8968
    _cairo_pdf_surface_get_extents,
8969
    _cairo_pdf_surface_get_font_options,
8970
8971
    NULL, /* flush */
8972
    NULL, /* mark_dirty_rectangle */
8973
8974
    /* Here are the drawing functions */
8975
    _cairo_pdf_surface_paint,
8976
    _cairo_pdf_surface_mask,
8977
    _cairo_pdf_surface_stroke,
8978
    _cairo_pdf_surface_fill,
8979
    _cairo_pdf_surface_fill_stroke,
8980
    NULL, /* show_glyphs */
8981
    _cairo_pdf_surface_has_show_text_glyphs,
8982
    _cairo_pdf_surface_show_text_glyphs,
8983
    _cairo_pdf_surface_get_supported_mime_types,
8984
    _cairo_pdf_surface_tag,
8985
};
8986
8987
static const cairo_paginated_surface_backend_t
8988
cairo_pdf_surface_paginated_backend = {
8989
    _cairo_pdf_surface_start_page,
8990
    _cairo_pdf_surface_set_paginated_mode,
8991
    NULL, /* set_bounding_box */
8992
    _cairo_pdf_surface_has_fallback_images,
8993
    _cairo_pdf_surface_supports_fine_grained_fallbacks,
8994
    _cairo_pdf_surface_requires_thumbnail_image,
8995
    _cairo_pdf_surface_set_thumbnail_image,
8996
};