Coverage Report

Created: 2025-07-23 08:13

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