Coverage Report

Created: 2026-03-31 07:41

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