~ubuntu-branches/ubuntu/karmic/moon/karmic

« back to all changes in this revision

Viewing changes to cairo/src/cairo-pdf-surface.c

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2009-02-14 12:01:08 UTC
  • Revision ID: james.westby@ubuntu.com-20090214120108-06539vb25vhbd8bn
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 _BSD_SOURCE /* for snprintf() */
 
43
#include "cairoint.h"
 
44
#include "cairo-pdf.h"
 
45
#include "cairo-pdf-surface-private.h"
 
46
#include "cairo-pdf-operators-private.h"
 
47
#include "cairo-scaled-font-subsets-private.h"
 
48
#include "cairo-paginated-private.h"
 
49
#include "cairo-output-stream-private.h"
 
50
#include "cairo-meta-surface-private.h"
 
51
#include "cairo-type3-glyph-surface-private.h"
 
52
 
 
53
#include <time.h>
 
54
#include <zlib.h>
 
55
 
 
56
/* Issues:
 
57
 *
 
58
 * - We embed an image in the stream each time it's composited.  We
 
59
 *   could add generation counters to surfaces and remember the stream
 
60
 *   ID for a particular generation for a particular surface.
 
61
 *
 
62
 * - Backend specific meta data.
 
63
 */
 
64
 
 
65
/*
 
66
 * Page Structure of the Generated PDF:
 
67
 *
 
68
 * Each page requiring fallbacks images contains a knockout group at
 
69
 * the top level. The first operation of the knockout group paints a
 
70
 * group containing all the supported drawing operations. Fallback
 
71
 * images (if any) are painted in the knockout group. This ensures
 
72
 * that fallback images do not composite with any content under the
 
73
 * fallback images.
 
74
 *
 
75
 * Streams:
 
76
 *
 
77
 * This PDF surface has three types of streams:
 
78
 *  - PDF Stream
 
79
 *  - Content Stream
 
80
 *  - Group Stream
 
81
 *
 
82
 * Calling _cairo_output_stream_printf (surface->output, ...) will
 
83
 * write to the currently open stream.
 
84
 *
 
85
 * PDF Stream:
 
86
 *   A PDF Stream may be opened and closed with the following functions:
 
87
 *     _cairo_pdf_surface_open stream ()
 
88
 *     _cairo_pdf_surface_close_stream ()
 
89
 *
 
90
 *   PDF Streams are written directly to the PDF file. They are used for
 
91
 *   fonts, images and patterns.
 
92
 *
 
93
 * Content Stream:
 
94
 *   The Content Stream is opened and closed with the following functions:
 
95
 *     _cairo_pdf_surface_open_content_stream ()
 
96
 *     _cairo_pdf_surface_close_content_stream ()
 
97
 *
 
98
 *   The Content Stream contains the text and graphics operators.
 
99
 *
 
100
 * Group Stream:
 
101
 *   A Group Stream may be opened and closed with the following functions:
 
102
 *     _cairo_pdf_surface_open_group ()
 
103
 *     _cairo_pdf_surface_close_group ()
 
104
 *
 
105
 *   A Group Stream is a Form XObject. It is used for short sequences
 
106
 *   of operators. As the content is very short the group is stored in
 
107
 *   memory until it is closed. This allows some optimization such as
 
108
 *   including the Resource dictionary and stream length inside the
 
109
 *   XObject instead of using an indirect object.
 
110
 */
 
111
 
 
112
typedef struct _cairo_pdf_object {
 
113
    long offset;
 
114
} cairo_pdf_object_t;
 
115
 
 
116
typedef struct _cairo_pdf_font {
 
117
    unsigned int font_id;
 
118
    unsigned int subset_id;
 
119
    cairo_pdf_resource_t subset_resource;
 
120
} cairo_pdf_font_t;
 
121
 
 
122
typedef struct _cairo_pdf_rgb_linear_function {
 
123
    cairo_pdf_resource_t resource;
 
124
    double               color1[3];
 
125
    double               color2[3];
 
126
} cairo_pdf_rgb_linear_function_t;
 
127
 
 
128
typedef struct _cairo_pdf_alpha_linear_function {
 
129
    cairo_pdf_resource_t resource;
 
130
    double               alpha1;
 
131
    double               alpha2;
 
132
} cairo_pdf_alpha_linear_function_t;
 
133
 
 
134
static cairo_pdf_resource_t
 
135
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
 
136
 
 
137
static void
 
138
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
 
139
 
 
140
static void
 
141
_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
 
142
 
 
143
static cairo_status_t
 
144
_cairo_pdf_surface_add_font (unsigned int        font_id,
 
145
                             unsigned int        subset_id,
 
146
                             void               *closure);
 
147
 
 
148
static void
 
149
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
 
150
 
 
151
static cairo_status_t
 
152
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t     *surface,
 
153
                                cairo_pdf_resource_t    *resource,
 
154
                                cairo_bool_t             compressed,
 
155
                                const char              *fmt,
 
156
                                ...) CAIRO_PRINTF_FORMAT(4, 5);
 
157
static cairo_status_t
 
158
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t    *surface);
 
159
 
 
160
static cairo_status_t
 
161
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
 
162
 
 
163
static void
 
164
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
 
165
 
 
166
static cairo_pdf_resource_t
 
167
_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface);
 
168
 
 
169
static cairo_pdf_resource_t
 
170
_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface);
 
171
 
 
172
static long
 
173
_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
 
174
 
 
175
static cairo_status_t
 
176
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
 
177
 
 
178
static cairo_status_t
 
179
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
 
180
 
 
181
static const cairo_surface_backend_t cairo_pdf_surface_backend;
 
182
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
 
183
 
 
184
static cairo_pdf_resource_t
 
185
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
 
186
{
 
187
    cairo_pdf_resource_t resource;
 
188
    cairo_status_t status;
 
189
    cairo_pdf_object_t object;
 
190
 
 
191
    object.offset = _cairo_output_stream_get_position (surface->output);
 
192
 
 
193
    status = _cairo_array_append (&surface->objects, &object);
 
194
    if (status) {
 
195
        resource.id = 0;
 
196
        return resource;
 
197
    }
 
198
 
 
199
    resource = surface->next_available_resource;
 
200
    surface->next_available_resource.id++;
 
201
 
 
202
    return resource;
 
203
}
 
204
 
 
205
static void
 
206
_cairo_pdf_surface_update_object (cairo_pdf_surface_t   *surface,
 
207
                                  cairo_pdf_resource_t   resource)
 
208
{
 
209
    cairo_pdf_object_t *object;
 
210
 
 
211
    object = _cairo_array_index (&surface->objects, resource.id - 1);
 
212
    object->offset = _cairo_output_stream_get_position (surface->output);
 
213
}
 
214
 
 
215
static void
 
216
_cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
 
217
                                      double              width,
 
218
                                      double              height)
 
219
{
 
220
    surface->width = width;
 
221
    surface->height = height;
 
222
    cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
 
223
    _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
 
224
                                                  &surface->cairo_to_pdf);
 
225
}
 
226
 
 
227
static cairo_surface_t *
 
228
_cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t    *output,
 
229
                                               double                    width,
 
230
                                               double                    height)
 
231
{
 
232
    cairo_pdf_surface_t *surface;
 
233
    cairo_status_t status, status_ignored;
 
234
 
 
235
    surface = malloc (sizeof (cairo_pdf_surface_t));
 
236
    if (surface == NULL) {
 
237
        /* destroy stream on behalf of caller */
 
238
        status = _cairo_output_stream_destroy (output);
 
239
        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
240
    }
 
241
 
 
242
    _cairo_surface_init (&surface->base, &cairo_pdf_surface_backend,
 
243
                         CAIRO_CONTENT_COLOR_ALPHA);
 
244
 
 
245
    surface->output = output;
 
246
    surface->width = width;
 
247
    surface->height = height;
 
248
    cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
 
249
 
 
250
    _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
 
251
    _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
 
252
    _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
 
253
    _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
 
254
    _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
 
255
    _cairo_array_init (&surface->patterns, sizeof (cairo_pdf_pattern_t));
 
256
    _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
 
257
    _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t));
 
258
 
 
259
    _cairo_pdf_group_resources_init (&surface->resources);
 
260
 
 
261
    surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
 
262
    if (! surface->font_subsets) {
 
263
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
264
        goto BAIL0;
 
265
    }
 
266
 
 
267
    surface->next_available_resource.id = 1;
 
268
    surface->pages_resource = _cairo_pdf_surface_new_object (surface);
 
269
    if (surface->pages_resource.id == 0) {
 
270
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
271
        goto BAIL1;
 
272
    }
 
273
 
 
274
    surface->compress_content = TRUE;
 
275
    surface->pdf_stream.active = FALSE;
 
276
    surface->pdf_stream.old_output = NULL;
 
277
    surface->group_stream.active = FALSE;
 
278
    surface->group_stream.stream = NULL;
 
279
    surface->group_stream.mem_stream = NULL;
 
280
 
 
281
    surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
 
282
 
 
283
    surface->force_fallbacks = FALSE;
 
284
    surface->select_pattern_gstate_saved = FALSE;
 
285
    surface->current_pattern_is_solid_color = FALSE;
 
286
 
 
287
    _cairo_pdf_operators_init (&surface->pdf_operators,
 
288
                               surface->output,
 
289
                               &surface->cairo_to_pdf,
 
290
                               surface->font_subsets);
 
291
    _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
 
292
                                                    _cairo_pdf_surface_add_font,
 
293
                                                    surface);
 
294
 
 
295
    /* Document header */
 
296
    _cairo_output_stream_printf (surface->output,
 
297
                                 "%%PDF-1.4\n");
 
298
    _cairo_output_stream_printf (surface->output,
 
299
                                 "%%%c%c%c%c\n", 181, 237, 174, 251);
 
300
 
 
301
    surface->paginated_surface =  _cairo_paginated_surface_create (
 
302
                                          &surface->base,
 
303
                                          CAIRO_CONTENT_COLOR_ALPHA,
 
304
                                          width, height,
 
305
                                          &cairo_pdf_surface_paginated_backend);
 
306
 
 
307
    status = surface->paginated_surface->status;
 
308
    if (status == CAIRO_STATUS_SUCCESS) {
 
309
        /* paginated keeps the only reference to surface now, drop ours */
 
310
        cairo_surface_destroy (&surface->base);
 
311
        return surface->paginated_surface;
 
312
    }
 
313
 
 
314
BAIL1:
 
315
    _cairo_scaled_font_subsets_destroy (surface->font_subsets);
 
316
BAIL0:
 
317
    _cairo_array_fini (&surface->objects);
 
318
    free (surface);
 
319
 
 
320
    /* destroy stream on behalf of caller */
 
321
    status_ignored = _cairo_output_stream_destroy (output);
 
322
 
 
323
    return _cairo_surface_create_in_error (status);
 
324
}
 
325
 
 
326
/**
 
327
 * cairo_pdf_surface_create_for_stream:
 
328
 * @write_func: a #cairo_write_func_t to accept the output data
 
329
 * @closure: the closure argument for @write_func
 
330
 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
 
331
 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
 
332
 *
 
333
 * Creates a PDF surface of the specified size in points to be written
 
334
 * incrementally to the stream represented by @write_func and @closure.
 
335
 *
 
336
 * Return value: a pointer to the newly created surface. The caller
 
337
 * owns the surface and should call cairo_surface_destroy() when done
 
338
 * with it.
 
339
 *
 
340
 * This function always returns a valid pointer, but it will return a
 
341
 * pointer to a "nil" surface if an error such as out of memory
 
342
 * occurs. You can use cairo_surface_status() to check for this.
 
343
 *
 
344
 * Since: 1.2
 
345
 */
 
346
cairo_surface_t *
 
347
cairo_pdf_surface_create_for_stream (cairo_write_func_t          write_func,
 
348
                                     void                       *closure,
 
349
                                     double                      width_in_points,
 
350
                                     double                      height_in_points)
 
351
{
 
352
    cairo_output_stream_t *output;
 
353
 
 
354
    output = _cairo_output_stream_create (write_func, NULL, closure);
 
355
    if (_cairo_output_stream_get_status (output))
 
356
        return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
 
357
 
 
358
    return _cairo_pdf_surface_create_for_stream_internal (output,
 
359
                                                          width_in_points,
 
360
                                                          height_in_points);
 
361
}
 
362
 
 
363
/**
 
364
 * cairo_pdf_surface_create:
 
365
 * @filename: a filename for the PDF output (must be writable)
 
366
 * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
 
367
 * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
 
368
 *
 
369
 * Creates a PDF surface of the specified size in points to be written
 
370
 * to @filename.
 
371
 *
 
372
 * Return value: a pointer to the newly created surface. The caller
 
373
 * owns the surface and should call cairo_surface_destroy() when done
 
374
 * with it.
 
375
 *
 
376
 * This function always returns a valid pointer, but it will return a
 
377
 * pointer to a "nil" surface if an error such as out of memory
 
378
 * occurs. You can use cairo_surface_status() to check for this.
 
379
 *
 
380
 * Since: 1.2
 
381
 **/
 
382
cairo_surface_t *
 
383
cairo_pdf_surface_create (const char            *filename,
 
384
                          double                 width_in_points,
 
385
                          double                 height_in_points)
 
386
{
 
387
    cairo_output_stream_t *output;
 
388
 
 
389
    output = _cairo_output_stream_create_for_filename (filename);
 
390
    if (_cairo_output_stream_get_status (output))
 
391
        return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
 
392
 
 
393
    return _cairo_pdf_surface_create_for_stream_internal (output,
 
394
                                                          width_in_points,
 
395
                                                          height_in_points);
 
396
}
 
397
 
 
398
static cairo_bool_t
 
399
_cairo_surface_is_pdf (cairo_surface_t *surface)
 
400
{
 
401
    return surface->backend == &cairo_pdf_surface_backend;
 
402
}
 
403
 
 
404
/* If the abstract_surface is a paginated surface, and that paginated
 
405
 * surface's target is a pdf_surface, then set pdf_surface to that
 
406
 * target. Otherwise return %CAIRO_STATUS_SURFACE_TYPE_MISMATCH.
 
407
 */
 
408
static cairo_status_t
 
409
_extract_pdf_surface (cairo_surface_t            *surface,
 
410
                      cairo_pdf_surface_t       **pdf_surface)
 
411
{
 
412
    cairo_surface_t *target;
 
413
 
 
414
    if (surface->status)
 
415
        return surface->status;
 
416
 
 
417
    if (! _cairo_surface_is_paginated (surface))
 
418
        return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
419
 
 
420
    target = _cairo_paginated_surface_get_target (surface);
 
421
    if (target->status)
 
422
        return target->status;
 
423
 
 
424
    if (! _cairo_surface_is_pdf (target))
 
425
        return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
426
 
 
427
    *pdf_surface = (cairo_pdf_surface_t *) target;
 
428
 
 
429
    return CAIRO_STATUS_SUCCESS;
 
430
}
 
431
 
 
432
/**
 
433
 * cairo_pdf_surface_set_size:
 
434
 * @surface: a PDF #cairo_surface_t
 
435
 * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
 
436
 * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
 
437
 *
 
438
 * Changes the size of a PDF surface for the current (and
 
439
 * subsequent) pages.
 
440
 *
 
441
 * This function should only be called before any drawing operations
 
442
 * have been performed on the current page. The simplest way to do
 
443
 * this is to call this function immediately after creating the
 
444
 * surface or immediately after completing a page with either
 
445
 * cairo_show_page() or cairo_copy_page().
 
446
 *
 
447
 * Since: 1.2
 
448
 **/
 
449
void
 
450
cairo_pdf_surface_set_size (cairo_surface_t     *surface,
 
451
                            double               width_in_points,
 
452
                            double               height_in_points)
 
453
{
 
454
    cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
 
455
    cairo_status_t status;
 
456
 
 
457
    status = _extract_pdf_surface (surface, &pdf_surface);
 
458
    if (status) {
 
459
        status = _cairo_surface_set_error (surface, status);
 
460
        return;
 
461
    }
 
462
 
 
463
    _cairo_pdf_surface_set_size_internal (pdf_surface,
 
464
                                          width_in_points,
 
465
                                          height_in_points);
 
466
    status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
 
467
                                                width_in_points,
 
468
                                                height_in_points);
 
469
    if (status)
 
470
        status = _cairo_surface_set_error (surface, status);
 
471
}
 
472
 
 
473
static void
 
474
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
 
475
{
 
476
    int i, size;
 
477
    cairo_pdf_pattern_t *pattern;
 
478
    cairo_pdf_smask_group_t *group;
 
479
 
 
480
    size = _cairo_array_num_elements (&surface->patterns);
 
481
    for (i = 0; i < size; i++) {
 
482
        pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->patterns, i);
 
483
        cairo_pattern_destroy (pattern->pattern);
 
484
    }
 
485
    _cairo_array_truncate (&surface->patterns, 0);
 
486
 
 
487
    size = _cairo_array_num_elements (&surface->smask_groups);
 
488
    for (i = 0; i < size; i++) {
 
489
        _cairo_array_copy_element (&surface->smask_groups, i, &group);
 
490
        _cairo_pdf_smask_group_destroy (group);
 
491
    }
 
492
    _cairo_array_truncate (&surface->smask_groups, 0);
 
493
    _cairo_array_truncate (&surface->knockout_group, 0);
 
494
}
 
495
 
 
496
static void
 
497
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
 
498
{
 
499
    _cairo_array_init (&res->alphas, sizeof (double));
 
500
    _cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t));
 
501
    _cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t));
 
502
    _cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t));
 
503
    _cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t));
 
504
}
 
505
 
 
506
static void
 
507
_cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
 
508
{
 
509
    _cairo_array_fini (&res->alphas);
 
510
    _cairo_array_fini (&res->smasks);
 
511
    _cairo_array_fini (&res->patterns);
 
512
    _cairo_array_fini (&res->xobjects);
 
513
    _cairo_array_fini (&res->fonts);
 
514
}
 
515
 
 
516
static void
 
517
_cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
 
518
{
 
519
    _cairo_array_truncate (&res->alphas, 0);
 
520
    _cairo_array_truncate (&res->smasks, 0);
 
521
    _cairo_array_truncate (&res->patterns, 0);
 
522
    _cairo_array_truncate (&res->xobjects, 0);
 
523
    _cairo_array_truncate (&res->fonts, 0);
 
524
}
 
525
 
 
526
static cairo_status_t
 
527
_cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
 
528
                              double               alpha,
 
529
                              int                 *index)
 
530
{
 
531
    int num_alphas, i;
 
532
    double other;
 
533
    cairo_status_t status;
 
534
    cairo_pdf_group_resources_t *res = &surface->resources;
 
535
 
 
536
    num_alphas = _cairo_array_num_elements (&res->alphas);
 
537
    for (i = 0; i < num_alphas; i++) {
 
538
        _cairo_array_copy_element (&res->alphas, i, &other);
 
539
        if (alpha == other) {
 
540
            *index = i;
 
541
            return CAIRO_STATUS_SUCCESS;
 
542
        }
 
543
    }
 
544
 
 
545
    status = _cairo_array_append (&res->alphas, &alpha);
 
546
    if (status)
 
547
        return status;
 
548
 
 
549
    *index = _cairo_array_num_elements (&res->alphas) - 1;
 
550
 
 
551
    return CAIRO_STATUS_SUCCESS;
 
552
}
 
553
 
 
554
static cairo_status_t
 
555
_cairo_pdf_surface_add_smask (cairo_pdf_surface_t  *surface,
 
556
                              cairo_pdf_resource_t  smask)
 
557
{
 
558
    return _cairo_array_append (&(surface->resources.smasks), &smask);
 
559
}
 
560
 
 
561
static cairo_status_t
 
562
_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t  *surface,
 
563
                                cairo_pdf_resource_t  pattern)
 
564
{
 
565
    return _cairo_array_append (&(surface->resources.patterns), &pattern);
 
566
}
 
567
 
 
568
static cairo_status_t
 
569
_cairo_pdf_surface_add_xobject (cairo_pdf_surface_t  *surface,
 
570
                                cairo_pdf_resource_t  xobject)
 
571
{
 
572
    return _cairo_array_append (&(surface->resources.xobjects), &xobject);
 
573
}
 
574
 
 
575
static cairo_status_t
 
576
_cairo_pdf_surface_add_font (unsigned int        font_id,
 
577
                             unsigned int        subset_id,
 
578
                             void               *closure)
 
579
{
 
580
    cairo_pdf_surface_t *surface = closure;
 
581
    cairo_pdf_font_t font;
 
582
    int num_fonts, i;
 
583
    cairo_status_t status;
 
584
    cairo_pdf_group_resources_t *res = &surface->resources;
 
585
 
 
586
    num_fonts = _cairo_array_num_elements (&res->fonts);
 
587
    for (i = 0; i < num_fonts; i++) {
 
588
        _cairo_array_copy_element (&res->fonts, i, &font);
 
589
        if (font.font_id == font_id &&
 
590
            font.subset_id == subset_id)
 
591
            return CAIRO_STATUS_SUCCESS;
 
592
    }
 
593
 
 
594
    num_fonts = _cairo_array_num_elements (&surface->fonts);
 
595
    for (i = 0; i < num_fonts; i++) {
 
596
        _cairo_array_copy_element (&surface->fonts, i, &font);
 
597
        if (font.font_id == font_id &&
 
598
            font.subset_id == subset_id)
 
599
            return _cairo_array_append (&res->fonts, &font);
 
600
    }
 
601
 
 
602
    font.font_id = font_id;
 
603
    font.subset_id = subset_id;
 
604
    font.subset_resource = _cairo_pdf_surface_new_object (surface);
 
605
    if (font.subset_resource.id == 0)
 
606
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
607
 
 
608
    status = _cairo_array_append (&surface->fonts, &font);
 
609
    if (status)
 
610
        return status;
 
611
 
 
612
    return _cairo_array_append (&res->fonts, &font);
 
613
}
 
614
 
 
615
static cairo_pdf_resource_t
 
616
_cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface,
 
617
                                      unsigned int         font_id,
 
618
                                      unsigned int         subset_id)
 
619
{
 
620
    cairo_pdf_font_t font;
 
621
    int num_fonts, i;
 
622
 
 
623
    num_fonts = _cairo_array_num_elements (&surface->fonts);
 
624
    for (i = 0; i < num_fonts; i++) {
 
625
        _cairo_array_copy_element (&surface->fonts, i, &font);
 
626
        if (font.font_id == font_id && font.subset_id == subset_id)
 
627
            return font.subset_resource;
 
628
    }
 
629
 
 
630
    font.subset_resource.id = 0;
 
631
    return font.subset_resource;
 
632
}
 
633
 
 
634
static void
 
635
_cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t         *surface,
 
636
                                         cairo_pdf_group_resources_t *res)
 
637
{
 
638
    int num_alphas, num_smasks, num_resources, i;
 
639
    double alpha;
 
640
    cairo_pdf_resource_t *smask, *pattern, *xobject;
 
641
    cairo_pdf_font_t *font;
 
642
 
 
643
    _cairo_output_stream_printf (surface->output, "<<\n");
 
644
 
 
645
    num_alphas = _cairo_array_num_elements (&res->alphas);
 
646
    num_smasks = _cairo_array_num_elements (&res->smasks);
 
647
    if (num_alphas > 0 || num_smasks > 0) {
 
648
        _cairo_output_stream_printf (surface->output,
 
649
                                     "   /ExtGState <<\n");
 
650
 
 
651
        for (i = 0; i < num_alphas; i++) {
 
652
            _cairo_array_copy_element (&res->alphas, i, &alpha);
 
653
            _cairo_output_stream_printf (surface->output,
 
654
                                         "      /a%d << /CA %f /ca %f >>\n",
 
655
                                         i, alpha, alpha);
 
656
        }
 
657
 
 
658
        for (i = 0; i < num_smasks; i++) {
 
659
            smask = _cairo_array_index (&res->smasks, i);
 
660
            _cairo_output_stream_printf (surface->output,
 
661
                                         "      /s%d %d 0 R\n",
 
662
                                         smask->id, smask->id);
 
663
        }
 
664
 
 
665
        _cairo_output_stream_printf (surface->output,
 
666
                                     "   >>\n");
 
667
    }
 
668
 
 
669
    num_resources = _cairo_array_num_elements (&res->patterns);
 
670
    if (num_resources > 0) {
 
671
        _cairo_output_stream_printf (surface->output,
 
672
                                     "   /Pattern <<");
 
673
        for (i = 0; i < num_resources; i++) {
 
674
            pattern = _cairo_array_index (&res->patterns, i);
 
675
            _cairo_output_stream_printf (surface->output,
 
676
                                         " /p%d %d 0 R",
 
677
                                         pattern->id, pattern->id);
 
678
        }
 
679
 
 
680
        _cairo_output_stream_printf (surface->output,
 
681
                                     " >>\n");
 
682
    }
 
683
 
 
684
    num_resources = _cairo_array_num_elements (&res->xobjects);
 
685
    if (num_resources > 0) {
 
686
        _cairo_output_stream_printf (surface->output,
 
687
                                     "   /XObject <<");
 
688
 
 
689
        for (i = 0; i < num_resources; i++) {
 
690
            xobject = _cairo_array_index (&res->xobjects, i);
 
691
            _cairo_output_stream_printf (surface->output,
 
692
                                         " /x%d %d 0 R",
 
693
                                         xobject->id, xobject->id);
 
694
        }
 
695
 
 
696
        _cairo_output_stream_printf (surface->output,
 
697
                                     " >>\n");
 
698
    }
 
699
 
 
700
    num_resources = _cairo_array_num_elements (&res->fonts);
 
701
    if (num_resources > 0) {
 
702
        _cairo_output_stream_printf (surface->output,"   /Font <<\n");
 
703
        for (i = 0; i < num_resources; i++) {
 
704
            font = _cairo_array_index (&res->fonts, i);
 
705
            _cairo_output_stream_printf (surface->output,
 
706
                                         "      /f-%d-%d %d 0 R\n",
 
707
                                         font->font_id,
 
708
                                         font->subset_id,
 
709
                                         font->subset_resource.id);
 
710
        }
 
711
        _cairo_output_stream_printf (surface->output, "   >>\n");
 
712
    }
 
713
 
 
714
    _cairo_output_stream_printf (surface->output,
 
715
                                 ">>\n");
 
716
}
 
717
 
 
718
static cairo_pdf_smask_group_t *
 
719
_cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t      *surface)
 
720
{
 
721
    cairo_pdf_smask_group_t     *group;
 
722
 
 
723
    group = calloc (1, sizeof (cairo_pdf_smask_group_t));
 
724
    if (group == NULL) {
 
725
        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 
726
        return NULL;
 
727
    }
 
728
 
 
729
    group->group_res = _cairo_pdf_surface_new_object (surface);
 
730
    if (group->group_res.id == 0) {
 
731
        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 
732
        free (group);
 
733
        return NULL;
 
734
    }
 
735
    group->width = surface->width;
 
736
    group->height = surface->height;
 
737
 
 
738
    return group;
 
739
}
 
740
 
 
741
static void
 
742
_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
 
743
{
 
744
    if (group->operation == PDF_FILL || group->operation == PDF_STROKE)
 
745
        _cairo_path_fixed_fini (&group->path);
 
746
    if (group->source)
 
747
        cairo_pattern_destroy (group->source);
 
748
    if (group->mask)
 
749
        cairo_pattern_destroy (group->mask);
 
750
    if (group->utf8)
 
751
        free (group->utf8);
 
752
    if (group->glyphs)
 
753
        free (group->glyphs);
 
754
    if (group->clusters)
 
755
        free (group->clusters);
 
756
    if (group->scaled_font)
 
757
        cairo_scaled_font_destroy (group->scaled_font);
 
758
    free (group);
 
759
}
 
760
 
 
761
static cairo_status_t
 
762
_cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t     *surface,
 
763
                                    cairo_pdf_smask_group_t *group)
 
764
{
 
765
    return _cairo_array_append (&surface->smask_groups, &group);
 
766
}
 
767
 
 
768
static cairo_status_t
 
769
_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t         *surface,
 
770
                                    cairo_pattern_t             *pattern,
 
771
                                    cairo_pdf_resource_t        *pattern_res,
 
772
                                    cairo_pdf_resource_t        *gstate_res)
 
773
{
 
774
    cairo_pdf_pattern_t pdf_pattern;
 
775
    cairo_status_t status;
 
776
 
 
777
    /* Solid colors are emitted into the content stream */
 
778
    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
 
779
        pattern_res->id = 0;
 
780
        gstate_res->id = 0;
 
781
        return CAIRO_STATUS_SUCCESS;
 
782
    }
 
783
 
 
784
    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
 
785
        pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
 
786
    {
 
787
        cairo_gradient_pattern_t *gradient;
 
788
 
 
789
        gradient = (cairo_gradient_pattern_t *) pattern;
 
790
 
 
791
        /* Gradients with zero stops do not produce any output */
 
792
        if (gradient->n_stops == 0)
 
793
            return CAIRO_INT_STATUS_NOTHING_TO_DO;
 
794
 
 
795
        /* Gradients with one stop are the same as solid colors */
 
796
        if (gradient->n_stops == 1) {
 
797
            pattern_res->id = 0;
 
798
            gstate_res->id = 0;
 
799
            return CAIRO_STATUS_SUCCESS;
 
800
        }
 
801
    }
 
802
 
 
803
    pdf_pattern.pattern = cairo_pattern_reference (pattern);
 
804
    pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface);
 
805
    if (pdf_pattern.pattern_res.id == 0) {
 
806
        cairo_pattern_destroy (pattern);
 
807
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
808
    }
 
809
 
 
810
    pdf_pattern.gstate_res.id = 0;
 
811
 
 
812
    /* gradient patterns require an smask object to implement transparency */
 
813
    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
 
814
        pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
 
815
        if (_cairo_pattern_is_opaque (pattern) == FALSE) {
 
816
            pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
 
817
            if (pdf_pattern.gstate_res.id == 0) {
 
818
                cairo_pattern_destroy (pattern);
 
819
                return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
820
            }
 
821
        }
 
822
    }
 
823
 
 
824
    pdf_pattern.width = surface->width;
 
825
    pdf_pattern.height = surface->height;
 
826
    *pattern_res = pdf_pattern.pattern_res;
 
827
    *gstate_res = pdf_pattern.gstate_res;
 
828
 
 
829
    status = _cairo_array_append (&surface->patterns, &pdf_pattern);
 
830
    if (status) {
 
831
        cairo_pattern_destroy (pattern);
 
832
        return status;
 
833
    }
 
834
 
 
835
    return CAIRO_STATUS_SUCCESS;
 
836
}
 
837
 
 
838
static cairo_status_t
 
839
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t     *surface,
 
840
                                cairo_pdf_resource_t    *resource,
 
841
                                cairo_bool_t             compressed,
 
842
                                const char              *fmt,
 
843
                                ...)
 
844
{
 
845
    va_list ap;
 
846
    cairo_pdf_resource_t self, length;
 
847
    cairo_output_stream_t *output = NULL;
 
848
 
 
849
    if (resource) {
 
850
        self = *resource;
 
851
        _cairo_pdf_surface_update_object (surface, self);
 
852
    } else {
 
853
        self = _cairo_pdf_surface_new_object (surface);
 
854
        if (self.id == 0)
 
855
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
856
    }
 
857
 
 
858
    length = _cairo_pdf_surface_new_object (surface);
 
859
    if (length.id == 0)
 
860
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
861
 
 
862
    if (compressed) {
 
863
        output = _cairo_deflate_stream_create (surface->output);
 
864
        if (_cairo_output_stream_get_status (output))
 
865
            return _cairo_output_stream_destroy (output);
 
866
    }
 
867
 
 
868
    surface->pdf_stream.active = TRUE;
 
869
    surface->pdf_stream.self = self;
 
870
    surface->pdf_stream.length = length;
 
871
    surface->pdf_stream.compressed = compressed;
 
872
    surface->current_pattern_is_solid_color = FALSE;
 
873
    _cairo_pdf_operators_reset (&surface->pdf_operators);
 
874
 
 
875
    _cairo_output_stream_printf (surface->output,
 
876
                                 "%d 0 obj\n"
 
877
                                 "<< /Length %d 0 R\n",
 
878
                                 surface->pdf_stream.self.id,
 
879
                                 surface->pdf_stream.length.id);
 
880
    if (compressed)
 
881
        _cairo_output_stream_printf (surface->output,
 
882
                                     "   /Filter /FlateDecode\n");
 
883
 
 
884
    if (fmt != NULL) {
 
885
        va_start (ap, fmt);
 
886
        _cairo_output_stream_vprintf (surface->output, fmt, ap);
 
887
        va_end (ap);
 
888
    }
 
889
 
 
890
    _cairo_output_stream_printf (surface->output,
 
891
                                 ">>\n"
 
892
                                 "stream\n");
 
893
 
 
894
    surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
 
895
 
 
896
    if (compressed) {
 
897
        assert (surface->pdf_stream.old_output == NULL);
 
898
        surface->pdf_stream.old_output = surface->output;
 
899
        surface->output = output;
 
900
        _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
 
901
    }
 
902
 
 
903
    return _cairo_output_stream_get_status (surface->output);
 
904
}
 
905
 
 
906
static cairo_status_t
 
907
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
 
908
{
 
909
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
910
    long length;
 
911
 
 
912
    if (! surface->pdf_stream.active)
 
913
        return CAIRO_STATUS_SUCCESS;
 
914
 
 
915
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
916
    if (status)
 
917
        return status;
 
918
 
 
919
    if (surface->pdf_stream.compressed) {
 
920
        status = _cairo_output_stream_destroy (surface->output);
 
921
        surface->output = surface->pdf_stream.old_output;
 
922
        _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
 
923
        surface->pdf_stream.old_output = NULL;
 
924
        _cairo_output_stream_printf (surface->output,
 
925
                                     "\n");
 
926
    }
 
927
 
 
928
    length = _cairo_output_stream_get_position (surface->output) -
 
929
        surface->pdf_stream.start_offset;
 
930
    _cairo_output_stream_printf (surface->output,
 
931
                                 "endstream\n"
 
932
                                 "endobj\n");
 
933
 
 
934
    _cairo_pdf_surface_update_object (surface,
 
935
                                      surface->pdf_stream.length);
 
936
    _cairo_output_stream_printf (surface->output,
 
937
                                 "%d 0 obj\n"
 
938
                                 "   %ld\n"
 
939
                                 "endobj\n",
 
940
                                 surface->pdf_stream.length.id,
 
941
                                 length);
 
942
 
 
943
    surface->pdf_stream.active = FALSE;
 
944
 
 
945
    if (status == CAIRO_STATUS_SUCCESS)
 
946
        status = _cairo_output_stream_get_status (surface->output);
 
947
 
 
948
    return status;
 
949
}
 
950
 
 
951
static void
 
952
_cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t         *surface,
 
953
                                        cairo_output_stream_t       *mem_stream,
 
954
                                        cairo_pdf_resource_t         resource,
 
955
                                        cairo_pdf_group_resources_t *resources,
 
956
                                        cairo_bool_t                 is_knockout_group)
 
957
{
 
958
    _cairo_pdf_surface_update_object (surface, resource);
 
959
 
 
960
    _cairo_output_stream_printf (surface->output,
 
961
                                 "%d 0 obj\n"
 
962
                                 "<< /Type /XObject\n"
 
963
                                 "   /Length %d\n",
 
964
                                 resource.id,
 
965
                                 _cairo_memory_stream_length (mem_stream));
 
966
 
 
967
    if (surface->compress_content) {
 
968
        _cairo_output_stream_printf (surface->output,
 
969
                                     "   /Filter /FlateDecode\n");
 
970
    }
 
971
 
 
972
    _cairo_output_stream_printf (surface->output,
 
973
                                 "   /Subtype /Form\n"
 
974
                                 "   /BBox [ 0 0 %f %f ]\n"
 
975
                                 "   /Group <<\n"
 
976
                                 "      /Type /Group\n"
 
977
                                 "      /S /Transparency\n"
 
978
                                 "      /CS /DeviceRGB\n",
 
979
                                 surface->width,
 
980
                                 surface->height);
 
981
 
 
982
    if (is_knockout_group)
 
983
        _cairo_output_stream_printf (surface->output,
 
984
                                     "      /K true\n");
 
985
 
 
986
    _cairo_output_stream_printf (surface->output,
 
987
                                 "   >>\n"
 
988
                                 "   /Resources\n");
 
989
    _cairo_pdf_surface_emit_group_resources (surface, resources);
 
990
    _cairo_output_stream_printf (surface->output,
 
991
                                 ">>\n"
 
992
                                 "stream\n");
 
993
    _cairo_memory_stream_copy (mem_stream, surface->output);
 
994
    _cairo_output_stream_printf (surface->output,
 
995
                                 "endstream\n"
 
996
                                 "endobj\n");
 
997
}
 
998
 
 
999
static cairo_status_t
 
1000
_cairo_pdf_surface_open_group (cairo_pdf_surface_t  *surface,
 
1001
                               cairo_pdf_resource_t *resource)
 
1002
{
 
1003
    cairo_status_t status;
 
1004
 
 
1005
    assert (surface->pdf_stream.active == FALSE);
 
1006
    assert (surface->group_stream.active == FALSE);
 
1007
 
 
1008
    surface->group_stream.active = TRUE;
 
1009
    surface->current_pattern_is_solid_color = FALSE;
 
1010
    _cairo_pdf_operators_reset (&surface->pdf_operators);
 
1011
 
 
1012
    surface->group_stream.mem_stream = _cairo_memory_stream_create ();
 
1013
 
 
1014
    if (surface->compress_content) {
 
1015
        surface->group_stream.stream =
 
1016
            _cairo_deflate_stream_create (surface->group_stream.mem_stream);
 
1017
    } else {
 
1018
        surface->group_stream.stream = surface->group_stream.mem_stream;
 
1019
    }
 
1020
    status = _cairo_output_stream_get_status (surface->group_stream.stream);
 
1021
 
 
1022
    surface->group_stream.old_output = surface->output;
 
1023
    surface->output = surface->group_stream.stream;
 
1024
    _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
 
1025
    _cairo_pdf_group_resources_clear (&surface->resources);
 
1026
 
 
1027
    if (resource) {
 
1028
        surface->group_stream.resource = *resource;
 
1029
    } else {
 
1030
        surface->group_stream.resource = _cairo_pdf_surface_new_object (surface);
 
1031
        if (surface->group_stream.resource.id == 0)
 
1032
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1033
    }
 
1034
    surface->group_stream.is_knockout = FALSE;
 
1035
 
 
1036
    return status;
 
1037
}
 
1038
 
 
1039
static cairo_status_t
 
1040
_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t  *surface)
 
1041
{
 
1042
    cairo_status_t status;
 
1043
 
 
1044
    status = _cairo_pdf_surface_open_group (surface, NULL);
 
1045
    if (status)
 
1046
        return status;
 
1047
 
 
1048
    surface->group_stream.is_knockout = TRUE;
 
1049
 
 
1050
    return CAIRO_STATUS_SUCCESS;
 
1051
}
 
1052
 
 
1053
static cairo_status_t
 
1054
_cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
 
1055
                                cairo_pdf_resource_t *group)
 
1056
{
 
1057
    cairo_status_t status = CAIRO_STATUS_SUCCESS, status2;
 
1058
 
 
1059
    assert (surface->pdf_stream.active == FALSE);
 
1060
    assert (surface->group_stream.active == TRUE);
 
1061
 
 
1062
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
1063
    if (status)
 
1064
        return status;
 
1065
 
 
1066
    if (surface->compress_content) {
 
1067
        status = _cairo_output_stream_destroy (surface->group_stream.stream);
 
1068
        surface->group_stream.stream = NULL;
 
1069
 
 
1070
        _cairo_output_stream_printf (surface->group_stream.mem_stream,
 
1071
                                     "\n");
 
1072
    }
 
1073
    surface->output = surface->group_stream.old_output;
 
1074
    _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
 
1075
    surface->group_stream.active = FALSE;
 
1076
    _cairo_pdf_surface_write_memory_stream (surface,
 
1077
                                            surface->group_stream.mem_stream,
 
1078
                                            surface->group_stream.resource,
 
1079
                                            &surface->resources,
 
1080
                                            surface->group_stream.is_knockout);
 
1081
    if (group)
 
1082
        *group = surface->group_stream.resource;
 
1083
 
 
1084
    status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
 
1085
    if (status == CAIRO_STATUS_SUCCESS)
 
1086
        status = status2;
 
1087
 
 
1088
    surface->group_stream.mem_stream = NULL;
 
1089
    surface->group_stream.stream = NULL;
 
1090
 
 
1091
    return status;
 
1092
}
 
1093
 
 
1094
static cairo_status_t
 
1095
_cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t  *surface,
 
1096
                                        cairo_bool_t          is_form)
 
1097
{
 
1098
    cairo_status_t status;
 
1099
 
 
1100
    assert (surface->pdf_stream.active == FALSE);
 
1101
    assert (surface->group_stream.active == FALSE);
 
1102
 
 
1103
    surface->content_resources = _cairo_pdf_surface_new_object (surface);
 
1104
    if (surface->content_resources.id == 0)
 
1105
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1106
 
 
1107
    if (is_form) {
 
1108
        status =
 
1109
            _cairo_pdf_surface_open_stream (surface,
 
1110
                                            NULL,
 
1111
                                            surface->compress_content,
 
1112
                                            "   /Type /XObject\n"
 
1113
                                            "   /Subtype /Form\n"
 
1114
                                            "   /BBox [ 0 0 %f %f ]\n"
 
1115
                                            "   /Group <<\n"
 
1116
                                            "      /Type /Group\n"
 
1117
                                            "      /S /Transparency\n"
 
1118
                                            "      /CS /DeviceRGB\n"
 
1119
                                            "   >>\n"
 
1120
                                            "   /Resources %d 0 R\n",
 
1121
                                            surface->width,
 
1122
                                            surface->height,
 
1123
                                            surface->content_resources.id);
 
1124
    } else {
 
1125
        status =
 
1126
            _cairo_pdf_surface_open_stream (surface,
 
1127
                                            NULL,
 
1128
                                            surface->compress_content,
 
1129
                                            NULL);
 
1130
    }
 
1131
    if (status)
 
1132
        return status;
 
1133
 
 
1134
    surface->content = surface->pdf_stream.self;
 
1135
 
 
1136
    _cairo_output_stream_printf (surface->output, "q\n");
 
1137
 
 
1138
    return _cairo_output_stream_get_status (surface->output);
 
1139
}
 
1140
 
 
1141
static cairo_status_t
 
1142
_cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
 
1143
{
 
1144
    cairo_status_t status;
 
1145
 
 
1146
    assert (surface->pdf_stream.active == TRUE);
 
1147
    assert (surface->group_stream.active == FALSE);
 
1148
 
 
1149
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
1150
    if (status)
 
1151
        return status;
 
1152
 
 
1153
    _cairo_output_stream_printf (surface->output, "Q\n");
 
1154
    status = _cairo_pdf_surface_close_stream (surface);
 
1155
    if (status)
 
1156
        return status;
 
1157
 
 
1158
    _cairo_pdf_surface_update_object (surface, surface->content_resources);
 
1159
    _cairo_output_stream_printf (surface->output,
 
1160
                                 "%d 0 obj\n",
 
1161
                                 surface->content_resources.id);
 
1162
    _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
 
1163
    _cairo_output_stream_printf (surface->output,
 
1164
                                 "endobj\n");
 
1165
 
 
1166
    return _cairo_output_stream_get_status (surface->output);
 
1167
}
 
1168
 
 
1169
static cairo_surface_t *
 
1170
_cairo_pdf_surface_create_similar (void                 *abstract_surface,
 
1171
                                   cairo_content_t       content,
 
1172
                                   int                   width,
 
1173
                                   int                   height)
 
1174
{
 
1175
    return _cairo_meta_surface_create (content, width, height);
 
1176
}
 
1177
 
 
1178
static cairo_status_t
 
1179
_cairo_pdf_surface_finish (void *abstract_surface)
 
1180
{
 
1181
    cairo_pdf_surface_t *surface = abstract_surface;
 
1182
    long offset;
 
1183
    cairo_pdf_resource_t info, catalog;
 
1184
    cairo_status_t status, status2;
 
1185
 
 
1186
    status = surface->base.status;
 
1187
    if (status == CAIRO_STATUS_SUCCESS)
 
1188
        status = _cairo_pdf_surface_emit_font_subsets (surface);
 
1189
 
 
1190
    _cairo_pdf_surface_write_pages (surface);
 
1191
 
 
1192
    info = _cairo_pdf_surface_write_info (surface);
 
1193
    if (info.id == 0 && status == CAIRO_STATUS_SUCCESS)
 
1194
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1195
 
 
1196
    catalog = _cairo_pdf_surface_write_catalog (surface);
 
1197
    if (catalog.id == 0 && status == CAIRO_STATUS_SUCCESS)
 
1198
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1199
 
 
1200
    offset = _cairo_pdf_surface_write_xref (surface);
 
1201
 
 
1202
    _cairo_output_stream_printf (surface->output,
 
1203
                                 "trailer\n"
 
1204
                                 "<< /Size %d\n"
 
1205
                                 "   /Root %d 0 R\n"
 
1206
                                 "   /Info %d 0 R\n"
 
1207
                                 ">>\n",
 
1208
                                 surface->next_available_resource.id,
 
1209
                                 catalog.id,
 
1210
                                 info.id);
 
1211
 
 
1212
    _cairo_output_stream_printf (surface->output,
 
1213
                                 "startxref\n"
 
1214
                                 "%ld\n"
 
1215
                                 "%%%%EOF\n",
 
1216
                                 offset);
 
1217
 
 
1218
    status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
 
1219
    /* pdf_operators has already been flushed when the last stream was
 
1220
     * closed so we should never be writing anything here. */
 
1221
    assert(status2 == CAIRO_STATUS_SUCCESS);
 
1222
 
 
1223
    /* close any active streams still open due to fatal errors */
 
1224
    status2 = _cairo_pdf_surface_close_stream (surface);
 
1225
    if (status == CAIRO_STATUS_SUCCESS)
 
1226
        status = status2;
 
1227
 
 
1228
    if (surface->group_stream.stream != NULL) {
 
1229
        status2 = _cairo_output_stream_destroy (surface->group_stream.stream);
 
1230
        if (status == CAIRO_STATUS_SUCCESS)
 
1231
            status = status2;
 
1232
    }
 
1233
    if (surface->group_stream.mem_stream != NULL) {
 
1234
        status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
 
1235
        if (status == CAIRO_STATUS_SUCCESS)
 
1236
            status = status2;
 
1237
    }
 
1238
    if (surface->pdf_stream.active)
 
1239
        surface->output = surface->pdf_stream.old_output;
 
1240
    if (surface->group_stream.active)
 
1241
        surface->output = surface->group_stream.old_output;
 
1242
 
 
1243
    /* and finish the pdf surface */
 
1244
    status2 = _cairo_output_stream_destroy (surface->output);
 
1245
    if (status == CAIRO_STATUS_SUCCESS)
 
1246
        status = status2;
 
1247
 
 
1248
    _cairo_pdf_surface_clear (surface);
 
1249
    _cairo_pdf_group_resources_fini (&surface->resources);
 
1250
 
 
1251
    _cairo_array_fini (&surface->objects);
 
1252
    _cairo_array_fini (&surface->pages);
 
1253
    _cairo_array_fini (&surface->rgb_linear_functions);
 
1254
    _cairo_array_fini (&surface->alpha_linear_functions);
 
1255
    _cairo_array_fini (&surface->patterns);
 
1256
    _cairo_array_fini (&surface->smask_groups);
 
1257
    _cairo_array_fini (&surface->fonts);
 
1258
    _cairo_array_fini (&surface->knockout_group);
 
1259
 
 
1260
    if (surface->font_subsets) {
 
1261
        _cairo_scaled_font_subsets_destroy (surface->font_subsets);
 
1262
        surface->font_subsets = NULL;
 
1263
    }
 
1264
 
 
1265
    return status;
 
1266
}
 
1267
 
 
1268
static cairo_int_status_t
 
1269
_cairo_pdf_surface_start_page (void *abstract_surface)
 
1270
{
 
1271
    cairo_pdf_surface_t *surface = abstract_surface;
 
1272
 
 
1273
    _cairo_pdf_group_resources_clear (&surface->resources);
 
1274
 
 
1275
    return CAIRO_STATUS_SUCCESS;
 
1276
}
 
1277
 
 
1278
static cairo_int_status_t
 
1279
_cairo_pdf_surface_has_fallback_images (void            *abstract_surface,
 
1280
                                        cairo_bool_t     has_fallbacks)
 
1281
{
 
1282
    cairo_status_t status;
 
1283
    cairo_pdf_surface_t *surface = abstract_surface;
 
1284
 
 
1285
    surface->has_fallback_images = has_fallbacks;
 
1286
    status = _cairo_pdf_surface_open_content_stream (surface, has_fallbacks);
 
1287
    if (status)
 
1288
        return status;
 
1289
 
 
1290
    return CAIRO_STATUS_SUCCESS;
 
1291
}
 
1292
 
 
1293
/* Emit alpha channel from the image into the given data, providing
 
1294
 * an id that can be used to reference the resulting SMask object.
 
1295
 *
 
1296
 * In the case that the alpha channel happens to be all opaque, then
 
1297
 * no SMask object will be emitted and *id_ret will be set to 0.
 
1298
 */
 
1299
static cairo_status_t
 
1300
_cairo_pdf_surface_emit_smask (cairo_pdf_surface_t      *surface,
 
1301
                               cairo_image_surface_t    *image,
 
1302
                               cairo_pdf_resource_t     *stream_ret)
 
1303
{
 
1304
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
1305
    char *alpha;
 
1306
    unsigned long alpha_size;
 
1307
    uint32_t *pixel32;
 
1308
    uint8_t *pixel8;
 
1309
    int i, x, y;
 
1310
    cairo_bool_t opaque;
 
1311
    uint8_t a;
 
1312
 
 
1313
    /* This is the only image format we support, which simplifies things. */
 
1314
    assert (image->format == CAIRO_FORMAT_ARGB32 ||
 
1315
            image->format == CAIRO_FORMAT_A8 ||
 
1316
            image->format == CAIRO_FORMAT_A1 );
 
1317
 
 
1318
    stream_ret->id = 0;
 
1319
 
 
1320
    if (image->format == CAIRO_FORMAT_A1) {
 
1321
        alpha_size = (image->width + 7) / 8 * image->height;
 
1322
        alpha = _cairo_malloc_ab ((image->width+7) / 8, image->height);
 
1323
    } else {
 
1324
        alpha_size = image->height * image->width;
 
1325
        alpha = _cairo_malloc_ab (image->height, image->width);
 
1326
    }
 
1327
 
 
1328
    if (alpha == NULL) {
 
1329
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1330
        goto CLEANUP;
 
1331
    }
 
1332
 
 
1333
    opaque = TRUE;
 
1334
    i = 0;
 
1335
    for (y = 0; y < image->height; y++) {
 
1336
        if (image->format == CAIRO_FORMAT_ARGB32) {
 
1337
            pixel32 = (uint32_t *) (image->data + y * image->stride);
 
1338
 
 
1339
            for (x = 0; x < image->width; x++, pixel32++) {
 
1340
                a = (*pixel32 & 0xff000000) >> 24;
 
1341
                alpha[i++] = a;
 
1342
                if (a != 0xff)
 
1343
                    opaque = FALSE;
 
1344
            }
 
1345
        } else if (image->format == CAIRO_FORMAT_A8){
 
1346
            pixel8 = (uint8_t *) (image->data + y * image->stride);
 
1347
 
 
1348
            for (x = 0; x < image->width; x++, pixel8++) {
 
1349
                a = *pixel8;
 
1350
                alpha[i++] = a;
 
1351
                if (a != 0xff)
 
1352
                    opaque = FALSE;
 
1353
            }
 
1354
        } else { /* image->format == CAIRO_FORMAT_A1 */
 
1355
            pixel8 = (uint8_t *) (image->data + y * image->stride);
 
1356
 
 
1357
            for (x = 0; x < (image->width + 7) / 8; x++, pixel8++) {
 
1358
                a = *pixel8;
 
1359
                a = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a);
 
1360
                alpha[i++] = a;
 
1361
                if (a != 0xff)
 
1362
                    opaque = FALSE;
 
1363
            }
 
1364
        }
 
1365
    }
 
1366
 
 
1367
    /* Bail out without emitting smask if it's all opaque. */
 
1368
    if (opaque)
 
1369
        goto CLEANUP_ALPHA;
 
1370
 
 
1371
    status = _cairo_pdf_surface_open_stream (surface,
 
1372
                                             NULL,
 
1373
                                             TRUE,
 
1374
                                             "   /Type /XObject\n"
 
1375
                                             "   /Subtype /Image\n"
 
1376
                                             "   /Width %d\n"
 
1377
                                             "   /Height %d\n"
 
1378
                                             "   /ColorSpace /DeviceGray\n"
 
1379
                                             "   /BitsPerComponent %d\n",
 
1380
                                             image->width, image->height,
 
1381
                                             image->format == CAIRO_FORMAT_A1 ? 1 : 8);
 
1382
    if (status)
 
1383
        goto CLEANUP_ALPHA;
 
1384
 
 
1385
    *stream_ret = surface->pdf_stream.self;
 
1386
    _cairo_output_stream_write (surface->output, alpha, alpha_size);
 
1387
    status = _cairo_pdf_surface_close_stream (surface);
 
1388
 
 
1389
 CLEANUP_ALPHA:
 
1390
    free (alpha);
 
1391
 CLEANUP:
 
1392
    return status;
 
1393
}
 
1394
 
 
1395
/* Emit image data into the given surface, providing a resource that
 
1396
 * can be used to reference the data in image_ret. */
 
1397
static cairo_status_t
 
1398
_cairo_pdf_surface_emit_image (cairo_pdf_surface_t   *surface,
 
1399
                               cairo_image_surface_t *image,
 
1400
                               cairo_pdf_resource_t  *image_ret)
 
1401
{
 
1402
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
1403
    char *rgb;
 
1404
    unsigned long rgb_size;
 
1405
    uint32_t *pixel;
 
1406
    int i, x, y;
 
1407
    cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
 
1408
    cairo_bool_t need_smask;
 
1409
 
 
1410
    /* These are the only image formats we currently support, (which
 
1411
     * makes things a lot simpler here). This is enforced through
 
1412
     * _cairo_pdf_surface_analyze_operation which only accept source surfaces of
 
1413
     * CONTENT_COLOR or CONTENT_COLOR_ALPHA.
 
1414
     */
 
1415
    assert (image->format == CAIRO_FORMAT_RGB24 ||
 
1416
            image->format == CAIRO_FORMAT_ARGB32 ||
 
1417
            image->format == CAIRO_FORMAT_A8 ||
 
1418
            image->format == CAIRO_FORMAT_A1);
 
1419
 
 
1420
    rgb_size = image->height * image->width * 3;
 
1421
    rgb = _cairo_malloc_abc (image->width, image->height, 3);
 
1422
    if (rgb == NULL) {
 
1423
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1424
        goto CLEANUP;
 
1425
    }
 
1426
 
 
1427
    i = 0;
 
1428
    for (y = 0; y < image->height; y++) {
 
1429
        pixel = (uint32_t *) (image->data + y * image->stride);
 
1430
 
 
1431
        for (x = 0; x < image->width; x++, pixel++) {
 
1432
            /* XXX: We're un-premultiplying alpha here. My reading of the PDF
 
1433
             * specification suggests that we should be able to avoid having
 
1434
             * to do this by filling in the SMask's Matte dictionary
 
1435
             * appropriately, but my attempts to do that so far have
 
1436
             * failed. */
 
1437
            if (image->format == CAIRO_FORMAT_ARGB32) {
 
1438
                uint8_t a;
 
1439
                a = (*pixel & 0xff000000) >> 24;
 
1440
                if (a == 0) {
 
1441
                    rgb[i++] = 0;
 
1442
                    rgb[i++] = 0;
 
1443
                    rgb[i++] = 0;
 
1444
                } else {
 
1445
                    rgb[i++] = (((*pixel & 0xff0000) >> 16) * 255 + a / 2) / a;
 
1446
                    rgb[i++] = (((*pixel & 0x00ff00) >>  8) * 255 + a / 2) / a;
 
1447
                    rgb[i++] = (((*pixel & 0x0000ff) >>  0) * 255 + a / 2) / a;
 
1448
                }
 
1449
            } else if (image->format == CAIRO_FORMAT_RGB24) {
 
1450
                rgb[i++] = (*pixel & 0x00ff0000) >> 16;
 
1451
                rgb[i++] = (*pixel & 0x0000ff00) >>  8;
 
1452
                rgb[i++] = (*pixel & 0x000000ff) >>  0;
 
1453
            } else {
 
1454
                rgb[i++] = 0;
 
1455
                rgb[i++] = 0;
 
1456
                rgb[i++] = 0;
 
1457
            }
 
1458
        }
 
1459
    }
 
1460
 
 
1461
    need_smask = FALSE;
 
1462
    if (image->format == CAIRO_FORMAT_ARGB32 ||
 
1463
        image->format == CAIRO_FORMAT_A8 ||
 
1464
        image->format == CAIRO_FORMAT_A1) {
 
1465
        status = _cairo_pdf_surface_emit_smask (surface, image, &smask);
 
1466
        if (status)
 
1467
            goto CLEANUP_RGB;
 
1468
 
 
1469
        if (smask.id)
 
1470
            need_smask = TRUE;
 
1471
    }
 
1472
 
 
1473
#define IMAGE_DICTIONARY        "   /Type /XObject\n"           \
 
1474
                                "   /Subtype /Image\n"  \
 
1475
                                "   /Width %d\n"                \
 
1476
                                "   /Height %d\n"               \
 
1477
                                "   /ColorSpace /DeviceRGB\n"   \
 
1478
                                "   /BitsPerComponent 8\n"
 
1479
 
 
1480
    if (need_smask)
 
1481
        status = _cairo_pdf_surface_open_stream (surface,
 
1482
                                                 NULL,
 
1483
                                                 TRUE,
 
1484
                                                 IMAGE_DICTIONARY
 
1485
                                                 "   /SMask %d 0 R\n",
 
1486
                                                 image->width, image->height,
 
1487
                                                 smask.id);
 
1488
    else
 
1489
        status = _cairo_pdf_surface_open_stream (surface,
 
1490
                                                 NULL,
 
1491
                                                 TRUE,
 
1492
                                                 IMAGE_DICTIONARY,
 
1493
                                                 image->width, image->height);
 
1494
    if (status)
 
1495
        goto CLEANUP_RGB;
 
1496
 
 
1497
#undef IMAGE_DICTIONARY
 
1498
 
 
1499
    *image_ret = surface->pdf_stream.self;
 
1500
    _cairo_output_stream_write (surface->output, rgb, rgb_size);
 
1501
    status = _cairo_pdf_surface_close_stream (surface);
 
1502
 
 
1503
CLEANUP_RGB:
 
1504
    free (rgb);
 
1505
CLEANUP:
 
1506
    return status;
 
1507
}
 
1508
 
 
1509
static cairo_status_t
 
1510
_cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
 
1511
                                       cairo_surface_pattern_t *pattern,
 
1512
                                       cairo_pdf_resource_t    *resource,
 
1513
                                       int                     *width,
 
1514
                                       int                     *height)
 
1515
{
 
1516
    cairo_image_surface_t *image;
 
1517
    void *image_extra;
 
1518
    cairo_status_t status;
 
1519
 
 
1520
    status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
 
1521
    if (status)
 
1522
        goto BAIL;
 
1523
 
 
1524
    status = _cairo_pdf_surface_emit_image (surface, image, resource);
 
1525
    if (status)
 
1526
        goto BAIL;
 
1527
 
 
1528
    *width = image->width;
 
1529
    *height = image->height;
 
1530
 
 
1531
BAIL:
 
1532
    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
 
1533
 
 
1534
    return status;
 
1535
}
 
1536
 
 
1537
static cairo_status_t
 
1538
_cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t  *surface,
 
1539
                                      cairo_surface_t      *meta_surface,
 
1540
                                      cairo_pdf_resource_t *resource)
 
1541
{
 
1542
    double old_width, old_height;
 
1543
    cairo_paginated_mode_t old_paginated_mode;
 
1544
    cairo_clip_t *old_clip;
 
1545
    cairo_rectangle_int_t meta_extents;
 
1546
    cairo_status_t status;
 
1547
    int alpha = 0;
 
1548
 
 
1549
    status = _cairo_surface_get_extents (meta_surface, &meta_extents);
 
1550
    if (status)
 
1551
        return status;
 
1552
 
 
1553
    old_width = surface->width;
 
1554
    old_height = surface->height;
 
1555
    old_paginated_mode = surface->paginated_mode;
 
1556
    old_clip = _cairo_surface_get_clip (&surface->base);
 
1557
    _cairo_pdf_surface_set_size_internal (surface,
 
1558
                                          meta_extents.width,
 
1559
                                          meta_extents.height);
 
1560
    /* Patterns are emitted after fallback images. The paginated mode
 
1561
     * needs to be set to _RENDER while the meta surface is replayed
 
1562
     * back to this surface.
 
1563
     */
 
1564
    surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
 
1565
    _cairo_pdf_group_resources_clear (&surface->resources);
 
1566
    status = _cairo_pdf_surface_open_content_stream (surface, TRUE);
 
1567
    if (status)
 
1568
        return status;
 
1569
 
 
1570
    *resource = surface->content;
 
1571
    if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
 
1572
        status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
 
1573
        if (status)
 
1574
            return status;
 
1575
 
 
1576
        _cairo_output_stream_printf (surface->output,
 
1577
                                     "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
 
1578
                                     alpha,
 
1579
                                     surface->width,
 
1580
                                     surface->height);
 
1581
    }
 
1582
 
 
1583
    status = _cairo_meta_surface_replay_region (meta_surface, &surface->base,
 
1584
                                                CAIRO_META_REGION_NATIVE);
 
1585
    assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
 
1586
    if (status)
 
1587
        return status;
 
1588
 
 
1589
    status = _cairo_surface_set_clip (&surface->base, old_clip);
 
1590
    if (status)
 
1591
        return status;
 
1592
 
 
1593
    status = _cairo_pdf_surface_close_content_stream (surface);
 
1594
 
 
1595
    _cairo_pdf_surface_set_size_internal (surface,
 
1596
                                          old_width,
 
1597
                                          old_height);
 
1598
    surface->paginated_mode = old_paginated_mode;
 
1599
 
 
1600
    return status;
 
1601
}
 
1602
 
 
1603
static cairo_status_t
 
1604
_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t    *surface,
 
1605
                                         cairo_pdf_pattern_t    *pdf_pattern)
 
1606
{
 
1607
    cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
 
1608
    cairo_status_t status;
 
1609
    cairo_pdf_resource_t pattern_resource = {0}; /* squelch bogus compiler warning */
 
1610
    cairo_matrix_t cairo_p2d, pdf_p2d;
 
1611
    cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
 
1612
    double xstep, ystep;
 
1613
    cairo_rectangle_int_t surface_extents;
 
1614
    int pattern_width = 0; /* squelch bogus compiler warning */
 
1615
    int pattern_height = 0; /* squelch bogus compiler warning */
 
1616
    int bbox_x, bbox_y;
 
1617
    char draw_surface[200];
 
1618
 
 
1619
    if (_cairo_surface_is_meta (pattern->surface)) {
 
1620
        cairo_surface_t *meta_surface = pattern->surface;
 
1621
        cairo_rectangle_int_t pattern_extents;
 
1622
 
 
1623
        status = _cairo_pdf_surface_emit_meta_surface (surface,
 
1624
                                                       meta_surface,
 
1625
                                                       &pattern_resource);
 
1626
        if (status)
 
1627
            return status;
 
1628
 
 
1629
        status = _cairo_surface_get_extents (meta_surface, &pattern_extents);
 
1630
        if (status)
 
1631
            return status;
 
1632
 
 
1633
        pattern_width = pattern_extents.width;
 
1634
        pattern_height = pattern_extents.height;
 
1635
    } else {
 
1636
        status = _cairo_pdf_surface_emit_image_surface (surface,
 
1637
                                                        pattern,
 
1638
                                                        &pattern_resource,
 
1639
                                                        &pattern_width,
 
1640
                                                        &pattern_height);
 
1641
        if (status)
 
1642
            return status;
 
1643
    }
 
1644
 
 
1645
    status = _cairo_surface_get_extents (&surface->base, &surface_extents);
 
1646
    if (status)
 
1647
        return status;
 
1648
 
 
1649
    bbox_x = pattern_width;
 
1650
    bbox_y = pattern_height;
 
1651
    switch (extend) {
 
1652
        /* We implement EXTEND_PAD like EXTEND_NONE for now */
 
1653
    case CAIRO_EXTEND_PAD:
 
1654
    case CAIRO_EXTEND_NONE:
 
1655
    {
 
1656
        /* In PS/PDF, (as far as I can tell), all patterns are
 
1657
         * repeating. So we support cairo's EXTEND_NONE semantics
 
1658
         * by setting the repeat step size to a size large enough
 
1659
         * to guarantee that no more than a single occurrence will
 
1660
         * be visible.
 
1661
         *
 
1662
         * First, map the surface extents into pattern space (since
 
1663
         * xstep and ystep are in pattern space).  Then use an upper
 
1664
         * bound on the length of the diagonal of the pattern image
 
1665
         * and the surface as repeat size.  This guarantees to never
 
1666
         * repeat visibly.
 
1667
         */
 
1668
        double x1 = 0.0, y1 = 0.0;
 
1669
        double x2 = surface->width, y2 = surface->height;
 
1670
        _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
 
1671
                                              &x1, &y1, &x2, &y2,
 
1672
                                              NULL);
 
1673
 
 
1674
        /* Rather than computing precise bounds of the union, just
 
1675
         * add the surface extents unconditionally. We only
 
1676
         * required an answer that's large enough, we don't really
 
1677
         * care if it's not as tight as possible.*/
 
1678
        xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
 
1679
                              pattern_width + pattern_height);
 
1680
    }
 
1681
    break;
 
1682
    case CAIRO_EXTEND_REPEAT:
 
1683
        xstep = pattern_width;
 
1684
        ystep = pattern_height;
 
1685
        break;
 
1686
    case CAIRO_EXTEND_REFLECT:
 
1687
        bbox_x = pattern_width*2;
 
1688
        bbox_y = pattern_height*2;
 
1689
        xstep = bbox_x;
 
1690
        ystep = bbox_y;
 
1691
        break;
 
1692
        /* All the rest (if any) should have been analyzed away, so this
 
1693
         * case should be unreachable. */
 
1694
    default:
 
1695
        ASSERT_NOT_REACHED;
 
1696
        xstep = 0;
 
1697
        ystep = 0;
 
1698
    }
 
1699
 
 
1700
    /* At this point, (that is, within the surface backend interface),
 
1701
     * the pattern's matrix maps from cairo's device space to cairo's
 
1702
     * pattern space, (both with their origin at the upper-left, and
 
1703
     * cairo's pattern space of size width,height).
 
1704
     *
 
1705
     * Then, we must emit a PDF pattern object that maps from its own
 
1706
     * pattern space, (which has a size that we establish in the BBox
 
1707
     * dictionary entry), to the PDF page's *initial* space, (which
 
1708
     * does not benefit from the Y-axis flipping matrix that we emit
 
1709
     * on each page). So the PDF patterns matrix maps from a
 
1710
     * (width,height) pattern space to a device space with the origin
 
1711
     * in the lower-left corner.
 
1712
     *
 
1713
     * So to handle all of that, we start with an identity matrix for
 
1714
     * the PDF pattern to device matrix. We translate it up by the
 
1715
     * image height then flip it in the Y direction, (moving us from
 
1716
     * the PDF origin to cairo's origin). We then multiply in the
 
1717
     * inverse of the cairo pattern matrix, (since it maps from device
 
1718
     * to pattern, while we're setting up pattern to device). Finally,
 
1719
     * we translate back down by the image height and flip again to
 
1720
     * end up at the lower-left origin that PDF expects.
 
1721
     *
 
1722
     * Additionally, within the stream that paints the pattern itself,
 
1723
     * we are using a PDF image object that has a size of (1,1) so we
 
1724
     * have to scale it up by the image width and height to fill our
 
1725
     * pattern cell.
 
1726
     */
 
1727
    cairo_p2d = pattern->base.matrix;
 
1728
    status = cairo_matrix_invert (&cairo_p2d);
 
1729
    /* cairo_pattern_set_matrix ensures the matrix is invertible */
 
1730
    assert (status == CAIRO_STATUS_SUCCESS);
 
1731
 
 
1732
    cairo_matrix_init_identity (&pdf_p2d);
 
1733
    cairo_matrix_translate (&pdf_p2d, 0.0, surface_extents.height);
 
1734
    cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
 
1735
    cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
 
1736
    cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
 
1737
    cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
 
1738
 
 
1739
    _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
 
1740
    status = _cairo_pdf_surface_open_stream (surface,
 
1741
                                             &pdf_pattern->pattern_res,
 
1742
                                             FALSE,
 
1743
                                             "   /PatternType 1\n"
 
1744
                                             "   /BBox [0 0 %d %d]\n"
 
1745
                                             "   /XStep %f\n"
 
1746
                                             "   /YStep %f\n"
 
1747
                                             "   /TilingType 1\n"
 
1748
                                             "   /PaintType 1\n"
 
1749
                                             "   /Matrix [ %f %f %f %f %f %f ]\n"
 
1750
                                             "   /Resources << /XObject << /x%d %d 0 R >> >>\n",
 
1751
                                             bbox_x, bbox_y,
 
1752
                                             xstep, ystep,
 
1753
                                             pdf_p2d.xx, pdf_p2d.yx,
 
1754
                                             pdf_p2d.xy, pdf_p2d.yy,
 
1755
                                             pdf_p2d.x0, pdf_p2d.y0,
 
1756
                                             pattern_resource.id,
 
1757
                                             pattern_resource.id);
 
1758
    if (status)
 
1759
        return status;
 
1760
 
 
1761
    if (_cairo_surface_is_meta (pattern->surface)) {
 
1762
        snprintf(draw_surface,
 
1763
                 sizeof (draw_surface),
 
1764
                 "/x%d Do\n",
 
1765
                 pattern_resource.id);
 
1766
    } else {
 
1767
        snprintf(draw_surface,
 
1768
                 sizeof (draw_surface),
 
1769
                 "q %d 0 0 %d 0 0 cm /x%d Do Q",
 
1770
                 pattern_width,
 
1771
                 pattern_height,
 
1772
                 pattern_resource.id);
 
1773
    }
 
1774
 
 
1775
    if (extend == CAIRO_EXTEND_REFLECT) {
 
1776
        _cairo_output_stream_printf (surface->output,
 
1777
                                     "q 0 0 %d %d re W n %s Q\n"
 
1778
                                     "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n %s Q\n"
 
1779
                                     "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n %s Q\n"
 
1780
                                     "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n %s Q\n",
 
1781
                                     pattern_width, pattern_height,
 
1782
                                     draw_surface,
 
1783
                                     pattern_width*2, pattern_width, pattern_height,
 
1784
                                     draw_surface,
 
1785
                                     pattern_height*2, pattern_width, pattern_height,
 
1786
                                     draw_surface,
 
1787
                                     pattern_width*2, pattern_height*2, pattern_width, pattern_height,
 
1788
                                     draw_surface);
 
1789
    } else {
 
1790
        _cairo_output_stream_printf (surface->output,
 
1791
                                     " %s \n",
 
1792
                                     draw_surface);
 
1793
    }
 
1794
 
 
1795
    status = _cairo_pdf_surface_close_stream (surface);
 
1796
    if (status)
 
1797
        return status;
 
1798
 
 
1799
    return _cairo_output_stream_get_status (surface->output);
 
1800
}
 
1801
 
 
1802
typedef struct _cairo_pdf_color_stop {
 
1803
    double offset;
 
1804
    double color[4];
 
1805
    cairo_pdf_resource_t resource;
 
1806
} cairo_pdf_color_stop_t;
 
1807
 
 
1808
static cairo_status_t
 
1809
cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t    *surface,
 
1810
                                            cairo_pdf_color_stop_t *stop1,
 
1811
                                            cairo_pdf_color_stop_t *stop2,
 
1812
                                            cairo_pdf_resource_t   *function)
 
1813
{
 
1814
    int num_elems, i;
 
1815
    cairo_pdf_rgb_linear_function_t elem;
 
1816
    cairo_pdf_resource_t res;
 
1817
    cairo_status_t status;
 
1818
 
 
1819
    num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions);
 
1820
    for (i = 0; i < num_elems; i++) {
 
1821
        _cairo_array_copy_element (&surface->rgb_linear_functions, i, &elem);
 
1822
        if (memcmp (&elem.color1[0], &stop1->color[0], sizeof (double)*3) != 0)
 
1823
            continue;
 
1824
        if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0)
 
1825
            continue;
 
1826
        *function =  elem.resource;
 
1827
        return CAIRO_STATUS_SUCCESS;
 
1828
    }
 
1829
 
 
1830
    res = _cairo_pdf_surface_new_object (surface);
 
1831
    if (res.id == 0)
 
1832
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1833
 
 
1834
    _cairo_output_stream_printf (surface->output,
 
1835
                                 "%d 0 obj\n"
 
1836
                                 "<< /FunctionType 2\n"
 
1837
                                 "   /Domain [ 0 1 ]\n"
 
1838
                                 "   /C0 [ %f %f %f ]\n"
 
1839
                                 "   /C1 [ %f %f %f ]\n"
 
1840
                                 "   /N 1\n"
 
1841
                                 ">>\n"
 
1842
                                 "endobj\n",
 
1843
                                 res.id,
 
1844
                                 stop1->color[0],
 
1845
                                 stop1->color[1],
 
1846
                                 stop1->color[2],
 
1847
                                 stop2->color[0],
 
1848
                                 stop2->color[1],
 
1849
                                 stop2->color[2]);
 
1850
 
 
1851
    elem.resource = res;
 
1852
    memcpy (&elem.color1[0], &stop1->color[0], sizeof (double)*3);
 
1853
    memcpy (&elem.color2[0], &stop2->color[0], sizeof (double)*3);
 
1854
 
 
1855
    status = _cairo_array_append (&surface->rgb_linear_functions, &elem);
 
1856
    *function = res;
 
1857
 
 
1858
    return status;
 
1859
}
 
1860
 
 
1861
static cairo_status_t
 
1862
cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t    *surface,
 
1863
                                              cairo_pdf_color_stop_t *stop1,
 
1864
                                              cairo_pdf_color_stop_t *stop2,
 
1865
                                              cairo_pdf_resource_t   *function)
 
1866
{
 
1867
    int num_elems, i;
 
1868
    cairo_pdf_alpha_linear_function_t elem;
 
1869
    cairo_pdf_resource_t res;
 
1870
    cairo_status_t status;
 
1871
 
 
1872
    num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions);
 
1873
    for (i = 0; i < num_elems; i++) {
 
1874
        _cairo_array_copy_element (&surface->alpha_linear_functions, i, &elem);
 
1875
        if (elem.alpha1 != stop1->color[3])
 
1876
            continue;
 
1877
        if (elem.alpha2 != stop2->color[3])
 
1878
            continue;
 
1879
        *function =  elem.resource;
 
1880
        return CAIRO_STATUS_SUCCESS;
 
1881
    }
 
1882
 
 
1883
    res = _cairo_pdf_surface_new_object (surface);
 
1884
    if (res.id == 0)
 
1885
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1886
 
 
1887
    _cairo_output_stream_printf (surface->output,
 
1888
                                 "%d 0 obj\n"
 
1889
                                 "<< /FunctionType 2\n"
 
1890
                                 "   /Domain [ 0 1 ]\n"
 
1891
                                 "   /C0 [ %f ]\n"
 
1892
                                 "   /C1 [ %f ]\n"
 
1893
                                 "   /N 1\n"
 
1894
                                 ">>\n"
 
1895
                                 "endobj\n",
 
1896
                                 res.id,
 
1897
                                 stop1->color[3],
 
1898
                                 stop2->color[3]);
 
1899
 
 
1900
    elem.resource = res;
 
1901
    elem.alpha1 = stop1->color[3];
 
1902
    elem.alpha2 = stop2->color[3];
 
1903
 
 
1904
    status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
 
1905
    *function = res;
 
1906
 
 
1907
    return status;
 
1908
}
 
1909
 
 
1910
static cairo_status_t
 
1911
_cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t    *surface,
 
1912
                                                unsigned int            n_stops,
 
1913
                                                cairo_pdf_color_stop_t *stops,
 
1914
                                                cairo_bool_t            is_alpha,
 
1915
                                                cairo_pdf_resource_t   *function)
 
1916
{
 
1917
    cairo_pdf_resource_t res;
 
1918
    unsigned int i;
 
1919
    cairo_status_t status;
 
1920
 
 
1921
    /* emit linear gradients between pairs of subsequent stops... */
 
1922
    for (i = 0; i < n_stops-1; i++) {
 
1923
        if (is_alpha) {
 
1924
            status = cairo_pdf_surface_emit_alpha_linear_function (surface,
 
1925
                                                                   &stops[i],
 
1926
                                                                   &stops[i+1],
 
1927
                                                                   &stops[i].resource);
 
1928
            if (status)
 
1929
                return status;
 
1930
        } else {
 
1931
            status = cairo_pdf_surface_emit_rgb_linear_function (surface,
 
1932
                                                                 &stops[i],
 
1933
                                                                 &stops[i+1],
 
1934
                                                                 &stops[i].resource);
 
1935
            if (status)
 
1936
                return status;
 
1937
        }
 
1938
    }
 
1939
 
 
1940
    /* ... and stitch them together */
 
1941
    res = _cairo_pdf_surface_new_object (surface);
 
1942
    if (res.id == 0)
 
1943
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1944
 
 
1945
    _cairo_output_stream_printf (surface->output,
 
1946
                                 "%d 0 obj\n"
 
1947
                                 "<< /FunctionType 3\n"
 
1948
                                 "   /Domain [ %f %f ]\n",
 
1949
                                 res.id,
 
1950
                                 stops[0].offset,
 
1951
                                 stops[n_stops - 1].offset);
 
1952
 
 
1953
    _cairo_output_stream_printf (surface->output,
 
1954
                                 "   /Functions [ ");
 
1955
    for (i = 0; i < n_stops-1; i++)
 
1956
        _cairo_output_stream_printf (surface->output,
 
1957
                                     "%d 0 R ", stops[i].resource.id);
 
1958
    _cairo_output_stream_printf (surface->output,
 
1959
                                 "]\n");
 
1960
 
 
1961
    _cairo_output_stream_printf (surface->output,
 
1962
                                 "   /Bounds [ ");
 
1963
    for (i = 1; i < n_stops-1; i++)
 
1964
        _cairo_output_stream_printf (surface->output,
 
1965
                                     "%f ", stops[i].offset);
 
1966
    _cairo_output_stream_printf (surface->output,
 
1967
                                 "]\n");
 
1968
 
 
1969
    _cairo_output_stream_printf (surface->output,
 
1970
                                 "   /Encode [ ");
 
1971
    for (i = 1; i < n_stops; i++)
 
1972
        _cairo_output_stream_printf (surface->output,
 
1973
                                     "0 1 ");
 
1974
    _cairo_output_stream_printf (surface->output,
 
1975
                                 "]\n");
 
1976
 
 
1977
    _cairo_output_stream_printf (surface->output,
 
1978
                                 ">>\n"
 
1979
                                 "endobj\n");
 
1980
 
 
1981
    *function = res;
 
1982
 
 
1983
    return _cairo_output_stream_get_status (surface->output);
 
1984
}
 
1985
 
 
1986
 
 
1987
static void
 
1988
calc_gradient_color (cairo_pdf_color_stop_t *new_stop,
 
1989
                     cairo_pdf_color_stop_t *stop1,
 
1990
                     cairo_pdf_color_stop_t *stop2)
 
1991
{
 
1992
    int i;
 
1993
    double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
 
1994
 
 
1995
    for (i = 0; i < 4; i++)
 
1996
        new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
 
1997
}
 
1998
 
 
1999
#define COLOR_STOP_EPSILON 1e-6
 
2000
 
 
2001
static cairo_status_t
 
2002
_cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t      *surface,
 
2003
                                       cairo_gradient_pattern_t *pattern,
 
2004
                                       cairo_pdf_resource_t     *color_function,
 
2005
                                       cairo_pdf_resource_t     *alpha_function)
 
2006
{
 
2007
    cairo_pdf_color_stop_t *allstops, *stops;
 
2008
    unsigned int n_stops;
 
2009
    unsigned int i;
 
2010
    cairo_bool_t emit_alpha = FALSE;
 
2011
    cairo_status_t status;
 
2012
 
 
2013
    color_function->id = 0;
 
2014
    alpha_function->id = 0;
 
2015
 
 
2016
    allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t));
 
2017
    if (allstops == NULL)
 
2018
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
2019
 
 
2020
    stops = &allstops[1];
 
2021
    n_stops = pattern->n_stops;
 
2022
 
 
2023
    for (i = 0; i < n_stops; i++) {
 
2024
        stops[i].color[0] = pattern->stops[i].color.red;
 
2025
        stops[i].color[1] = pattern->stops[i].color.green;
 
2026
        stops[i].color[2] = pattern->stops[i].color.blue;
 
2027
        stops[i].color[3] = pattern->stops[i].color.alpha;
 
2028
        if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
 
2029
            emit_alpha = TRUE;
 
2030
        stops[i].offset = pattern->stops[i].offset;
 
2031
    }
 
2032
 
 
2033
    if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
 
2034
        pattern->base.extend == CAIRO_EXTEND_REFLECT) {
 
2035
        if (stops[0].offset > COLOR_STOP_EPSILON) {
 
2036
            if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
 
2037
                memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
 
2038
            else
 
2039
                calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
 
2040
            stops = allstops;
 
2041
            n_stops++;
 
2042
        }
 
2043
        stops[0].offset = 0.0;
 
2044
 
 
2045
        if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
 
2046
            if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
 
2047
                memcpy (&stops[n_stops],
 
2048
                        &stops[n_stops - 1],
 
2049
                        sizeof (cairo_pdf_color_stop_t));
 
2050
            } else {
 
2051
                calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
 
2052
            }
 
2053
            n_stops++;
 
2054
        }
 
2055
        stops[n_stops-1].offset = 1.0;
 
2056
    }
 
2057
 
 
2058
    if (n_stops == 2) {
 
2059
        /* no need for stitched function */
 
2060
        status = cairo_pdf_surface_emit_rgb_linear_function (surface,
 
2061
                                                             &stops[0],
 
2062
                                                             &stops[1],
 
2063
                                                             color_function);
 
2064
        if (status)
 
2065
            goto BAIL;
 
2066
 
 
2067
        if (emit_alpha) {
 
2068
            status = cairo_pdf_surface_emit_alpha_linear_function (surface,
 
2069
                                                                   &stops[0],
 
2070
                                                                   &stops[1],
 
2071
                                                                   alpha_function);
 
2072
            if (status)
 
2073
                goto BAIL;
 
2074
        }
 
2075
    } else {
 
2076
        /* multiple stops: stitch. XXX possible optimization: regularly spaced
 
2077
         * stops do not require stitching. XXX */
 
2078
        status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
 
2079
                                                                 n_stops,
 
2080
                                                                 stops,
 
2081
                                                                 FALSE,
 
2082
                                                                 color_function);
 
2083
        if (status)
 
2084
            goto BAIL;
 
2085
 
 
2086
        if (emit_alpha) {
 
2087
            status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
 
2088
                                                                     n_stops,
 
2089
                                                                     stops,
 
2090
                                                                     TRUE,
 
2091
                                                                     alpha_function);
 
2092
            if (status)
 
2093
                goto BAIL;
 
2094
        }
 
2095
    }
 
2096
 
 
2097
BAIL:
 
2098
    free (allstops);
 
2099
    return status;
 
2100
}
 
2101
 
 
2102
static cairo_status_t
 
2103
_cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t      *surface,
 
2104
                                            cairo_gradient_pattern_t *pattern,
 
2105
                                            cairo_pdf_resource_t     *function,
 
2106
                                            int                       begin,
 
2107
                                            int                       end)
 
2108
{
 
2109
    cairo_pdf_resource_t res;
 
2110
    int i;
 
2111
 
 
2112
    res = _cairo_pdf_surface_new_object (surface);
 
2113
    if (res.id == 0)
 
2114
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
2115
 
 
2116
    _cairo_output_stream_printf (surface->output,
 
2117
                                 "%d 0 obj\n"
 
2118
                                 "<< /FunctionType 3\n"
 
2119
                                 "   /Domain [ %d %d ]\n",
 
2120
                                 res.id,
 
2121
                                 begin,
 
2122
                                 end);
 
2123
 
 
2124
    _cairo_output_stream_printf (surface->output,
 
2125
                                 "   /Functions [ ");
 
2126
    for (i = begin; i < end; i++)
 
2127
        _cairo_output_stream_printf (surface->output,
 
2128
                                     "%d 0 R ", function->id);
 
2129
    _cairo_output_stream_printf (surface->output,
 
2130
                                 "]\n");
 
2131
 
 
2132
    _cairo_output_stream_printf (surface->output,
 
2133
                                 "   /Bounds [ ");
 
2134
    for (i = begin + 1; i < end; i++)
 
2135
        _cairo_output_stream_printf (surface->output,
 
2136
                                     "%d ", i);
 
2137
    _cairo_output_stream_printf (surface->output,
 
2138
                                 "]\n");
 
2139
 
 
2140
    _cairo_output_stream_printf (surface->output,
 
2141
                                 "   /Encode [ ");
 
2142
    for (i = begin; i < end; i++) {
 
2143
        if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) {
 
2144
            _cairo_output_stream_printf (surface->output,
 
2145
                                         "1 0 ");
 
2146
        } else {
 
2147
            _cairo_output_stream_printf (surface->output,
 
2148
                                         "0 1 ");
 
2149
        }
 
2150
    }
 
2151
    _cairo_output_stream_printf (surface->output,
 
2152
                                 "]\n");
 
2153
 
 
2154
    _cairo_output_stream_printf (surface->output,
 
2155
                                 ">>\n"
 
2156
                                 "endobj\n");
 
2157
 
 
2158
    *function = res;
 
2159
 
 
2160
    return _cairo_output_stream_get_status (surface->output);
 
2161
}
 
2162
 
 
2163
static cairo_status_t
 
2164
cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t  *surface,
 
2165
                                           cairo_pdf_resource_t  gstate_resource,
 
2166
                                           cairo_pdf_resource_t  gradient_mask)
 
2167
{
 
2168
    cairo_pdf_resource_t smask_resource;
 
2169
    cairo_status_t status;
 
2170
 
 
2171
    status = _cairo_pdf_surface_open_stream (surface,
 
2172
                                             NULL,
 
2173
                                             surface->compress_content,
 
2174
                                             "   /Type /XObject\n"
 
2175
                                             "   /Subtype /Form\n"
 
2176
                                             "   /FormType 1\n"
 
2177
                                             "   /BBox [ 0 0 %f %f ]\n"
 
2178
                                             "   /Resources\n"
 
2179
                                             "      << /ExtGState\n"
 
2180
                                             "            << /a0 << /ca 1 /CA 1 >>"
 
2181
                                             "      >>\n"
 
2182
                                             "         /Pattern\n"
 
2183
                                             "            << /p%d %d 0 R >>\n"
 
2184
                                             "      >>\n"
 
2185
                                             "   /Group\n"
 
2186
                                             "      << /Type /Group\n"
 
2187
                                             "         /S /Transparency\n"
 
2188
                                             "         /CS /DeviceGray\n"
 
2189
                                             "      >>\n",
 
2190
                                             surface->width,
 
2191
                                             surface->height,
 
2192
                                             gradient_mask.id,
 
2193
                                             gradient_mask.id);
 
2194
    if (status)
 
2195
        return status;
 
2196
 
 
2197
    _cairo_output_stream_printf (surface->output,
 
2198
                                 "q\n"
 
2199
                                 "/a0 gs\n"
 
2200
                                 "/Pattern cs /p%d scn\n"
 
2201
                                 "0 0 %f %f re\n"
 
2202
                                 "f\n"
 
2203
                                 "Q\n",
 
2204
                                 gradient_mask.id,
 
2205
                                 surface->width,
 
2206
                                 surface->height);
 
2207
 
 
2208
     status = _cairo_pdf_surface_close_stream (surface);
 
2209
     if (status)
 
2210
        return status;
 
2211
 
 
2212
    smask_resource = _cairo_pdf_surface_new_object (surface);
 
2213
    if (smask_resource.id == 0)
 
2214
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
2215
 
 
2216
    _cairo_output_stream_printf (surface->output,
 
2217
                                 "%d 0 obj\n"
 
2218
                                 "<< /Type /Mask\n"
 
2219
                                 "   /S /Luminosity\n"
 
2220
                                 "   /G %d 0 R\n"
 
2221
                                 ">>\n"
 
2222
                                 "endobj\n",
 
2223
                                 smask_resource.id,
 
2224
                                 surface->pdf_stream.self.id);
 
2225
 
 
2226
    /* Create GState which uses the transparency group as an SMask. */
 
2227
    _cairo_pdf_surface_update_object (surface, gstate_resource);
 
2228
 
 
2229
    _cairo_output_stream_printf (surface->output,
 
2230
                                 "%d 0 obj\n"
 
2231
                                 "<< /Type /ExtGState\n"
 
2232
                                 "   /SMask %d 0 R\n"
 
2233
                                 "   /ca 1\n"
 
2234
                                 "   /CA 1\n"
 
2235
                                 "   /AIS false\n"
 
2236
                                 ">>\n"
 
2237
                                 "endobj\n",
 
2238
                                 gstate_resource.id,
 
2239
                                 smask_resource.id);
 
2240
 
 
2241
    return _cairo_output_stream_get_status (surface->output);
 
2242
}
 
2243
 
 
2244
static cairo_status_t
 
2245
_cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t    *surface,
 
2246
                                        cairo_pdf_pattern_t    *pdf_pattern)
 
2247
{
 
2248
    cairo_linear_pattern_t *pattern = (cairo_linear_pattern_t *) pdf_pattern->pattern;
 
2249
    cairo_pdf_resource_t color_function, alpha_function;
 
2250
    double x1, y1, x2, y2;
 
2251
    double _x1, _y1, _x2, _y2;
 
2252
    cairo_matrix_t pat_to_pdf;
 
2253
    cairo_extend_t extend;
 
2254
    cairo_status_t status;
 
2255
    cairo_gradient_pattern_t *gradient = &pattern->base;
 
2256
    double first_stop, last_stop;
 
2257
    int repeat_begin = 0, repeat_end = 1;
 
2258
 
 
2259
    assert (pattern->base.n_stops != 0);
 
2260
 
 
2261
    extend = cairo_pattern_get_extend (pdf_pattern->pattern);
 
2262
 
 
2263
    pat_to_pdf = pattern->base.base.matrix;
 
2264
    status = cairo_matrix_invert (&pat_to_pdf);
 
2265
    /* cairo_pattern_set_matrix ensures the matrix is invertible */
 
2266
    assert (status == CAIRO_STATUS_SUCCESS);
 
2267
 
 
2268
    cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
 
2269
    first_stop = gradient->stops[0].offset;
 
2270
    last_stop = gradient->stops[gradient->n_stops - 1].offset;
 
2271
 
 
2272
    if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
 
2273
        pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
 
2274
        double dx, dy;
 
2275
        int x_rep = 0, y_rep = 0;
 
2276
 
 
2277
        x1 = _cairo_fixed_to_double (pattern->p1.x);
 
2278
        y1 = _cairo_fixed_to_double (pattern->p1.y);
 
2279
        cairo_matrix_transform_point (&pat_to_pdf, &x1, &y1);
 
2280
 
 
2281
        x2 = _cairo_fixed_to_double (pattern->p2.x);
 
2282
        y2 = _cairo_fixed_to_double (pattern->p2.y);
 
2283
        cairo_matrix_transform_point (&pat_to_pdf, &x2, &y2);
 
2284
 
 
2285
        dx = fabs (x2 - x1);
 
2286
        dy = fabs (y2 - y1);
 
2287
        if (dx > 1e-6)
 
2288
            x_rep = (int) ceil (surface->width/dx);
 
2289
        if (dy > 1e-6)
 
2290
            y_rep = (int) ceil (surface->height/dy);
 
2291
 
 
2292
        repeat_end = MAX (x_rep, y_rep);
 
2293
        repeat_begin = -repeat_end;
 
2294
        first_stop = repeat_begin;
 
2295
        last_stop = repeat_end;
 
2296
    }
 
2297
 
 
2298
    /* PDF requires the first and last stop to be the same as the line
 
2299
     * coordinates. For repeating patterns this moves the line
 
2300
     * coordinates out to the begin/end of the repeating function. For
 
2301
     * non repeating patterns this may move the line coordinates in if
 
2302
     * there are not stops at offset 0 and 1. */
 
2303
    x1 = _cairo_fixed_to_double (pattern->p1.x);
 
2304
    y1 = _cairo_fixed_to_double (pattern->p1.y);
 
2305
    x2 = _cairo_fixed_to_double (pattern->p2.x);
 
2306
    y2 = _cairo_fixed_to_double (pattern->p2.y);
 
2307
 
 
2308
    _x1 = x1 + (x2 - x1)*first_stop;
 
2309
    _y1 = y1 + (y2 - y1)*first_stop;
 
2310
    _x2 = x1 + (x2 - x1)*last_stop;
 
2311
    _y2 = y1 + (y2 - y1)*last_stop;
 
2312
 
 
2313
    x1 = _x1;
 
2314
    x2 = _x2;
 
2315
    y1 = _y1;
 
2316
    y2 = _y2;
 
2317
 
 
2318
    /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
 
2319
     * Type 2 function is used by itself without a stitching
 
2320
     * function. Type 2 functions always have the domain [0 1] */
 
2321
    if ((pattern->base.base.extend == CAIRO_EXTEND_NONE ||
 
2322
         pattern->base.base.extend == CAIRO_EXTEND_PAD) &&
 
2323
        gradient->n_stops == 2) {
 
2324
        first_stop = 0.0;
 
2325
        last_stop = 1.0;
 
2326
    }
 
2327
 
 
2328
    status = _cairo_pdf_surface_emit_pattern_stops (surface,
 
2329
                                                    &pattern->base,
 
2330
                                                    &color_function,
 
2331
                                                    &alpha_function);
 
2332
    if (status)
 
2333
        return status;
 
2334
 
 
2335
    if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
 
2336
        pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
 
2337
        status = _cairo_pdf_surface_emit_repeating_function (surface,
 
2338
                                                             &pattern->base,
 
2339
                                                             &color_function,
 
2340
                                                             repeat_begin,
 
2341
                                                             repeat_end);
 
2342
        if (status)
 
2343
            return status;
 
2344
 
 
2345
        if (alpha_function.id != 0) {
 
2346
            status = _cairo_pdf_surface_emit_repeating_function (surface,
 
2347
                                                                 &pattern->base,
 
2348
                                                                 &alpha_function,
 
2349
                                                                 repeat_begin,
 
2350
                                                                 repeat_end);
 
2351
            if (status)
 
2352
                return status;
 
2353
        }
 
2354
    }
 
2355
 
 
2356
    _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
 
2357
    _cairo_output_stream_printf (surface->output,
 
2358
                                 "%d 0 obj\n"
 
2359
                                 "<< /Type /Pattern\n"
 
2360
                                 "   /PatternType 2\n"
 
2361
                                 "   /Matrix [ %f %f %f %f %f %f ]\n"
 
2362
                                 "   /Shading\n"
 
2363
                                 "      << /ShadingType 2\n"
 
2364
                                 "         /ColorSpace /DeviceRGB\n"
 
2365
                                 "         /Coords [ %f %f %f %f ]\n"
 
2366
                                 "         /Domain [ %f %f ]\n"
 
2367
                                 "         /Function %d 0 R\n",
 
2368
                                 pdf_pattern->pattern_res.id,
 
2369
                                 pat_to_pdf.xx, pat_to_pdf.yx,
 
2370
                                 pat_to_pdf.xy, pat_to_pdf.yy,
 
2371
                                 pat_to_pdf.x0, pat_to_pdf.y0,
 
2372
                                 x1, y1, x2, y2,
 
2373
                                 first_stop, last_stop,
 
2374
                                 color_function.id);
 
2375
 
 
2376
    if (extend == CAIRO_EXTEND_PAD) {
 
2377
        _cairo_output_stream_printf (surface->output,
 
2378
                                     "         /Extend [ true true ]\n");
 
2379
    } else {
 
2380
        _cairo_output_stream_printf (surface->output,
 
2381
                                     "         /Extend [ false false ]\n");
 
2382
    }
 
2383
 
 
2384
    _cairo_output_stream_printf (surface->output,
 
2385
                                 "      >>\n"
 
2386
                                 ">>\n"
 
2387
                                 "endobj\n");
 
2388
 
 
2389
    if (alpha_function.id != 0) {
 
2390
        cairo_pdf_resource_t mask_resource;
 
2391
 
 
2392
        assert (pdf_pattern->gstate_res.id != 0);
 
2393
 
 
2394
        /* Create pattern for SMask. */
 
2395
        mask_resource = _cairo_pdf_surface_new_object (surface);
 
2396
        if (mask_resource.id == 0)
 
2397
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
2398
 
 
2399
        _cairo_output_stream_printf (surface->output,
 
2400
                                     "%d 0 obj\n"
 
2401
                                     "<< /Type /Pattern\n"
 
2402
                                     "   /PatternType 2\n"
 
2403
                                     "   /Matrix [ %f %f %f %f %f %f ]\n"
 
2404
                                     "   /Shading\n"
 
2405
                                     "      << /ShadingType 2\n"
 
2406
                                     "         /ColorSpace /DeviceGray\n"
 
2407
                                     "         /Coords [ %f %f %f %f ]\n"
 
2408
                                     "         /Domain [ %f %f ]\n"
 
2409
                                     "         /Function %d 0 R\n",
 
2410
                                     mask_resource.id,
 
2411
                                     pat_to_pdf.xx, pat_to_pdf.yx,
 
2412
                                     pat_to_pdf.xy, pat_to_pdf.yy,
 
2413
                                     pat_to_pdf.x0, pat_to_pdf.y0,
 
2414
                                     x1, y1, x2, y2,
 
2415
                                     first_stop, last_stop,
 
2416
                                     alpha_function.id);
 
2417
 
 
2418
        if (extend == CAIRO_EXTEND_PAD) {
 
2419
            _cairo_output_stream_printf (surface->output,
 
2420
                                         "         /Extend [ true true ]\n");
 
2421
        } else {
 
2422
            _cairo_output_stream_printf (surface->output,
 
2423
                                         "         /Extend [ false false ]\n");
 
2424
        }
 
2425
 
 
2426
        _cairo_output_stream_printf (surface->output,
 
2427
                                     "      >>\n"
 
2428
                                     ">>\n"
 
2429
                                     "endobj\n");
 
2430
        status = _cairo_pdf_surface_add_pattern (surface, mask_resource);
 
2431
        if (status)
 
2432
            return status;
 
2433
 
 
2434
        status = cairo_pdf_surface_emit_transparency_group (surface,
 
2435
                                                            pdf_pattern->gstate_res,
 
2436
                                                            mask_resource);
 
2437
        if (status)
 
2438
            return status;
 
2439
    }
 
2440
 
 
2441
    return _cairo_output_stream_get_status (surface->output);
 
2442
}
 
2443
 
 
2444
static cairo_status_t
 
2445
_cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t    *surface,
 
2446
                                        cairo_pdf_pattern_t    *pdf_pattern)
 
2447
{
 
2448
    cairo_pdf_resource_t color_function, alpha_function;
 
2449
    double x1, y1, x2, y2, r1, r2;
 
2450
    cairo_matrix_t pat_to_pdf;
 
2451
    cairo_extend_t extend;
 
2452
    cairo_status_t status;
 
2453
    cairo_radial_pattern_t *pattern = (cairo_radial_pattern_t *) pdf_pattern->pattern;
 
2454
 
 
2455
    assert (pattern->base.n_stops != 0);
 
2456
 
 
2457
    extend = cairo_pattern_get_extend (pdf_pattern->pattern);
 
2458
 
 
2459
    status = _cairo_pdf_surface_emit_pattern_stops (surface,
 
2460
                                                    &pattern->base,
 
2461
                                                    &color_function,
 
2462
                                                    &alpha_function);
 
2463
    if (status)
 
2464
        return status;
 
2465
 
 
2466
    pat_to_pdf = pattern->base.base.matrix;
 
2467
    status = cairo_matrix_invert (&pat_to_pdf);
 
2468
    /* cairo_pattern_set_matrix ensures the matrix is invertible */
 
2469
    assert (status == CAIRO_STATUS_SUCCESS);
 
2470
 
 
2471
    cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
 
2472
    x1 = _cairo_fixed_to_double (pattern->c1.x);
 
2473
    y1 = _cairo_fixed_to_double (pattern->c1.y);
 
2474
    r1 = _cairo_fixed_to_double (pattern->r1);
 
2475
    x2 = _cairo_fixed_to_double (pattern->c2.x);
 
2476
    y2 = _cairo_fixed_to_double (pattern->c2.y);
 
2477
    r2 = _cairo_fixed_to_double (pattern->r2);
 
2478
 
 
2479
    _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
 
2480
 
 
2481
    _cairo_output_stream_printf (surface->output,
 
2482
                                 "%d 0 obj\n"
 
2483
                                 "<< /Type /Pattern\n"
 
2484
                                 "   /PatternType 2\n"
 
2485
                                 "   /Matrix [ %f %f %f %f %f %f ]\n"
 
2486
                                 "   /Shading\n"
 
2487
                                 "      << /ShadingType 3\n"
 
2488
                                 "         /ColorSpace /DeviceRGB\n"
 
2489
                                 "         /Coords [ %f %f %f %f %f %f ]\n"
 
2490
                                 "         /Function %d 0 R\n",
 
2491
                                 pdf_pattern->pattern_res.id,
 
2492
                                 pat_to_pdf.xx, pat_to_pdf.yx,
 
2493
                                 pat_to_pdf.xy, pat_to_pdf.yy,
 
2494
                                 pat_to_pdf.x0, pat_to_pdf.y0,
 
2495
                                 x1, y1, r1, x2, y2, r2,
 
2496
                                 color_function.id);
 
2497
 
 
2498
    if (extend == CAIRO_EXTEND_PAD) {
 
2499
        _cairo_output_stream_printf (surface->output,
 
2500
                                     "         /Extend [ true true ]\n");
 
2501
    } else {
 
2502
        _cairo_output_stream_printf (surface->output,
 
2503
                                     "         /Extend [ false false ]\n");
 
2504
    }
 
2505
 
 
2506
    _cairo_output_stream_printf (surface->output,
 
2507
                                 "      >>\n"
 
2508
                                 ">>\n"
 
2509
                                 "endobj\n");
 
2510
 
 
2511
    if (alpha_function.id != 0) {
 
2512
        cairo_pdf_resource_t mask_resource;
 
2513
 
 
2514
        assert (pdf_pattern->gstate_res.id != 0);
 
2515
 
 
2516
        /* Create pattern for SMask. */
 
2517
        mask_resource = _cairo_pdf_surface_new_object (surface);
 
2518
        if (mask_resource.id == 0)
 
2519
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
2520
 
 
2521
        _cairo_output_stream_printf (surface->output,
 
2522
                                     "%d 0 obj\n"
 
2523
                                     "<< /Type /Pattern\n"
 
2524
                                     "   /PatternType 2\n"
 
2525
                                     "   /Matrix [ %f %f %f %f %f %f ]\n"
 
2526
                                     "   /Shading\n"
 
2527
                                     "      << /ShadingType 3\n"
 
2528
                                     "         /ColorSpace /DeviceGray\n"
 
2529
                                     "         /Coords [ %f %f %f %f %f %f ]\n"
 
2530
                                     "         /Function %d 0 R\n",
 
2531
                                     mask_resource.id,
 
2532
                                     pat_to_pdf.xx, pat_to_pdf.yx,
 
2533
                                     pat_to_pdf.xy, pat_to_pdf.yy,
 
2534
                                     pat_to_pdf.x0, pat_to_pdf.y0,
 
2535
                                     x1, y1, r1, x2, y2, r2,
 
2536
                                     alpha_function.id);
 
2537
 
 
2538
        if (extend == CAIRO_EXTEND_PAD) {
 
2539
            _cairo_output_stream_printf (surface->output,
 
2540
                                         "         /Extend [ true true ]\n");
 
2541
        } else {
 
2542
            _cairo_output_stream_printf (surface->output,
 
2543
                                         "         /Extend [ false false ]\n");
 
2544
        }
 
2545
 
 
2546
        _cairo_output_stream_printf (surface->output,
 
2547
                                     "      >>\n"
 
2548
                                     ">>\n"
 
2549
                                     "endobj\n");
 
2550
 
 
2551
        status = cairo_pdf_surface_emit_transparency_group (surface,
 
2552
                                                            pdf_pattern->gstate_res,
 
2553
                                                            mask_resource);
 
2554
        if (status)
 
2555
            return status;
 
2556
    }
 
2557
 
 
2558
    return _cairo_output_stream_get_status (surface->output);
 
2559
}
 
2560
 
 
2561
static cairo_status_t
 
2562
_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
 
2563
{
 
2564
    double old_width, old_height;
 
2565
    cairo_status_t status;
 
2566
 
 
2567
    old_width = surface->width;
 
2568
    old_height = surface->height;
 
2569
    _cairo_pdf_surface_set_size_internal (surface,
 
2570
                                          pdf_pattern->width,
 
2571
                                          pdf_pattern->height);
 
2572
 
 
2573
    switch (pdf_pattern->pattern->type) {
 
2574
    case CAIRO_PATTERN_TYPE_SOLID:
 
2575
        ASSERT_NOT_REACHED;
 
2576
        status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 
2577
        break;
 
2578
 
 
2579
    case CAIRO_PATTERN_TYPE_SURFACE:
 
2580
        status = _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
 
2581
        break;
 
2582
 
 
2583
    case CAIRO_PATTERN_TYPE_LINEAR:
 
2584
        status = _cairo_pdf_surface_emit_linear_pattern (surface, pdf_pattern);
 
2585
        break;
 
2586
 
 
2587
    case CAIRO_PATTERN_TYPE_RADIAL:
 
2588
        status = _cairo_pdf_surface_emit_radial_pattern (surface, pdf_pattern);
 
2589
        break;
 
2590
 
 
2591
    default:
 
2592
        ASSERT_NOT_REACHED;
 
2593
        status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 
2594
        break;
 
2595
    }
 
2596
 
 
2597
    _cairo_pdf_surface_set_size_internal (surface,
 
2598
                                          old_width,
 
2599
                                          old_height);
 
2600
 
 
2601
    return status;
 
2602
}
 
2603
 
 
2604
static cairo_status_t
 
2605
_cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
 
2606
                                   cairo_pattern_t     *pattern,
 
2607
                                   cairo_pdf_resource_t pattern_res,
 
2608
                                   cairo_bool_t         is_stroke)
 
2609
{
 
2610
    cairo_status_t status;
 
2611
    int alpha;
 
2612
    cairo_color_t *solid_color = NULL;
 
2613
 
 
2614
    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
 
2615
        cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
 
2616
 
 
2617
        solid_color = &solid->color;
 
2618
    }
 
2619
 
 
2620
    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
 
2621
        pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
 
2622
    {
 
2623
        cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
 
2624
 
 
2625
        if (gradient->n_stops == 1)
 
2626
            solid_color = &gradient->stops[0].color;
 
2627
    }
 
2628
 
 
2629
    if (solid_color != NULL) {
 
2630
        if (surface->current_pattern_is_solid_color == FALSE ||
 
2631
            surface->current_color_red != solid_color->red ||
 
2632
            surface->current_color_green != solid_color->green ||
 
2633
            surface->current_color_blue != solid_color->blue ||
 
2634
            surface->current_color_is_stroke != is_stroke)
 
2635
        {
 
2636
            status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
2637
            if (status)
 
2638
                return status;
 
2639
 
 
2640
            _cairo_output_stream_printf (surface->output,
 
2641
                                         "%f %f %f ",
 
2642
                                         solid_color->red,
 
2643
                                         solid_color->green,
 
2644
                                         solid_color->blue);
 
2645
 
 
2646
            if (is_stroke)
 
2647
                _cairo_output_stream_printf (surface->output, "RG ");
 
2648
            else
 
2649
                _cairo_output_stream_printf (surface->output, "rg ");
 
2650
 
 
2651
            surface->current_color_red = solid_color->red;
 
2652
            surface->current_color_green = solid_color->green;
 
2653
            surface->current_color_blue = solid_color->blue;
 
2654
            surface->current_color_is_stroke = is_stroke;
 
2655
        }
 
2656
 
 
2657
        if (surface->current_pattern_is_solid_color == FALSE ||
 
2658
            surface->current_color_alpha != solid_color->alpha)
 
2659
        {
 
2660
            status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha);
 
2661
            if (status)
 
2662
                return status;
 
2663
 
 
2664
            status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
2665
            if (status)
 
2666
                return status;
 
2667
 
 
2668
            _cairo_output_stream_printf (surface->output,
 
2669
                                         "/a%d gs\n",
 
2670
                                         alpha);
 
2671
            surface->current_color_alpha = solid_color->alpha;
 
2672
        }
 
2673
 
 
2674
        surface->current_pattern_is_solid_color = TRUE;
 
2675
    } else {
 
2676
        status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
 
2677
        if (status)
 
2678
            return status;
 
2679
 
 
2680
        status = _cairo_pdf_surface_add_pattern (surface, pattern_res);
 
2681
        if (status)
 
2682
            return status;
 
2683
 
 
2684
        status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
2685
        if (status)
 
2686
            return status;
 
2687
 
 
2688
        /* fill-stroke calls select_pattern twice. Don't save if the
 
2689
         * gstate is already saved. */
 
2690
        if (!surface->select_pattern_gstate_saved)
 
2691
            _cairo_output_stream_printf (surface->output, "q ");
 
2692
 
 
2693
        if (is_stroke) {
 
2694
            _cairo_output_stream_printf (surface->output,
 
2695
                                         "/Pattern CS /p%d SCN ",
 
2696
                                         pattern_res.id);
 
2697
        } else {
 
2698
            _cairo_output_stream_printf (surface->output,
 
2699
                                         "/Pattern cs /p%d scn ",
 
2700
                                         pattern_res.id);
 
2701
        }
 
2702
        _cairo_output_stream_printf (surface->output,
 
2703
                                     "/a%d gs\n",
 
2704
                                     alpha);
 
2705
        surface->select_pattern_gstate_saved = TRUE;
 
2706
        surface->current_pattern_is_solid_color = FALSE;
 
2707
    }
 
2708
 
 
2709
    return _cairo_output_stream_get_status (surface->output);
 
2710
}
 
2711
 
 
2712
static cairo_int_status_t
 
2713
_cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
 
2714
{
 
2715
    cairo_int_status_t status;
 
2716
 
 
2717
    if (surface->select_pattern_gstate_saved) {
 
2718
        status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
2719
        if (status)
 
2720
            return status;
 
2721
 
 
2722
        _cairo_output_stream_printf (surface->output, "Q\n");
 
2723
        _cairo_pdf_operators_reset (&surface->pdf_operators);
 
2724
    }
 
2725
    surface->select_pattern_gstate_saved = FALSE;
 
2726
 
 
2727
    return CAIRO_STATUS_SUCCESS;
 
2728
}
 
2729
 
 
2730
static cairo_int_status_t
 
2731
_cairo_pdf_surface_show_page (void *abstract_surface)
 
2732
{
 
2733
    cairo_pdf_surface_t *surface = abstract_surface;
 
2734
    cairo_int_status_t status;
 
2735
 
 
2736
    status = _cairo_pdf_surface_close_content_stream (surface);
 
2737
    if (status)
 
2738
        return status;
 
2739
 
 
2740
    status = _cairo_pdf_surface_write_page (surface);
 
2741
    if (status)
 
2742
        return status;
 
2743
 
 
2744
    _cairo_pdf_surface_clear (surface);
 
2745
 
 
2746
    return CAIRO_STATUS_SUCCESS;
 
2747
}
 
2748
 
 
2749
static cairo_int_status_t
 
2750
_cairo_pdf_surface_get_extents (void                    *abstract_surface,
 
2751
                                cairo_rectangle_int_t   *rectangle)
 
2752
{
 
2753
    cairo_pdf_surface_t *surface = abstract_surface;
 
2754
 
 
2755
    rectangle->x = 0;
 
2756
    rectangle->y = 0;
 
2757
 
 
2758
    /* XXX: The conversion to integers here is pretty bogus, (not to
 
2759
     * mention the arbitrary limitation of width to a short(!). We
 
2760
     * may need to come up with a better interface for get_size.
 
2761
     */
 
2762
    rectangle->width  = (int) ceil (surface->width);
 
2763
    rectangle->height = (int) ceil (surface->height);
 
2764
 
 
2765
    return CAIRO_STATUS_SUCCESS;
 
2766
}
 
2767
 
 
2768
static cairo_int_status_t
 
2769
_cairo_pdf_surface_intersect_clip_path (void                    *abstract_surface,
 
2770
                                        cairo_path_fixed_t      *path,
 
2771
                                        cairo_fill_rule_t       fill_rule,
 
2772
                                        double                  tolerance,
 
2773
                                        cairo_antialias_t       antialias)
 
2774
{
 
2775
    cairo_pdf_surface_t *surface = abstract_surface;
 
2776
    cairo_int_status_t status;
 
2777
 
 
2778
    if (path == NULL) {
 
2779
        status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
2780
        if (status)
 
2781
            return status;
 
2782
 
 
2783
        _cairo_output_stream_printf (surface->output, "Q q\n");
 
2784
        surface->current_pattern_is_solid_color = FALSE;
 
2785
        _cairo_pdf_operators_reset (&surface->pdf_operators);
 
2786
 
 
2787
        return CAIRO_STATUS_SUCCESS;
 
2788
    }
 
2789
 
 
2790
    return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
 
2791
}
 
2792
 
 
2793
static void
 
2794
_cairo_pdf_surface_get_font_options (void                  *abstract_surface,
 
2795
                                     cairo_font_options_t  *options)
 
2796
{
 
2797
    _cairo_font_options_init_default (options);
 
2798
 
 
2799
    cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
 
2800
    cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
 
2801
    cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
 
2802
}
 
2803
 
 
2804
static cairo_pdf_resource_t
 
2805
_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface)
 
2806
{
 
2807
    cairo_pdf_resource_t info;
 
2808
 
 
2809
    info = _cairo_pdf_surface_new_object (surface);
 
2810
    if (info.id == 0)
 
2811
        return info;
 
2812
 
 
2813
    _cairo_output_stream_printf (surface->output,
 
2814
                                 "%d 0 obj\n"
 
2815
                                 "<< /Creator (cairo %s (http://cairographics.org))\n"
 
2816
                                 "   /Producer (cairo %s (http://cairographics.org))\n"
 
2817
                                 ">>\n"
 
2818
                                 "endobj\n",
 
2819
                                 info.id,
 
2820
                                 cairo_version_string (),
 
2821
                                 cairo_version_string ());
 
2822
 
 
2823
    return info;
 
2824
}
 
2825
 
 
2826
static void
 
2827
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
 
2828
{
 
2829
    cairo_pdf_resource_t page;
 
2830
    int num_pages, i;
 
2831
 
 
2832
    _cairo_pdf_surface_update_object (surface, surface->pages_resource);
 
2833
    _cairo_output_stream_printf (surface->output,
 
2834
                                 "%d 0 obj\n"
 
2835
                                 "<< /Type /Pages\n"
 
2836
                                 "   /Kids [ ",
 
2837
                                 surface->pages_resource.id);
 
2838
 
 
2839
    num_pages = _cairo_array_num_elements (&surface->pages);
 
2840
    for (i = 0; i < num_pages; i++) {
 
2841
        _cairo_array_copy_element (&surface->pages, i, &page);
 
2842
        _cairo_output_stream_printf (surface->output, "%d 0 R ", page.id);
 
2843
    }
 
2844
 
 
2845
    _cairo_output_stream_printf (surface->output, "]\n");
 
2846
    _cairo_output_stream_printf (surface->output, "   /Count %d\n", num_pages);
 
2847
 
 
2848
 
 
2849
    /* TODO: Figure out which other defaults to be inherited by /Page
 
2850
     * objects. */
 
2851
    _cairo_output_stream_printf (surface->output,
 
2852
                                 ">>\n"
 
2853
                                 "endobj\n");
 
2854
}
 
2855
 
 
2856
static cairo_status_t
 
2857
_cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t  *surface,
 
2858
                                           const char           *utf8)
 
2859
{
 
2860
    uint16_t *utf16 = NULL;
 
2861
    int utf16_len = 0;
 
2862
    cairo_status_t status;
 
2863
    int i;
 
2864
 
 
2865
    if (utf8 && *utf8) {
 
2866
        status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
 
2867
        if (status)
 
2868
            return status;
 
2869
    }
 
2870
 
 
2871
    _cairo_output_stream_printf (surface->output, "<");
 
2872
    if (utf16 == NULL || utf16_len == 0) {
 
2873
        /* According to the "ToUnicode Mapping File Tutorial"
 
2874
         * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
 
2875
         *
 
2876
         * Glyphs that do not map to a Unicode code point must be
 
2877
         * mapped to 0xfffd "REPLACEMENT CHARACTER".
 
2878
         */
 
2879
        _cairo_output_stream_printf (surface->output,
 
2880
                                     "fffd");
 
2881
    } else {
 
2882
        for (i = 0; i < utf16_len; i++)
 
2883
            _cairo_output_stream_printf (surface->output,
 
2884
                                         "%04x", (int) (utf16[i]));
 
2885
    }
 
2886
    _cairo_output_stream_printf (surface->output, ">");
 
2887
 
 
2888
    if (utf16)
 
2889
        free (utf16);
 
2890
 
 
2891
    return CAIRO_STATUS_SUCCESS;
 
2892
}
 
2893
 
 
2894
static cairo_int_status_t
 
2895
_cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t          *surface,
 
2896
                                           cairo_scaled_font_subset_t   *font_subset,
 
2897
                                           cairo_bool_t                  is_composite,
 
2898
                                           cairo_pdf_resource_t         *stream)
 
2899
{
 
2900
    unsigned int i, num_bfchar;
 
2901
    cairo_int_status_t status;
 
2902
 
 
2903
    stream->id = 0;
 
2904
 
 
2905
    status = _cairo_pdf_surface_open_stream (surface,
 
2906
                                              NULL,
 
2907
                                              surface->compress_content,
 
2908
                                              NULL);
 
2909
    if (status)
 
2910
        return status;
 
2911
 
 
2912
    _cairo_output_stream_printf (surface->output,
 
2913
                                 "/CIDInit /ProcSet findresource begin\n"
 
2914
                                 "12 dict begin\n"
 
2915
                                 "begincmap\n"
 
2916
                                 "/CIDSystemInfo\n"
 
2917
                                 "<< /Registry (Adobe)\n"
 
2918
                                 "   /Ordering (UCS)\n"
 
2919
                                 "   /Supplement 0\n"
 
2920
                                 ">> def\n"
 
2921
                                 "/CMapName /Adobe-Identity-UCS def\n"
 
2922
                                 "/CMapType 2 def\n"
 
2923
                                 "1 begincodespacerange\n");
 
2924
 
 
2925
    if (is_composite) {
 
2926
        _cairo_output_stream_printf (surface->output,
 
2927
                                     "<0000> <ffff>\n");
 
2928
    } else {
 
2929
        _cairo_output_stream_printf (surface->output,
 
2930
                                     "<00> <ff>\n");
 
2931
    }
 
2932
 
 
2933
    _cairo_output_stream_printf (surface->output,
 
2934
                                  "endcodespacerange\n");
 
2935
 
 
2936
    num_bfchar = font_subset->num_glyphs - 1;
 
2937
 
 
2938
    /* The CMap specification has a limit of 100 characters per beginbfchar operator */
 
2939
    _cairo_output_stream_printf (surface->output,
 
2940
                                 "%d beginbfchar\n",
 
2941
                                 num_bfchar > 100 ? 100 : num_bfchar);
 
2942
 
 
2943
    for (i = 0; i < num_bfchar; i++) {
 
2944
        if (i != 0 && i % 100 == 0) {
 
2945
            _cairo_output_stream_printf (surface->output,
 
2946
                                         "endbfchar\n"
 
2947
                                         "%d beginbfchar\n",
 
2948
                                         num_bfchar - i > 100 ? 100 : num_bfchar - i);
 
2949
        }
 
2950
        if (is_composite) {
 
2951
            _cairo_output_stream_printf (surface->output,
 
2952
                                         "<%04x> ",
 
2953
                                         i + 1);
 
2954
        } else {
 
2955
            _cairo_output_stream_printf (surface->output,
 
2956
                                         "<%02x> ",
 
2957
                                         i + 1);
 
2958
        }
 
2959
        _cairo_pdf_surface_emit_unicode_for_glyph (surface, font_subset->utf8[i + 1]);
 
2960
        _cairo_output_stream_printf (surface->output,
 
2961
                                     "\n");
 
2962
    }
 
2963
    _cairo_output_stream_printf (surface->output,
 
2964
                                 "endbfchar\n");
 
2965
 
 
2966
    _cairo_output_stream_printf (surface->output,
 
2967
                                 "endcmap\n"
 
2968
                                 "CMapName currentdict /CMap defineresource pop\n"
 
2969
                                 "end\n"
 
2970
                                 "end\n");
 
2971
 
 
2972
    *stream = surface->pdf_stream.self;
 
2973
    return _cairo_pdf_surface_close_stream (surface);
 
2974
}
 
2975
 
 
2976
static cairo_status_t
 
2977
_cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t           *surface,
 
2978
                                  cairo_scaled_font_subset_t    *font_subset,
 
2979
                                  cairo_cff_subset_t            *subset)
 
2980
{
 
2981
    cairo_pdf_resource_t stream, descriptor, cidfont_dict;
 
2982
    cairo_pdf_resource_t subset_resource, to_unicode_stream;
 
2983
    cairo_pdf_font_t font;
 
2984
    unsigned int i;
 
2985
    cairo_status_t status;
 
2986
 
 
2987
    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
 
2988
                                                            font_subset->font_id,
 
2989
                                                            font_subset->subset_id);
 
2990
    if (subset_resource.id == 0)
 
2991
        return CAIRO_STATUS_SUCCESS;
 
2992
 
 
2993
    status = _cairo_pdf_surface_open_stream (surface,
 
2994
                                             NULL,
 
2995
                                             TRUE,
 
2996
                                             "   /Subtype /CIDFontType0C\n");
 
2997
    if (status)
 
2998
        return status;
 
2999
 
 
3000
    stream = surface->pdf_stream.self;
 
3001
    _cairo_output_stream_write (surface->output,
 
3002
                                subset->data, subset->data_length);
 
3003
    status = _cairo_pdf_surface_close_stream (surface);
 
3004
    if (status)
 
3005
        return status;
 
3006
 
 
3007
    status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
 
3008
                                                        font_subset, TRUE,
 
3009
                                                        &to_unicode_stream);
 
3010
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 
3011
        return status;
 
3012
 
 
3013
    descriptor = _cairo_pdf_surface_new_object (surface);
 
3014
    if (descriptor.id == 0)
 
3015
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3016
 
 
3017
    _cairo_output_stream_printf (surface->output,
 
3018
                                 "%d 0 obj\n"
 
3019
                                 "<< /Type /FontDescriptor\n"
 
3020
                                 "   /FontName /%s\n"
 
3021
                                 "   /Flags 4\n"
 
3022
                                 "   /FontBBox [ %ld %ld %ld %ld ]\n"
 
3023
                                 "   /ItalicAngle 0\n"
 
3024
                                 "   /Ascent %ld\n"
 
3025
                                 "   /Descent %ld\n"
 
3026
                                 "   /CapHeight 500\n"
 
3027
                                 "   /StemV 80\n"
 
3028
                                 "   /StemH 80\n"
 
3029
                                 "   /FontFile3 %u 0 R\n"
 
3030
                                 ">>\n"
 
3031
                                 "endobj\n",
 
3032
                                 descriptor.id,
 
3033
                                 subset->base_font,
 
3034
                                 subset->x_min,
 
3035
                                 subset->y_min,
 
3036
                                 subset->x_max,
 
3037
                                 subset->y_max,
 
3038
                                 subset->ascent,
 
3039
                                 subset->descent,
 
3040
                                 stream.id);
 
3041
 
 
3042
    cidfont_dict = _cairo_pdf_surface_new_object (surface);
 
3043
    if (cidfont_dict.id == 0)
 
3044
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3045
 
 
3046
    _cairo_output_stream_printf (surface->output,
 
3047
                                 "%d 0 obj\n"
 
3048
                                 "<< /Type /Font\n"
 
3049
                                 "   /Subtype /CIDFontType0\n"
 
3050
                                 "   /BaseFont /%s\n"
 
3051
                                 "   /CIDSystemInfo\n"
 
3052
                                 "   << /Registry (Adobe)\n"
 
3053
                                 "      /Ordering (Identity)\n"
 
3054
                                 "      /Supplement 0\n"
 
3055
                                 "   >>\n"
 
3056
                                 "   /FontDescriptor %d 0 R\n"
 
3057
                                 "   /W [0 [",
 
3058
                                 cidfont_dict.id,
 
3059
                                 subset->base_font,
 
3060
                                 descriptor.id);
 
3061
 
 
3062
    for (i = 0; i < font_subset->num_glyphs; i++)
 
3063
        _cairo_output_stream_printf (surface->output,
 
3064
                                     " %d",
 
3065
                                     subset->widths[i]);
 
3066
 
 
3067
    _cairo_output_stream_printf (surface->output,
 
3068
                                 " ]]\n"
 
3069
                                 ">>\n"
 
3070
                                 "endobj\n");
 
3071
 
 
3072
    _cairo_pdf_surface_update_object (surface, subset_resource);
 
3073
    _cairo_output_stream_printf (surface->output,
 
3074
                                 "%d 0 obj\n"
 
3075
                                 "<< /Type /Font\n"
 
3076
                                 "   /Subtype /Type0\n"
 
3077
                                 "   /BaseFont /%s\n"
 
3078
                                 "   /Encoding /Identity-H\n"
 
3079
                                 "   /DescendantFonts [ %d 0 R]\n",
 
3080
                                 subset_resource.id,
 
3081
                                 subset->base_font,
 
3082
                                 cidfont_dict.id);
 
3083
 
 
3084
    if (to_unicode_stream.id != 0)
 
3085
        _cairo_output_stream_printf (surface->output,
 
3086
                                     "   /ToUnicode %d 0 R\n",
 
3087
                                     to_unicode_stream.id);
 
3088
 
 
3089
    _cairo_output_stream_printf (surface->output,
 
3090
                                 ">>\n"
 
3091
                                 "endobj\n");
 
3092
 
 
3093
    font.font_id = font_subset->font_id;
 
3094
    font.subset_id = font_subset->subset_id;
 
3095
    font.subset_resource = subset_resource;
 
3096
    status = _cairo_array_append (&surface->fonts, &font);
 
3097
 
 
3098
    return status;
 
3099
}
 
3100
 
 
3101
static cairo_status_t
 
3102
_cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t         *surface,
 
3103
                                         cairo_scaled_font_subset_t  *font_subset)
 
3104
{
 
3105
    cairo_status_t status;
 
3106
    cairo_cff_subset_t subset;
 
3107
    char name[64];
 
3108
 
 
3109
    snprintf (name, sizeof name, "CairoFont-%d-%d",
 
3110
              font_subset->font_id, font_subset->subset_id);
 
3111
    status = _cairo_cff_subset_init (&subset, name, font_subset);
 
3112
    if (status)
 
3113
        return status;
 
3114
 
 
3115
    status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
 
3116
 
 
3117
    _cairo_cff_subset_fini (&subset);
 
3118
 
 
3119
    return status;
 
3120
}
 
3121
 
 
3122
static cairo_status_t
 
3123
_cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t         *surface,
 
3124
                                           cairo_scaled_font_subset_t  *font_subset)
 
3125
{
 
3126
    cairo_status_t status;
 
3127
    cairo_cff_subset_t subset;
 
3128
    char name[64];
 
3129
 
 
3130
    snprintf (name, sizeof name, "CairoFont-%d-%d",
 
3131
              font_subset->font_id, font_subset->subset_id);
 
3132
    status = _cairo_cff_fallback_init (&subset, name, font_subset);
 
3133
    if (status)
 
3134
        return status;
 
3135
 
 
3136
    status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
 
3137
 
 
3138
    _cairo_cff_fallback_fini (&subset);
 
3139
 
 
3140
    return status;
 
3141
}
 
3142
 
 
3143
static cairo_status_t
 
3144
_cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t         *surface,
 
3145
                                    cairo_scaled_font_subset_t  *font_subset,
 
3146
                                    cairo_type1_subset_t        *subset)
 
3147
{
 
3148
    cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
 
3149
    cairo_pdf_font_t font;
 
3150
    cairo_status_t status;
 
3151
    unsigned long length;
 
3152
    unsigned int i;
 
3153
 
 
3154
    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
 
3155
                                                            font_subset->font_id,
 
3156
                                                            font_subset->subset_id);
 
3157
    if (subset_resource.id == 0)
 
3158
        return CAIRO_STATUS_SUCCESS;
 
3159
 
 
3160
    /* We ignore the zero-trailer and set Length3 to 0. */
 
3161
    length = subset->header_length + subset->data_length;
 
3162
    status = _cairo_pdf_surface_open_stream (surface,
 
3163
                                             NULL,
 
3164
                                             TRUE,
 
3165
                                             "   /Length1 %lu\n"
 
3166
                                             "   /Length2 %lu\n"
 
3167
                                             "   /Length3 0\n",
 
3168
                                             subset->header_length,
 
3169
                                             subset->data_length);
 
3170
    if (status)
 
3171
        return status;
 
3172
 
 
3173
    stream = surface->pdf_stream.self;
 
3174
    _cairo_output_stream_write (surface->output, subset->data, length);
 
3175
    status = _cairo_pdf_surface_close_stream (surface);
 
3176
    if (status)
 
3177
        return status;
 
3178
 
 
3179
    status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
 
3180
                                                        font_subset, FALSE,
 
3181
                                                        &to_unicode_stream);
 
3182
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 
3183
        return status;
 
3184
 
 
3185
    descriptor = _cairo_pdf_surface_new_object (surface);
 
3186
    if (descriptor.id == 0)
 
3187
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3188
 
 
3189
    _cairo_output_stream_printf (surface->output,
 
3190
                                 "%d 0 obj\n"
 
3191
                                 "<< /Type /FontDescriptor\n"
 
3192
                                 "   /FontName /%s\n"
 
3193
                                 "   /Flags 4\n"
 
3194
                                 "   /FontBBox [ %ld %ld %ld %ld ]\n"
 
3195
                                 "   /ItalicAngle 0\n"
 
3196
                                 "   /Ascent %ld\n"
 
3197
                                 "   /Descent %ld\n"
 
3198
                                 "   /CapHeight 500\n"
 
3199
                                 "   /StemV 80\n"
 
3200
                                 "   /StemH 80\n"
 
3201
                                 "   /FontFile %u 0 R\n"
 
3202
                                 ">>\n"
 
3203
                                 "endobj\n",
 
3204
                                 descriptor.id,
 
3205
                                 subset->base_font,
 
3206
                                 subset->x_min,
 
3207
                                 subset->y_min,
 
3208
                                 subset->x_max,
 
3209
                                 subset->y_max,
 
3210
                                 subset->ascent,
 
3211
                                 subset->descent,
 
3212
                                 stream.id);
 
3213
 
 
3214
    _cairo_pdf_surface_update_object (surface, subset_resource);
 
3215
    _cairo_output_stream_printf (surface->output,
 
3216
                                 "%d 0 obj\n"
 
3217
                                 "<< /Type /Font\n"
 
3218
                                 "   /Subtype /Type1\n"
 
3219
                                 "   /BaseFont /%s\n"
 
3220
                                 "   /FirstChar 0\n"
 
3221
                                 "   /LastChar %d\n"
 
3222
                                 "   /FontDescriptor %d 0 R\n"
 
3223
                                 "   /Widths [",
 
3224
                                 subset_resource.id,
 
3225
                                 subset->base_font,
 
3226
                                 font_subset->num_glyphs - 1,
 
3227
                                 descriptor.id);
 
3228
 
 
3229
    for (i = 0; i < font_subset->num_glyphs; i++)
 
3230
        _cairo_output_stream_printf (surface->output,
 
3231
                                     " %d",
 
3232
                                     subset->widths[i]);
 
3233
 
 
3234
    _cairo_output_stream_printf (surface->output,
 
3235
                                 " ]\n");
 
3236
 
 
3237
    if (to_unicode_stream.id != 0)
 
3238
        _cairo_output_stream_printf (surface->output,
 
3239
                                     "    /ToUnicode %d 0 R\n",
 
3240
                                     to_unicode_stream.id);
 
3241
 
 
3242
    _cairo_output_stream_printf (surface->output,
 
3243
                                 ">>\n"
 
3244
                                 "endobj\n");
 
3245
 
 
3246
    font.font_id = font_subset->font_id;
 
3247
    font.subset_id = font_subset->subset_id;
 
3248
    font.subset_resource = subset_resource;
 
3249
    return _cairo_array_append (&surface->fonts, &font);
 
3250
}
 
3251
 
 
3252
#if CAIRO_HAS_FT_FONT
 
3253
static cairo_status_t
 
3254
_cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t          *surface,
 
3255
                                           cairo_scaled_font_subset_t   *font_subset)
 
3256
{
 
3257
    cairo_status_t status;
 
3258
    cairo_type1_subset_t subset;
 
3259
    char name[64];
 
3260
 
 
3261
    snprintf (name, sizeof name, "CairoFont-%d-%d",
 
3262
              font_subset->font_id, font_subset->subset_id);
 
3263
    status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE);
 
3264
    if (status)
 
3265
        return status;
 
3266
 
 
3267
    status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
 
3268
 
 
3269
    _cairo_type1_subset_fini (&subset);
 
3270
    return status;
 
3271
}
 
3272
#endif
 
3273
 
 
3274
static cairo_status_t
 
3275
_cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t        *surface,
 
3276
                                             cairo_scaled_font_subset_t *font_subset)
 
3277
{
 
3278
    cairo_status_t status;
 
3279
    cairo_type1_subset_t subset;
 
3280
    char name[64];
 
3281
 
 
3282
    snprintf (name, sizeof name, "CairoFont-%d-%d",
 
3283
              font_subset->font_id, font_subset->subset_id);
 
3284
    status = _cairo_type1_fallback_init_binary (&subset, name, font_subset);
 
3285
    if (status)
 
3286
        return status;
 
3287
 
 
3288
    status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
 
3289
 
 
3290
    _cairo_type1_fallback_fini (&subset);
 
3291
    return status;
 
3292
}
 
3293
 
 
3294
#define PDF_UNITS_PER_EM 1000
 
3295
 
 
3296
static cairo_status_t
 
3297
_cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t               *surface,
 
3298
                                              cairo_scaled_font_subset_t        *font_subset)
 
3299
{
 
3300
    cairo_pdf_resource_t stream, descriptor, cidfont_dict;
 
3301
    cairo_pdf_resource_t subset_resource, to_unicode_stream;
 
3302
    cairo_status_t status;
 
3303
    cairo_pdf_font_t font;
 
3304
    cairo_truetype_subset_t subset;
 
3305
    unsigned int i;
 
3306
 
 
3307
    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
 
3308
                                                            font_subset->font_id,
 
3309
                                                            font_subset->subset_id);
 
3310
    if (subset_resource.id == 0)
 
3311
        return CAIRO_STATUS_SUCCESS;
 
3312
 
 
3313
    status = _cairo_truetype_subset_init (&subset, font_subset);
 
3314
    if (status)
 
3315
        return status;
 
3316
 
 
3317
    status = _cairo_pdf_surface_open_stream (surface,
 
3318
                                             NULL,
 
3319
                                             TRUE,
 
3320
                                             "   /Length1 %lu\n",
 
3321
                                             subset.data_length);
 
3322
    if (status) {
 
3323
        _cairo_truetype_subset_fini (&subset);
 
3324
        return status;
 
3325
    }
 
3326
 
 
3327
    stream = surface->pdf_stream.self;
 
3328
    _cairo_output_stream_write (surface->output,
 
3329
                                subset.data, subset.data_length);
 
3330
    status = _cairo_pdf_surface_close_stream (surface);
 
3331
    if (status) {
 
3332
        _cairo_truetype_subset_fini (&subset);
 
3333
        return status;
 
3334
    }
 
3335
 
 
3336
    status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
 
3337
                                                        font_subset, TRUE,
 
3338
                                                        &to_unicode_stream);
 
3339
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) {
 
3340
        _cairo_truetype_subset_fini (&subset);
 
3341
        return status;
 
3342
    }
 
3343
 
 
3344
    descriptor = _cairo_pdf_surface_new_object (surface);
 
3345
    if (descriptor.id == 0) {
 
3346
        _cairo_truetype_subset_fini (&subset);
 
3347
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3348
    }
 
3349
 
 
3350
    _cairo_output_stream_printf (surface->output,
 
3351
                                 "%d 0 obj\n"
 
3352
                                 "<< /Type /FontDescriptor\n"
 
3353
                                 "   /FontName /%s\n"
 
3354
                                 "   /Flags 4\n"
 
3355
                                 "   /FontBBox [ %ld %ld %ld %ld ]\n"
 
3356
                                 "   /ItalicAngle 0\n"
 
3357
                                 "   /Ascent %ld\n"
 
3358
                                 "   /Descent %ld\n"
 
3359
                                 "   /CapHeight %ld\n"
 
3360
                                 "   /StemV 80\n"
 
3361
                                 "   /StemH 80\n"
 
3362
                                 "   /FontFile2 %u 0 R\n"
 
3363
                                 ">>\n"
 
3364
                                 "endobj\n",
 
3365
                                 descriptor.id,
 
3366
                                 subset.base_font,
 
3367
                                 (long)(subset.x_min*PDF_UNITS_PER_EM),
 
3368
                                 (long)(subset.y_min*PDF_UNITS_PER_EM),
 
3369
                                 (long)(subset.x_max*PDF_UNITS_PER_EM),
 
3370
                                 (long)(subset.y_max*PDF_UNITS_PER_EM),
 
3371
                                 (long)(subset.ascent*PDF_UNITS_PER_EM),
 
3372
                                 (long)(subset.descent*PDF_UNITS_PER_EM),
 
3373
                                 (long)(subset.y_max*PDF_UNITS_PER_EM),
 
3374
                                 stream.id);
 
3375
 
 
3376
    cidfont_dict = _cairo_pdf_surface_new_object (surface);
 
3377
    if (cidfont_dict.id == 0) {
 
3378
        _cairo_truetype_subset_fini (&subset);
 
3379
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3380
    }
 
3381
 
 
3382
    _cairo_output_stream_printf (surface->output,
 
3383
                                 "%d 0 obj\n"
 
3384
                                 "<< /Type /Font\n"
 
3385
                                 "   /Subtype /CIDFontType2\n"
 
3386
                                 "   /BaseFont /%s\n"
 
3387
                                 "   /CIDSystemInfo\n"
 
3388
                                 "   << /Registry (Adobe)\n"
 
3389
                                 "      /Ordering (Identity)\n"
 
3390
                                 "      /Supplement 0\n"
 
3391
                                 "   >>\n"
 
3392
                                 "   /FontDescriptor %d 0 R\n"
 
3393
                                 "   /W [0 [",
 
3394
                                 cidfont_dict.id,
 
3395
                                 subset.base_font,
 
3396
                                 descriptor.id);
 
3397
 
 
3398
    for (i = 0; i < font_subset->num_glyphs; i++)
 
3399
        _cairo_output_stream_printf (surface->output,
 
3400
                                     " %ld",
 
3401
                                     (long)(subset.widths[i]*PDF_UNITS_PER_EM));
 
3402
 
 
3403
    _cairo_output_stream_printf (surface->output,
 
3404
                                 " ]]\n"
 
3405
                                 ">>\n"
 
3406
                                 "endobj\n");
 
3407
 
 
3408
    _cairo_pdf_surface_update_object (surface, subset_resource);
 
3409
    _cairo_output_stream_printf (surface->output,
 
3410
                                 "%d 0 obj\n"
 
3411
                                 "<< /Type /Font\n"
 
3412
                                 "   /Subtype /Type0\n"
 
3413
                                 "   /BaseFont /%s\n"
 
3414
                                 "   /Encoding /Identity-H\n"
 
3415
                                 "   /DescendantFonts [ %d 0 R]\n",
 
3416
                                 subset_resource.id,
 
3417
                                 subset.base_font,
 
3418
                                 cidfont_dict.id);
 
3419
 
 
3420
    if (to_unicode_stream.id != 0)
 
3421
        _cairo_output_stream_printf (surface->output,
 
3422
                                     "   /ToUnicode %d 0 R\n",
 
3423
                                     to_unicode_stream.id);
 
3424
 
 
3425
    _cairo_output_stream_printf (surface->output,
 
3426
                                 ">>\n"
 
3427
                                 "endobj\n");
 
3428
 
 
3429
    font.font_id = font_subset->font_id;
 
3430
    font.subset_id = font_subset->subset_id;
 
3431
    font.subset_resource = subset_resource;
 
3432
    status = _cairo_array_append (&surface->fonts, &font);
 
3433
 
 
3434
    _cairo_truetype_subset_fini (&subset);
 
3435
 
 
3436
    return status;
 
3437
}
 
3438
 
 
3439
static cairo_status_t
 
3440
_cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
 
3441
                             cairo_output_stream_t *stream)
 
3442
{
 
3443
    uint8_t *byte, output_byte;
 
3444
    int row, col, num_cols;
 
3445
 
 
3446
    /* The only image type supported by Type 3 fonts are 1-bit image
 
3447
     * masks */
 
3448
    assert (image->format == CAIRO_FORMAT_A1);
 
3449
 
 
3450
    _cairo_output_stream_printf (stream,
 
3451
                                 "BI\n"
 
3452
                                 "/IM true\n"
 
3453
                                 "/W %d\n"
 
3454
                                 "/H %d\n"
 
3455
                                 "/BPC 1\n"
 
3456
                                 "/D [1 0]\n",
 
3457
                                 image->width,
 
3458
                                 image->height);
 
3459
 
 
3460
    _cairo_output_stream_printf (stream,
 
3461
                                 "ID ");
 
3462
 
 
3463
    num_cols = (image->width + 7) / 8;
 
3464
    for (row = 0; row < image->height; row++) {
 
3465
        byte = image->data + row * image->stride;
 
3466
        for (col = 0; col < num_cols; col++) {
 
3467
            output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
 
3468
            _cairo_output_stream_write (stream, &output_byte, 1);
 
3469
            byte++;
 
3470
        }
 
3471
    }
 
3472
 
 
3473
    _cairo_output_stream_printf (stream,
 
3474
                                 "\nEI\n");
 
3475
 
 
3476
    return _cairo_output_stream_get_status (stream);
 
3477
}
 
3478
 
 
3479
static cairo_status_t
 
3480
_cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
 
3481
                                             void                       *closure)
 
3482
{
 
3483
    cairo_pdf_surface_t *surface = closure;
 
3484
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
3485
    cairo_status_t status2;
 
3486
    unsigned int i;
 
3487
    cairo_surface_t *type3_surface;
 
3488
    cairo_output_stream_t *null_stream;
 
3489
 
 
3490
    null_stream = _cairo_null_stream_create ();
 
3491
    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
 
3492
                                                       null_stream,
 
3493
                                                       _cairo_pdf_emit_imagemask,
 
3494
                                                       surface->font_subsets);
 
3495
    _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
 
3496
                                                          _cairo_pdf_surface_add_font,
 
3497
                                                          surface);
 
3498
 
 
3499
    for (i = 1; i < font_subset->num_glyphs; i++) {
 
3500
        status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
 
3501
                                                           font_subset->glyphs[i]);
 
3502
        if (status)
 
3503
            break;
 
3504
    }
 
3505
 
 
3506
    cairo_surface_destroy (type3_surface);
 
3507
    status2 = _cairo_output_stream_destroy (null_stream);
 
3508
    if (status == CAIRO_STATUS_SUCCESS)
 
3509
        status = status2;
 
3510
 
 
3511
    return status;
 
3512
}
 
3513
 
 
3514
static cairo_status_t
 
3515
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t          *surface,
 
3516
                                           cairo_scaled_font_subset_t   *font_subset)
 
3517
{
 
3518
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
3519
    cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
 
3520
    cairo_pdf_font_t font;
 
3521
    double *widths;
 
3522
    unsigned int i;
 
3523
    cairo_box_t font_bbox = {{0,0},{0,0}};
 
3524
    cairo_box_t bbox = {{0,0},{0,0}};
 
3525
    cairo_surface_t *type3_surface;
 
3526
 
 
3527
    if (font_subset->num_glyphs == 0)
 
3528
        return CAIRO_STATUS_SUCCESS;
 
3529
 
 
3530
    subset_resource = _cairo_pdf_surface_get_font_resource (surface,
 
3531
                                                            font_subset->font_id,
 
3532
                                                            font_subset->subset_id);
 
3533
    if (subset_resource.id == 0)
 
3534
        return CAIRO_STATUS_SUCCESS;
 
3535
 
 
3536
    glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
 
3537
    if (glyphs == NULL)
 
3538
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3539
 
 
3540
    widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
 
3541
    if (widths == NULL) {
 
3542
        free (glyphs);
 
3543
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3544
    }
 
3545
 
 
3546
    _cairo_pdf_group_resources_clear (&surface->resources);
 
3547
    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
 
3548
                                                       NULL,
 
3549
                                                       _cairo_pdf_emit_imagemask,
 
3550
                                                       surface->font_subsets);
 
3551
    _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
 
3552
                                                          _cairo_pdf_surface_add_font,
 
3553
                                                          surface);
 
3554
 
 
3555
    for (i = 0; i < font_subset->num_glyphs; i++) {
 
3556
        status = _cairo_pdf_surface_open_stream (surface,
 
3557
                                                 NULL,
 
3558
                                                 surface->compress_content,
 
3559
                                                 NULL);
 
3560
        if (status)
 
3561
            break;
 
3562
 
 
3563
        glyphs[i] = surface->pdf_stream.self;
 
3564
        if (i == 0) {
 
3565
            status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
 
3566
                                                                   surface->output,
 
3567
                                                                   &bbox,
 
3568
                                                                   &widths[i]);
 
3569
        } else {
 
3570
            status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
 
3571
                                                            surface->output,
 
3572
                                                            font_subset->glyphs[i],
 
3573
                                                            &bbox,
 
3574
                                                            &widths[i]);
 
3575
        }
 
3576
        if (status)
 
3577
            break;
 
3578
 
 
3579
        status = _cairo_pdf_surface_close_stream (surface);
 
3580
        if (status)
 
3581
            break;
 
3582
 
 
3583
        if (i == 0) {
 
3584
            font_bbox.p1.x = bbox.p1.x;
 
3585
            font_bbox.p1.y = bbox.p1.y;
 
3586
            font_bbox.p2.x = bbox.p2.x;
 
3587
            font_bbox.p2.y = bbox.p2.y;
 
3588
        } else {
 
3589
            if (bbox.p1.x < font_bbox.p1.x)
 
3590
                font_bbox.p1.x = bbox.p1.x;
 
3591
            if (bbox.p1.y < font_bbox.p1.y)
 
3592
                font_bbox.p1.y = bbox.p1.y;
 
3593
            if (bbox.p2.x > font_bbox.p2.x)
 
3594
                font_bbox.p2.x = bbox.p2.x;
 
3595
            if (bbox.p2.y > font_bbox.p2.y)
 
3596
                font_bbox.p2.y = bbox.p2.y;
 
3597
        }
 
3598
    }
 
3599
    cairo_surface_destroy (type3_surface);
 
3600
    if (status) {
 
3601
        free (glyphs);
 
3602
        free (widths);
 
3603
        return status;
 
3604
    }
 
3605
 
 
3606
    encoding = _cairo_pdf_surface_new_object (surface);
 
3607
    if (encoding.id == 0) {
 
3608
        free (glyphs);
 
3609
        free (widths);
 
3610
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3611
    }
 
3612
 
 
3613
    _cairo_output_stream_printf (surface->output,
 
3614
                                 "%d 0 obj\n"
 
3615
                                 "<< /Type /Encoding\n"
 
3616
                                 "   /Differences [0", encoding.id);
 
3617
    for (i = 0; i < font_subset->num_glyphs; i++)
 
3618
        _cairo_output_stream_printf (surface->output,
 
3619
                                     " /%d", i);
 
3620
    _cairo_output_stream_printf (surface->output,
 
3621
                                 "]\n"
 
3622
                                 ">>\n"
 
3623
                                 "endobj\n");
 
3624
 
 
3625
    char_procs = _cairo_pdf_surface_new_object (surface);
 
3626
    if (char_procs.id == 0) {
 
3627
        free (glyphs);
 
3628
        free (widths);
 
3629
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3630
    }
 
3631
 
 
3632
    _cairo_output_stream_printf (surface->output,
 
3633
                                 "%d 0 obj\n"
 
3634
                                 "<<\n", char_procs.id);
 
3635
    for (i = 0; i < font_subset->num_glyphs; i++)
 
3636
        _cairo_output_stream_printf (surface->output,
 
3637
                                     " /%d %d 0 R\n",
 
3638
                                     i, glyphs[i].id);
 
3639
    _cairo_output_stream_printf (surface->output,
 
3640
                                 ">>\n"
 
3641
                                 "endobj\n");
 
3642
 
 
3643
    free (glyphs);
 
3644
 
 
3645
    status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
 
3646
                                                        font_subset, FALSE,
 
3647
                                                        &to_unicode_stream);
 
3648
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) {
 
3649
        free (widths);
 
3650
        return status;
 
3651
    }
 
3652
 
 
3653
    _cairo_pdf_surface_update_object (surface, subset_resource);
 
3654
    _cairo_output_stream_printf (surface->output,
 
3655
                                 "%d 0 obj\n"
 
3656
                                 "<< /Type /Font\n"
 
3657
                                 "   /Subtype /Type3\n"
 
3658
                                 "   /FontBBox [%f %f %f %f]\n"
 
3659
                                 "   /FontMatrix [ 1 0 0 1 0 0 ]\n"
 
3660
                                 "   /Encoding %d 0 R\n"
 
3661
                                 "   /CharProcs %d 0 R\n"
 
3662
                                 "   /FirstChar 0\n"
 
3663
                                 "   /LastChar %d\n",
 
3664
                                 subset_resource.id,
 
3665
                                 _cairo_fixed_to_double (font_bbox.p1.x),
 
3666
                                 - _cairo_fixed_to_double (font_bbox.p2.y),
 
3667
                                 _cairo_fixed_to_double (font_bbox.p2.x),
 
3668
                                 - _cairo_fixed_to_double (font_bbox.p1.y),
 
3669
                                 encoding.id,
 
3670
                                 char_procs.id,
 
3671
                                 font_subset->num_glyphs - 1);
 
3672
 
 
3673
    _cairo_output_stream_printf (surface->output,
 
3674
                                 "   /Widths [");
 
3675
    for (i = 0; i < font_subset->num_glyphs; i++)
 
3676
        _cairo_output_stream_printf (surface->output, " %f", widths[i]);
 
3677
    _cairo_output_stream_printf (surface->output,
 
3678
                                 "]\n");
 
3679
    free (widths);
 
3680
 
 
3681
    _cairo_output_stream_printf (surface->output,
 
3682
                                 "   /Resources\n");
 
3683
    _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
 
3684
 
 
3685
    if (to_unicode_stream.id != 0)
 
3686
        _cairo_output_stream_printf (surface->output,
 
3687
                                     "    /ToUnicode %d 0 R\n",
 
3688
                                     to_unicode_stream.id);
 
3689
 
 
3690
    _cairo_output_stream_printf (surface->output,
 
3691
                                 ">>\n"
 
3692
                                 "endobj\n");
 
3693
 
 
3694
    font.font_id = font_subset->font_id;
 
3695
    font.subset_id = font_subset->subset_id;
 
3696
    font.subset_resource = subset_resource;
 
3697
    return _cairo_array_append (&surface->fonts, &font);
 
3698
}
 
3699
 
 
3700
static cairo_status_t
 
3701
_cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
 
3702
                                              void                       *closure)
 
3703
{
 
3704
    cairo_pdf_surface_t *surface = closure;
 
3705
    cairo_status_t status;
 
3706
 
 
3707
    if (font_subset->is_composite) {
 
3708
        status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
 
3709
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 
3710
            return status;
 
3711
 
 
3712
        status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
 
3713
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 
3714
            return status;
 
3715
 
 
3716
        status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
 
3717
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 
3718
            return status;
 
3719
    } else {
 
3720
#if CAIRO_HAS_FT_FONT
 
3721
        status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
 
3722
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 
3723
            return status;
 
3724
#endif
 
3725
 
 
3726
        status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
 
3727
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 
3728
            return status;
 
3729
 
 
3730
    }
 
3731
 
 
3732
    ASSERT_NOT_REACHED;
 
3733
    return CAIRO_STATUS_SUCCESS;
 
3734
}
 
3735
 
 
3736
static cairo_status_t
 
3737
_cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
 
3738
                                            void                       *closure)
 
3739
{
 
3740
    cairo_pdf_surface_t *surface = closure;
 
3741
    cairo_status_t status;
 
3742
 
 
3743
    status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
 
3744
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 
3745
        return status;
 
3746
 
 
3747
    ASSERT_NOT_REACHED;
 
3748
    return CAIRO_STATUS_SUCCESS;
 
3749
}
 
3750
 
 
3751
static cairo_status_t
 
3752
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
 
3753
{
 
3754
    cairo_status_t status;
 
3755
 
 
3756
    status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
 
3757
                                                      _cairo_pdf_surface_analyze_user_font_subset,
 
3758
                                                      surface);
 
3759
    if (status)
 
3760
        goto BAIL;
 
3761
 
 
3762
    status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
 
3763
                                                          _cairo_pdf_surface_emit_unscaled_font_subset,
 
3764
                                                          surface);
 
3765
    if (status)
 
3766
        goto BAIL;
 
3767
 
 
3768
    status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
 
3769
                                                        _cairo_pdf_surface_emit_scaled_font_subset,
 
3770
                                                        surface);
 
3771
    if (status)
 
3772
        goto BAIL;
 
3773
 
 
3774
    status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
 
3775
                                                      _cairo_pdf_surface_emit_scaled_font_subset,
 
3776
                                                      surface);
 
3777
 
 
3778
BAIL:
 
3779
    _cairo_scaled_font_subsets_destroy (surface->font_subsets);
 
3780
    surface->font_subsets = NULL;
 
3781
 
 
3782
    return status;
 
3783
}
 
3784
 
 
3785
static cairo_pdf_resource_t
 
3786
_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface)
 
3787
{
 
3788
    cairo_pdf_resource_t catalog;
 
3789
 
 
3790
    catalog = _cairo_pdf_surface_new_object (surface);
 
3791
    if (catalog.id == 0)
 
3792
        return catalog;
 
3793
 
 
3794
    _cairo_output_stream_printf (surface->output,
 
3795
                                 "%d 0 obj\n"
 
3796
                                 "<< /Type /Catalog\n"
 
3797
                                 "   /Pages %d 0 R\n"
 
3798
                                 ">>\n"
 
3799
                                 "endobj\n",
 
3800
                                 catalog.id,
 
3801
                                 surface->pages_resource.id);
 
3802
 
 
3803
    return catalog;
 
3804
}
 
3805
 
 
3806
static long
 
3807
_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
 
3808
{
 
3809
    cairo_pdf_object_t *object;
 
3810
    int num_objects, i;
 
3811
    long offset;
 
3812
    char buffer[11];
 
3813
 
 
3814
    num_objects = _cairo_array_num_elements (&surface->objects);
 
3815
 
 
3816
    offset = _cairo_output_stream_get_position (surface->output);
 
3817
    _cairo_output_stream_printf (surface->output,
 
3818
                                 "xref\n"
 
3819
                                 "%d %d\n",
 
3820
                                 0, num_objects + 1);
 
3821
 
 
3822
    _cairo_output_stream_printf (surface->output,
 
3823
                                 "0000000000 65535 f \n");
 
3824
    for (i = 0; i < num_objects; i++) {
 
3825
        object = _cairo_array_index (&surface->objects, i);
 
3826
        snprintf (buffer, sizeof buffer, "%010ld", object->offset);
 
3827
        _cairo_output_stream_printf (surface->output,
 
3828
                                     "%s 00000 n \n", buffer);
 
3829
    }
 
3830
 
 
3831
    return offset;
 
3832
}
 
3833
 
 
3834
static cairo_status_t
 
3835
_cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t        *surface,
 
3836
                                     cairo_pdf_smask_group_t    *group)
 
3837
{
 
3838
    cairo_pdf_resource_t mask_group;
 
3839
    cairo_pdf_resource_t smask;
 
3840
    cairo_pdf_smask_group_t *smask_group;
 
3841
    cairo_pdf_resource_t pattern_res, gstate_res;
 
3842
    cairo_status_t status;
 
3843
 
 
3844
    /* Create mask group */
 
3845
    status = _cairo_pdf_surface_open_group (surface, NULL);
 
3846
    if (status)
 
3847
        return status;
 
3848
 
 
3849
    pattern_res.id = 0;
 
3850
    gstate_res.id = 0;
 
3851
    status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, &pattern_res, &gstate_res);
 
3852
    if (status)
 
3853
        return status;
 
3854
 
 
3855
    if (gstate_res.id != 0) {
 
3856
        smask_group = _cairo_pdf_surface_create_smask_group (surface);
 
3857
        if (smask_group == NULL)
 
3858
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3859
 
 
3860
        smask_group->operation = PDF_PAINT;
 
3861
        smask_group->source = cairo_pattern_reference (group->mask);
 
3862
        smask_group->source_res = pattern_res;
 
3863
        status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
 
3864
        if (status) {
 
3865
            _cairo_pdf_smask_group_destroy (smask_group);
 
3866
            return status;
 
3867
        }
 
3868
 
 
3869
        status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 
3870
        if (status)
 
3871
            return status;
 
3872
 
 
3873
        status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
 
3874
        if (status)
 
3875
            return status;
 
3876
 
 
3877
        _cairo_output_stream_printf (surface->output,
 
3878
                                     "q /s%d gs /x%d Do Q\n",
 
3879
                                     gstate_res.id,
 
3880
                                     smask_group->group_res.id);
 
3881
    } else {
 
3882
        status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE);
 
3883
        if (status)
 
3884
            return status;
 
3885
 
 
3886
        _cairo_output_stream_printf (surface->output,
 
3887
                                     "0 0 %f %f re f\n",
 
3888
                                     surface->width, surface->height);
 
3889
 
 
3890
        status = _cairo_pdf_surface_unselect_pattern (surface);
 
3891
        if (status)
 
3892
            return status;
 
3893
    }
 
3894
 
 
3895
    status = _cairo_pdf_surface_close_group (surface, &mask_group);
 
3896
    if (status)
 
3897
        return status;
 
3898
 
 
3899
    /* Create source group */
 
3900
    status = _cairo_pdf_surface_open_group (surface, &group->source_res);
 
3901
    if (status)
 
3902
        return status;
 
3903
 
 
3904
    pattern_res.id = 0;
 
3905
    gstate_res.id = 0;
 
3906
    status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, &pattern_res, &gstate_res);
 
3907
    if (status)
 
3908
        return status;
 
3909
 
 
3910
    if (gstate_res.id != 0) {
 
3911
        smask_group = _cairo_pdf_surface_create_smask_group (surface);
 
3912
        if (smask_group == NULL)
 
3913
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3914
 
 
3915
        smask_group->operation = PDF_PAINT;
 
3916
        smask_group->source = cairo_pattern_reference (group->source);
 
3917
        smask_group->source_res = pattern_res;
 
3918
        status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
 
3919
        if (status) {
 
3920
            _cairo_pdf_smask_group_destroy (smask_group);
 
3921
            return status;
 
3922
        }
 
3923
 
 
3924
        status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 
3925
        if (status)
 
3926
            return status;
 
3927
 
 
3928
        status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
 
3929
        if (status)
 
3930
            return status;
 
3931
 
 
3932
        _cairo_output_stream_printf (surface->output,
 
3933
                                     "q /s%d gs /x%d Do Q\n",
 
3934
                                     gstate_res.id,
 
3935
                                     smask_group->group_res.id);
 
3936
    } else {
 
3937
        status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE);
 
3938
        if (status)
 
3939
            return status;
 
3940
 
 
3941
        _cairo_output_stream_printf (surface->output,
 
3942
                                     "0 0 %f %f re f\n",
 
3943
                                     surface->width, surface->height);
 
3944
 
 
3945
        status = _cairo_pdf_surface_unselect_pattern (surface);
 
3946
        if (status)
 
3947
            return status;
 
3948
    }
 
3949
 
 
3950
    status = _cairo_pdf_surface_close_group (surface, NULL);
 
3951
    if (status)
 
3952
        return status;
 
3953
 
 
3954
    /* Create an smask based on the alpha component of mask_group */
 
3955
    smask = _cairo_pdf_surface_new_object (surface);
 
3956
    if (smask.id == 0)
 
3957
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
3958
 
 
3959
    _cairo_output_stream_printf (surface->output,
 
3960
                                 "%d 0 obj\n"
 
3961
                                 "<< /Type /Mask\n"
 
3962
                                 "   /S /Alpha\n"
 
3963
                                 "   /G %d 0 R\n"
 
3964
                                 ">>\n"
 
3965
                                 "endobj\n",
 
3966
                                 smask.id,
 
3967
                                 mask_group.id);
 
3968
 
 
3969
    /* Create a GState that uses the smask */
 
3970
    _cairo_pdf_surface_update_object (surface, group->group_res);
 
3971
    _cairo_output_stream_printf (surface->output,
 
3972
                                 "%d 0 obj\n"
 
3973
                                 "<< /Type /ExtGState\n"
 
3974
                                 "   /SMask %d 0 R\n"
 
3975
                                 "   /ca 1\n"
 
3976
                                 "   /CA 1\n"
 
3977
                                 "   /AIS false\n"
 
3978
                                 ">>\n"
 
3979
                                 "endobj\n",
 
3980
                                 group->group_res.id,
 
3981
                                 smask.id);
 
3982
 
 
3983
    return _cairo_output_stream_get_status (surface->output);
 
3984
}
 
3985
 
 
3986
static cairo_status_t
 
3987
_cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t     *surface,
 
3988
                                      cairo_pdf_smask_group_t *group)
 
3989
{
 
3990
    double old_width, old_height;
 
3991
    cairo_status_t status;
 
3992
 
 
3993
    old_width = surface->width;
 
3994
    old_height = surface->height;
 
3995
    _cairo_pdf_surface_set_size_internal (surface,
 
3996
                                          group->width,
 
3997
                                          group->height);
 
3998
    /* _mask is a special case that requires two groups - source
 
3999
     * and mask as well as a smask and gstate dictionary */
 
4000
    if (group->operation == PDF_MASK)
 
4001
        return _cairo_pdf_surface_write_mask_group (surface, group);
 
4002
 
 
4003
    status = _cairo_pdf_surface_open_group (surface, &group->group_res);
 
4004
    if (status)
 
4005
        return status;
 
4006
 
 
4007
    status = _cairo_pdf_surface_select_pattern (surface,
 
4008
                                                group->source,
 
4009
                                                group->source_res,
 
4010
                                                group->operation == PDF_STROKE);
 
4011
    if (status)
 
4012
        return status;
 
4013
 
 
4014
    switch (group->operation) {
 
4015
    case PDF_PAINT:
 
4016
        _cairo_output_stream_printf (surface->output,
 
4017
                                     "0 0 %f %f re f\n",
 
4018
                                     surface->width, surface->height);
 
4019
        break;
 
4020
    case PDF_MASK:
 
4021
        ASSERT_NOT_REACHED;
 
4022
        break;
 
4023
    case PDF_FILL:
 
4024
        status = _cairo_pdf_operators_fill (&surface->pdf_operators,
 
4025
                                            &group->path,
 
4026
                                            group->fill_rule);
 
4027
        break;
 
4028
    case PDF_STROKE:
 
4029
        status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
 
4030
                                              &group->path,
 
4031
                                              group->style,
 
4032
                                              &group->ctm,
 
4033
                                              &group->ctm_inverse);
 
4034
        break;
 
4035
    case PDF_SHOW_GLYPHS:
 
4036
        status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
 
4037
                                                        group->utf8, group->utf8_len,
 
4038
                                                        group->glyphs, group->num_glyphs,
 
4039
                                                        group->clusters, group->num_clusters,
 
4040
                                                        group->cluster_flags,
 
4041
                                                        group->scaled_font);
 
4042
        break;
 
4043
    }
 
4044
    if (status)
 
4045
        return status;
 
4046
 
 
4047
    status = _cairo_pdf_surface_unselect_pattern (surface);
 
4048
    if (status)
 
4049
        return status;
 
4050
 
 
4051
    status = _cairo_pdf_surface_close_group (surface, NULL);
 
4052
 
 
4053
    _cairo_pdf_surface_set_size_internal (surface,
 
4054
                                          old_width,
 
4055
                                          old_height);
 
4056
 
 
4057
    return status;
 
4058
}
 
4059
 
 
4060
static cairo_status_t
 
4061
_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface)
 
4062
{
 
4063
    cairo_pdf_pattern_t pattern;
 
4064
    cairo_pdf_smask_group_t *group;
 
4065
    int pattern_index, group_index;
 
4066
    cairo_status_t status;
 
4067
 
 
4068
    /* Writing out PDF_MASK groups will cause additional smask groups
 
4069
     * to be appended to surface->smask_groups. Additional patterns
 
4070
     * may also be appended to surface->patterns.
 
4071
     *
 
4072
     * Writing meta surface patterns will cause additional patterns
 
4073
     * and groups to be appended.
 
4074
     */
 
4075
    pattern_index = 0;
 
4076
    group_index = 0;
 
4077
    while ((pattern_index < _cairo_array_num_elements (&surface->patterns)) ||
 
4078
           (group_index < _cairo_array_num_elements (&surface->smask_groups)))
 
4079
    {
 
4080
        for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) {
 
4081
            _cairo_array_copy_element (&surface->smask_groups, group_index, &group);
 
4082
            status = _cairo_pdf_surface_write_smask_group (surface, group);
 
4083
            if (status)
 
4084
                return status;
 
4085
        }
 
4086
 
 
4087
        for (; pattern_index < _cairo_array_num_elements (&surface->patterns); pattern_index++) {
 
4088
            _cairo_array_copy_element (&surface->patterns, pattern_index, &pattern);
 
4089
            status = _cairo_pdf_surface_emit_pattern (surface, &pattern);
 
4090
            if (status)
 
4091
                return status;
 
4092
        }
 
4093
    }
 
4094
 
 
4095
    return CAIRO_STATUS_SUCCESS;
 
4096
}
 
4097
 
 
4098
static cairo_status_t
 
4099
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
 
4100
{
 
4101
    cairo_pdf_resource_t page, knockout, res;
 
4102
    cairo_status_t status;
 
4103
    int i, len;
 
4104
 
 
4105
    _cairo_pdf_group_resources_clear (&surface->resources);
 
4106
    if (surface->has_fallback_images) {
 
4107
        status = _cairo_pdf_surface_open_knockout_group (surface);
 
4108
        if (status)
 
4109
            return status;
 
4110
 
 
4111
        len = _cairo_array_num_elements (&surface->knockout_group);
 
4112
        for (i = 0; i < len; i++) {
 
4113
            _cairo_array_copy_element (&surface->knockout_group, i, &res);
 
4114
            _cairo_output_stream_printf (surface->output,
 
4115
                                         "/x%d Do\n",
 
4116
                                         res.id);
 
4117
            status = _cairo_pdf_surface_add_xobject (surface, res);
 
4118
            if (status)
 
4119
                return status;
 
4120
        }
 
4121
        _cairo_output_stream_printf (surface->output,
 
4122
                                     "/x%d Do\n",
 
4123
                                     surface->content.id);
 
4124
        status = _cairo_pdf_surface_add_xobject (surface, surface->content);
 
4125
        if (status)
 
4126
            return status;
 
4127
 
 
4128
        status = _cairo_pdf_surface_close_group (surface, &knockout);
 
4129
        if (status)
 
4130
            return status;
 
4131
 
 
4132
        _cairo_pdf_group_resources_clear (&surface->resources);
 
4133
        status = _cairo_pdf_surface_open_content_stream (surface, FALSE);
 
4134
        if (status)
 
4135
            return status;
 
4136
 
 
4137
        _cairo_output_stream_printf (surface->output,
 
4138
                                     "/x%d Do\n",
 
4139
                                     knockout.id);
 
4140
        status = _cairo_pdf_surface_add_xobject (surface, knockout);
 
4141
        if (status)
 
4142
            return status;
 
4143
 
 
4144
        status = _cairo_pdf_surface_close_content_stream (surface);
 
4145
        if (status)
 
4146
            return status;
 
4147
    }
 
4148
 
 
4149
    page = _cairo_pdf_surface_new_object (surface);
 
4150
    if (page.id == 0)
 
4151
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
4152
 
 
4153
    _cairo_output_stream_printf (surface->output,
 
4154
                                 "%d 0 obj\n"
 
4155
                                 "<< /Type /Page\n"
 
4156
                                 "   /Parent %d 0 R\n"
 
4157
                                 "   /MediaBox [ 0 0 %f %f ]\n"
 
4158
                                 "   /Contents %d 0 R\n"
 
4159
                                 "   /Group <<\n"
 
4160
                                 "      /Type /Group\n"
 
4161
                                 "      /S /Transparency\n"
 
4162
                                 "      /CS /DeviceRGB\n"
 
4163
                                 "   >>\n"
 
4164
                                 "   /Resources %d 0 R\n"
 
4165
                                 ">>\n"
 
4166
                                 "endobj\n",
 
4167
                                 page.id,
 
4168
                                 surface->pages_resource.id,
 
4169
                                 surface->width,
 
4170
                                 surface->height,
 
4171
                                 surface->content.id,
 
4172
                                 surface->content_resources.id);
 
4173
 
 
4174
    status = _cairo_array_append (&surface->pages, &page);
 
4175
    if (status)
 
4176
        return status;
 
4177
 
 
4178
    status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface);
 
4179
    if (status)
 
4180
        return status;
 
4181
 
 
4182
    return CAIRO_STATUS_SUCCESS;
 
4183
}
 
4184
 
 
4185
static cairo_int_status_t
 
4186
_cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t      *surface,
 
4187
                                                         cairo_surface_pattern_t *pattern)
 
4188
{
 
4189
    cairo_image_surface_t  *image;
 
4190
    void                   *image_extra;
 
4191
    cairo_int_status_t      status;
 
4192
    cairo_image_transparency_t transparency;
 
4193
 
 
4194
    status = _cairo_surface_acquire_source_image (pattern->surface,
 
4195
                                                  &image,
 
4196
                                                  &image_extra);
 
4197
    if (status)
 
4198
        return status;
 
4199
 
 
4200
    if (image->base.status)
 
4201
        return image->base.status;
 
4202
 
 
4203
    transparency = _cairo_image_analyze_transparency (image);
 
4204
    if (transparency == CAIRO_IMAGE_IS_OPAQUE)
 
4205
        status = CAIRO_STATUS_SUCCESS;
 
4206
    else
 
4207
        status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
 
4208
 
 
4209
    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
 
4210
 
 
4211
    return status;
 
4212
}
 
4213
 
 
4214
static cairo_bool_t
 
4215
_surface_pattern_supported (cairo_surface_pattern_t *pattern)
 
4216
{
 
4217
    cairo_extend_t extend;
 
4218
 
 
4219
    if (_cairo_surface_is_meta (pattern->surface))
 
4220
        return TRUE;
 
4221
 
 
4222
    if (pattern->surface->backend->acquire_source_image == NULL)
 
4223
        return FALSE;
 
4224
 
 
4225
    /* Does an ALPHA-only source surface even make sense? Maybe, but I
 
4226
     * don't think it's worth the extra code to support it. */
 
4227
 
 
4228
/* XXX: Need to write this function here...
 
4229
    content = cairo_surface_get_content (pattern->surface);
 
4230
    if (content == CAIRO_CONTENT_ALPHA)
 
4231
        return FALSE;
 
4232
*/
 
4233
 
 
4234
    extend = cairo_pattern_get_extend (&pattern->base);
 
4235
    switch (extend) {
 
4236
    case CAIRO_EXTEND_NONE:
 
4237
    case CAIRO_EXTEND_REPEAT:
 
4238
    case CAIRO_EXTEND_REFLECT:
 
4239
    /* There's no point returning FALSE for EXTEND_PAD, as the image
 
4240
     * surface does not currently implement it either */
 
4241
    case CAIRO_EXTEND_PAD:
 
4242
        return TRUE;
 
4243
    }
 
4244
 
 
4245
    ASSERT_NOT_REACHED;
 
4246
    return FALSE;
 
4247
}
 
4248
 
 
4249
static cairo_bool_t
 
4250
_gradient_pattern_supported (cairo_pattern_t *pattern)
 
4251
{
 
4252
    cairo_extend_t extend;
 
4253
 
 
4254
    extend = cairo_pattern_get_extend (pattern);
 
4255
 
 
4256
 
 
4257
    /* Radial gradients are currently only supported with EXTEND_NONE
 
4258
     * and EXTEND_PAD and when one circle is inside the other. */
 
4259
    if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
 
4260
        double x1, y1, x2, y2, r1, r2, d;
 
4261
        cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
 
4262
 
 
4263
        if (extend == CAIRO_EXTEND_REPEAT ||
 
4264
            extend == CAIRO_EXTEND_REFLECT) {
 
4265
            return FALSE;
 
4266
        }
 
4267
 
 
4268
        x1 = _cairo_fixed_to_double (radial->c1.x);
 
4269
        y1 = _cairo_fixed_to_double (radial->c1.y);
 
4270
        r1 = _cairo_fixed_to_double (radial->r1);
 
4271
        x2 = _cairo_fixed_to_double (radial->c2.x);
 
4272
        y2 = _cairo_fixed_to_double (radial->c2.y);
 
4273
        r2 = _cairo_fixed_to_double (radial->r2);
 
4274
 
 
4275
        d = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
 
4276
        if (d > fabs(r2 - r1)) {
 
4277
            return FALSE;
 
4278
        }
 
4279
    }
 
4280
 
 
4281
    return TRUE;
 
4282
}
 
4283
 
 
4284
static cairo_bool_t
 
4285
_pattern_supported (cairo_pattern_t *pattern)
 
4286
{
 
4287
    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
 
4288
        return TRUE;
 
4289
 
 
4290
    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
 
4291
        pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
 
4292
        return _gradient_pattern_supported (pattern);
 
4293
 
 
4294
    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
 
4295
        return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
 
4296
 
 
4297
    return FALSE;
 
4298
}
 
4299
 
 
4300
static cairo_int_status_t
 
4301
_cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t  *surface,
 
4302
                                      cairo_operator_t      op,
 
4303
                                      cairo_pattern_t      *pattern)
 
4304
{
 
4305
    if (surface->force_fallbacks && surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 
4306
        return CAIRO_INT_STATUS_UNSUPPORTED;
 
4307
 
 
4308
    if (! _pattern_supported (pattern))
 
4309
        return CAIRO_INT_STATUS_UNSUPPORTED;
 
4310
 
 
4311
    if (op == CAIRO_OPERATOR_OVER) {
 
4312
        if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
 
4313
            cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
 
4314
 
 
4315
            if ( _cairo_surface_is_meta (surface_pattern->surface))
 
4316
                return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
 
4317
        }
 
4318
    }
 
4319
 
 
4320
    if (op == CAIRO_OPERATOR_OVER)
 
4321
        return CAIRO_STATUS_SUCCESS;
 
4322
 
 
4323
    /* The SOURCE operator is supported if the pattern is opaque or if
 
4324
     * there is nothing painted underneath. */
 
4325
    if (op == CAIRO_OPERATOR_SOURCE) {
 
4326
        if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
 
4327
            cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
 
4328
 
 
4329
            if (_cairo_surface_is_meta (surface_pattern->surface)) {
 
4330
                if (_cairo_pattern_is_opaque (pattern)) {
 
4331
                    return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
 
4332
                } else {
 
4333
                    /* FIXME: The analysis surface does not yet have
 
4334
                     * the capability to analyze a non opaque meta
 
4335
                     * surface and mark it supported if there is
 
4336
                     * nothing underneath. For now meta surfaces of
 
4337
                     * type CONTENT_COLOR_ALPHA painted with
 
4338
                     * OPERATOR_SOURCE will result in a fallback
 
4339
                     * image. */
 
4340
 
 
4341
                    return CAIRO_INT_STATUS_UNSUPPORTED;
 
4342
                }
 
4343
            } else {
 
4344
                return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
 
4345
                                                                                surface_pattern);
 
4346
            }
 
4347
        }
 
4348
 
 
4349
        if (_cairo_pattern_is_opaque (pattern))
 
4350
            return CAIRO_STATUS_SUCCESS;
 
4351
        else
 
4352
            return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
 
4353
    }
 
4354
 
 
4355
    return CAIRO_INT_STATUS_UNSUPPORTED;
 
4356
}
 
4357
 
 
4358
static cairo_bool_t
 
4359
_cairo_pdf_surface_operation_supported (cairo_pdf_surface_t  *surface,
 
4360
                                        cairo_operator_t      op,
 
4361
                                        cairo_pattern_t      *pattern)
 
4362
{
 
4363
    if (_cairo_pdf_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
 
4364
        return TRUE;
 
4365
    else
 
4366
        return FALSE;
 
4367
}
 
4368
 
 
4369
static cairo_int_status_t
 
4370
_cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
 
4371
{
 
4372
    cairo_status_t status;
 
4373
 
 
4374
    status = _cairo_pdf_surface_close_content_stream (surface);
 
4375
    if (status)
 
4376
        return status;
 
4377
 
 
4378
    status = _cairo_array_append (&surface->knockout_group, &surface->content);
 
4379
    if (status)
 
4380
        return status;
 
4381
 
 
4382
    _cairo_pdf_group_resources_clear (&surface->resources);
 
4383
    return _cairo_pdf_surface_open_content_stream (surface, TRUE);
 
4384
}
 
4385
 
 
4386
static cairo_int_status_t
 
4387
_cairo_pdf_surface_paint (void                  *abstract_surface,
 
4388
                          cairo_operator_t       op,
 
4389
                          cairo_pattern_t       *source)
 
4390
{
 
4391
    cairo_pdf_surface_t *surface = abstract_surface;
 
4392
    cairo_status_t status;
 
4393
    cairo_pdf_smask_group_t *group;
 
4394
    cairo_pdf_resource_t pattern_res, gstate_res;
 
4395
 
 
4396
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
 
4397
        return _cairo_pdf_surface_analyze_operation (surface, op, source);
 
4398
    } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
 
4399
        status = _cairo_pdf_surface_start_fallback (surface);
 
4400
        if (status)
 
4401
            return status;
 
4402
    }
 
4403
 
 
4404
    assert (_cairo_pdf_surface_operation_supported (surface, op, source));
 
4405
 
 
4406
    pattern_res.id = 0;
 
4407
    gstate_res.id = 0;
 
4408
    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
 
4409
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
 
4410
        return CAIRO_STATUS_SUCCESS;
 
4411
    if (status)
 
4412
        return status;
 
4413
 
 
4414
    if (gstate_res.id != 0) {
 
4415
        group = _cairo_pdf_surface_create_smask_group (surface);
 
4416
        if (group == NULL)
 
4417
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
4418
 
 
4419
        group->operation = PDF_PAINT;
 
4420
        group->source = cairo_pattern_reference (source);
 
4421
        group->source_res = pattern_res;
 
4422
        status = _cairo_pdf_surface_add_smask_group (surface, group);
 
4423
        if (status) {
 
4424
            _cairo_pdf_smask_group_destroy (group);
 
4425
            return status;
 
4426
        }
 
4427
 
 
4428
        status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 
4429
        if (status)
 
4430
            return status;
 
4431
 
 
4432
        status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
 
4433
        if (status)
 
4434
            return status;
 
4435
 
 
4436
        status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
4437
        if (status)
 
4438
            return status;
 
4439
 
 
4440
        _cairo_output_stream_printf (surface->output,
 
4441
                                     "q /s%d gs /x%d Do Q\n",
 
4442
                                     gstate_res.id,
 
4443
                                     group->group_res.id);
 
4444
    } else {
 
4445
        status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
 
4446
        if (status)
 
4447
            return status;
 
4448
 
 
4449
        _cairo_output_stream_printf (surface->output,
 
4450
                                     "0 0 %f %f re f\n",
 
4451
                                     surface->width, surface->height);
 
4452
 
 
4453
        status = _cairo_pdf_surface_unselect_pattern (surface);
 
4454
        if (status)
 
4455
            return status;
 
4456
    }
 
4457
 
 
4458
    return _cairo_output_stream_get_status (surface->output);
 
4459
}
 
4460
 
 
4461
static cairo_int_status_t
 
4462
_cairo_pdf_surface_mask (void                   *abstract_surface,
 
4463
                         cairo_operator_t        op,
 
4464
                         cairo_pattern_t        *source,
 
4465
                         cairo_pattern_t        *mask)
 
4466
{
 
4467
    cairo_pdf_surface_t *surface = abstract_surface;
 
4468
    cairo_pdf_smask_group_t *group;
 
4469
    cairo_status_t status;
 
4470
 
 
4471
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
 
4472
        cairo_status_t source_status, mask_status;
 
4473
 
 
4474
        source_status =  _cairo_pdf_surface_analyze_operation (surface, op, source);
 
4475
        if (source_status != CAIRO_STATUS_SUCCESS &&
 
4476
            source_status < CAIRO_INT_STATUS_UNSUPPORTED)
 
4477
            return source_status;
 
4478
 
 
4479
        mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask);
 
4480
        if (mask_status != CAIRO_STATUS_SUCCESS &&
 
4481
            mask_status < CAIRO_INT_STATUS_UNSUPPORTED)
 
4482
            return mask_status;
 
4483
 
 
4484
        /* return the most important status from either the source or mask */
 
4485
        if (source_status == CAIRO_INT_STATUS_UNSUPPORTED ||
 
4486
            mask_status == CAIRO_INT_STATUS_UNSUPPORTED)
 
4487
            return CAIRO_INT_STATUS_UNSUPPORTED;
 
4488
 
 
4489
        if (source_status == CAIRO_INT_STATUS_IMAGE_FALLBACK ||
 
4490
            mask_status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
 
4491
            return CAIRO_INT_STATUS_IMAGE_FALLBACK;
 
4492
 
 
4493
        if (source_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN ||
 
4494
            mask_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 
4495
            return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
 
4496
 
 
4497
        return CAIRO_STATUS_SUCCESS;
 
4498
    } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
 
4499
        status = _cairo_pdf_surface_start_fallback (surface);
 
4500
        if (status)
 
4501
            return status;
 
4502
    }
 
4503
 
 
4504
    assert (_cairo_pdf_surface_operation_supported (surface, op, source));
 
4505
    assert (_cairo_pdf_surface_operation_supported (surface, op, mask));
 
4506
 
 
4507
    group = _cairo_pdf_surface_create_smask_group (surface);
 
4508
    if (group == NULL)
 
4509
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
4510
 
 
4511
    group->operation = PDF_MASK;
 
4512
    group->source = cairo_pattern_reference (source);
 
4513
    group->mask = cairo_pattern_reference (mask);
 
4514
    group->source_res = _cairo_pdf_surface_new_object (surface);
 
4515
    if (group->source_res.id == 0) {
 
4516
        _cairo_pdf_smask_group_destroy (group);
 
4517
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
4518
    }
 
4519
 
 
4520
    status = _cairo_pdf_surface_add_smask_group (surface, group);
 
4521
    if (status) {
 
4522
        _cairo_pdf_smask_group_destroy (group);
 
4523
        return status;
 
4524
    }
 
4525
 
 
4526
    status = _cairo_pdf_surface_add_smask (surface, group->group_res);
 
4527
    if (status)
 
4528
        return status;
 
4529
 
 
4530
    status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
 
4531
    if (status)
 
4532
        return status;
 
4533
 
 
4534
    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
4535
    if (status)
 
4536
        return status;
 
4537
 
 
4538
    _cairo_output_stream_printf (surface->output,
 
4539
                                 "q /s%d gs /x%d Do Q\n",
 
4540
                                 group->group_res.id,
 
4541
                                 group->source_res.id);
 
4542
 
 
4543
    return _cairo_output_stream_get_status (surface->output);
 
4544
}
 
4545
 
 
4546
static cairo_int_status_t
 
4547
_cairo_pdf_surface_stroke (void                 *abstract_surface,
 
4548
                           cairo_operator_t      op,
 
4549
                           cairo_pattern_t      *source,
 
4550
                           cairo_path_fixed_t   *path,
 
4551
                           cairo_stroke_style_t *style,
 
4552
                           cairo_matrix_t       *ctm,
 
4553
                           cairo_matrix_t       *ctm_inverse,
 
4554
                           double                tolerance,
 
4555
                           cairo_antialias_t     antialias)
 
4556
{
 
4557
    cairo_pdf_surface_t *surface = abstract_surface;
 
4558
    cairo_status_t status;
 
4559
    cairo_pdf_smask_group_t *group;
 
4560
    cairo_pdf_resource_t pattern_res, gstate_res;
 
4561
 
 
4562
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 
4563
        return _cairo_pdf_surface_analyze_operation (surface, op, source);
 
4564
 
 
4565
    assert (_cairo_pdf_surface_operation_supported (surface, op, source));
 
4566
 
 
4567
    pattern_res.id = 0;
 
4568
    gstate_res.id = 0;
 
4569
    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
 
4570
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
 
4571
        return CAIRO_STATUS_SUCCESS;
 
4572
    if (status)
 
4573
        return status;
 
4574
 
 
4575
    if (gstate_res.id != 0) {
 
4576
        group = _cairo_pdf_surface_create_smask_group (surface);
 
4577
        if (group == NULL)
 
4578
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
4579
 
 
4580
        group->operation = PDF_STROKE;
 
4581
        group->source = cairo_pattern_reference (source);
 
4582
        group->source_res = pattern_res;
 
4583
        status = _cairo_path_fixed_init_copy (&group->path, path);
 
4584
        if (status) {
 
4585
            _cairo_pdf_smask_group_destroy (group);
 
4586
            return status;
 
4587
        }
 
4588
 
 
4589
        group->style = style;
 
4590
        group->ctm = *ctm;
 
4591
        group->ctm_inverse = *ctm_inverse;
 
4592
        status = _cairo_pdf_surface_add_smask_group (surface, group);
 
4593
        if (status) {
 
4594
            _cairo_pdf_smask_group_destroy (group);
 
4595
            return status;
 
4596
        }
 
4597
 
 
4598
        status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 
4599
        if (status)
 
4600
            return status;
 
4601
 
 
4602
        status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
 
4603
        if (status)
 
4604
            return status;
 
4605
 
 
4606
        status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
4607
        if (status)
 
4608
            return status;
 
4609
 
 
4610
        _cairo_output_stream_printf (surface->output,
 
4611
                                     "q /s%d gs /x%d Do Q\n",
 
4612
                                     gstate_res.id,
 
4613
                                     group->group_res.id);
 
4614
    } else {
 
4615
        status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
 
4616
        if (status)
 
4617
            return status;
 
4618
 
 
4619
        status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
 
4620
                                              path,
 
4621
                                              style,
 
4622
                                              ctm,
 
4623
                                              ctm_inverse);
 
4624
        if (status)
 
4625
            return status;
 
4626
 
 
4627
        status = _cairo_pdf_surface_unselect_pattern (surface);
 
4628
        if (status)
 
4629
            return status;
 
4630
    }
 
4631
 
 
4632
    return _cairo_output_stream_get_status (surface->output);
 
4633
}
 
4634
 
 
4635
static cairo_int_status_t
 
4636
_cairo_pdf_surface_fill (void                   *abstract_surface,
 
4637
                         cairo_operator_t        op,
 
4638
                         cairo_pattern_t        *source,
 
4639
                         cairo_path_fixed_t     *path,
 
4640
                         cairo_fill_rule_t       fill_rule,
 
4641
                         double                  tolerance,
 
4642
                         cairo_antialias_t       antialias)
 
4643
{
 
4644
    cairo_pdf_surface_t *surface = abstract_surface;
 
4645
    cairo_status_t status;
 
4646
    cairo_pdf_smask_group_t *group;
 
4647
    cairo_pdf_resource_t pattern_res, gstate_res;
 
4648
 
 
4649
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
 
4650
        return _cairo_pdf_surface_analyze_operation (surface, op, source);
 
4651
    } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
 
4652
        status = _cairo_pdf_surface_start_fallback (surface);
 
4653
        if (status)
 
4654
            return status;
 
4655
    }
 
4656
 
 
4657
    assert (_cairo_pdf_surface_operation_supported (surface, op, source));
 
4658
 
 
4659
    pattern_res.id = 0;
 
4660
    gstate_res.id = 0;
 
4661
    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
 
4662
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
 
4663
        return CAIRO_STATUS_SUCCESS;
 
4664
    if (status)
 
4665
        return status;
 
4666
 
 
4667
    if (gstate_res.id != 0) {
 
4668
        group = _cairo_pdf_surface_create_smask_group (surface);
 
4669
        if (group == NULL)
 
4670
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
4671
 
 
4672
        group->operation = PDF_FILL;
 
4673
        group->source = cairo_pattern_reference (source);
 
4674
        group->source_res = pattern_res;
 
4675
        status = _cairo_path_fixed_init_copy (&group->path, path);
 
4676
        if (status) {
 
4677
            _cairo_pdf_smask_group_destroy (group);
 
4678
            return status;
 
4679
        }
 
4680
 
 
4681
        group->fill_rule = fill_rule;
 
4682
        status = _cairo_pdf_surface_add_smask_group (surface, group);
 
4683
        if (status) {
 
4684
            _cairo_pdf_smask_group_destroy (group);
 
4685
            return status;
 
4686
        }
 
4687
 
 
4688
        status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 
4689
        if (status)
 
4690
            return status;
 
4691
 
 
4692
        status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
 
4693
        if (status)
 
4694
            return status;
 
4695
 
 
4696
        status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
4697
        if (status)
 
4698
            return status;
 
4699
 
 
4700
        _cairo_output_stream_printf (surface->output,
 
4701
                                     "q /s%d gs /x%d Do Q\n",
 
4702
                                     gstate_res.id,
 
4703
                                     group->group_res.id);
 
4704
    } else {
 
4705
        status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
 
4706
        if (status)
 
4707
            return status;
 
4708
 
 
4709
        status = _cairo_pdf_operators_fill (&surface->pdf_operators,
 
4710
                                            path,
 
4711
                                            fill_rule);
 
4712
        if (status)
 
4713
            return status;
 
4714
 
 
4715
        status = _cairo_pdf_surface_unselect_pattern (surface);
 
4716
        if (status)
 
4717
            return status;
 
4718
    }
 
4719
 
 
4720
    return _cairo_output_stream_get_status (surface->output);
 
4721
}
 
4722
 
 
4723
static cairo_int_status_t
 
4724
_cairo_pdf_surface_fill_stroke (void                 *abstract_surface,
 
4725
                                cairo_operator_t      fill_op,
 
4726
                                cairo_pattern_t      *fill_source,
 
4727
                                cairo_fill_rule_t     fill_rule,
 
4728
                                double                fill_tolerance,
 
4729
                                cairo_antialias_t     fill_antialias,
 
4730
                                cairo_path_fixed_t   *path,
 
4731
                                cairo_operator_t      stroke_op,
 
4732
                                cairo_pattern_t      *stroke_source,
 
4733
                                cairo_stroke_style_t *stroke_style,
 
4734
                                cairo_matrix_t       *stroke_ctm,
 
4735
                                cairo_matrix_t       *stroke_ctm_inverse,
 
4736
                                double                stroke_tolerance,
 
4737
                                cairo_antialias_t     stroke_antialias)
 
4738
{
 
4739
    cairo_pdf_surface_t *surface = abstract_surface;
 
4740
    cairo_status_t status;
 
4741
    cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res;
 
4742
 
 
4743
    /* During analysis we return unsupported and let the _fill and
 
4744
     * _stroke functions that are on the fallback path do the analysis
 
4745
     * for us. During render we may still encounter unsupported
 
4746
     * combinations of fill/stroke patterns. However we can return
 
4747
     * unsupported anytime to let the _fill and _stroke functions take
 
4748
     * over.
 
4749
     */
 
4750
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 
4751
        return CAIRO_INT_STATUS_UNSUPPORTED;
 
4752
 
 
4753
    /* PDF rendering of fill-stroke is not the same as cairo when
 
4754
     * either the fill or stroke is not opaque.
 
4755
     */
 
4756
    if ( !_cairo_pattern_is_opaque (fill_source) ||
 
4757
         !_cairo_pattern_is_opaque (stroke_source))
 
4758
    {
 
4759
        return CAIRO_INT_STATUS_UNSUPPORTED;
 
4760
    }
 
4761
 
 
4762
    fill_pattern_res.id = 0;
 
4763
    gstate_res.id = 0;
 
4764
    status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
 
4765
                                                 &fill_pattern_res,
 
4766
                                                 &gstate_res);
 
4767
    if (status)
 
4768
        return status;
 
4769
 
 
4770
    assert (gstate_res.id == 0);
 
4771
 
 
4772
    stroke_pattern_res.id = 0;
 
4773
    gstate_res.id = 0;
 
4774
    status = _cairo_pdf_surface_add_pdf_pattern (surface,
 
4775
                                                 stroke_source,
 
4776
                                                 &stroke_pattern_res,
 
4777
                                                 &gstate_res);
 
4778
    if (status)
 
4779
        return status;
 
4780
 
 
4781
    assert (gstate_res.id == 0);
 
4782
 
 
4783
    /* As PDF has separate graphics state for fill and stroke we can
 
4784
     * select both at the same time */
 
4785
    status = _cairo_pdf_surface_select_pattern (surface, fill_source,
 
4786
                                                fill_pattern_res, FALSE);
 
4787
    if (status)
 
4788
        return status;
 
4789
 
 
4790
    status = _cairo_pdf_surface_select_pattern (surface, stroke_source,
 
4791
                                                stroke_pattern_res, TRUE);
 
4792
    if (status)
 
4793
        return status;
 
4794
 
 
4795
    status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators,
 
4796
                                               path,
 
4797
                                               fill_rule,
 
4798
                                               stroke_style,
 
4799
                                               stroke_ctm,
 
4800
                                               stroke_ctm_inverse);
 
4801
    if (status)
 
4802
        return status;
 
4803
 
 
4804
    status = _cairo_pdf_surface_unselect_pattern (surface);
 
4805
    if (status)
 
4806
        return status;
 
4807
 
 
4808
    return _cairo_output_stream_get_status (surface->output);
 
4809
}
 
4810
 
 
4811
static cairo_bool_t
 
4812
_cairo_pdf_surface_has_show_text_glyphs (void                   *abstract_surface)
 
4813
{
 
4814
    return TRUE;
 
4815
}
 
4816
 
 
4817
static cairo_int_status_t
 
4818
_cairo_pdf_surface_show_text_glyphs (void                       *abstract_surface,
 
4819
                                     cairo_operator_t            op,
 
4820
                                     cairo_pattern_t            *source,
 
4821
                                     const char                 *utf8,
 
4822
                                     int                         utf8_len,
 
4823
                                     cairo_glyph_t              *glyphs,
 
4824
                                     int                         num_glyphs,
 
4825
                                     const cairo_text_cluster_t *clusters,
 
4826
                                     int                         num_clusters,
 
4827
                                     cairo_text_cluster_flags_t  cluster_flags,
 
4828
                                     cairo_scaled_font_t        *scaled_font)
 
4829
{
 
4830
    cairo_pdf_surface_t *surface = abstract_surface;
 
4831
    cairo_status_t status;
 
4832
    cairo_pdf_smask_group_t *group;
 
4833
    cairo_pdf_resource_t pattern_res, gstate_res;
 
4834
 
 
4835
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 
4836
        return _cairo_pdf_surface_analyze_operation (surface, op, source);
 
4837
 
 
4838
    assert (_cairo_pdf_surface_operation_supported (surface, op, source));
 
4839
 
 
4840
    pattern_res.id = 0;
 
4841
    gstate_res.id = 0;
 
4842
    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res);
 
4843
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
 
4844
        return CAIRO_STATUS_SUCCESS;
 
4845
    if (status)
 
4846
        return status;
 
4847
 
 
4848
    if (gstate_res.id != 0) {
 
4849
        group = _cairo_pdf_surface_create_smask_group (surface);
 
4850
        if (group == NULL)
 
4851
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
4852
 
 
4853
        group->operation = PDF_SHOW_GLYPHS;
 
4854
        group->source = cairo_pattern_reference (source);
 
4855
        group->source_res = pattern_res;
 
4856
 
 
4857
        if (utf8_len) {
 
4858
            group->utf8 = malloc (utf8_len);
 
4859
            if (group->utf8 == NULL) {
 
4860
                _cairo_pdf_smask_group_destroy (group);
 
4861
                return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
4862
            }
 
4863
            memcpy (group->utf8, utf8, utf8_len);
 
4864
        }
 
4865
        group->utf8_len = utf8_len;
 
4866
 
 
4867
        if (num_glyphs) {
 
4868
            group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
 
4869
            if (group->glyphs == NULL) {
 
4870
                _cairo_pdf_smask_group_destroy (group);
 
4871
                return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
4872
            }
 
4873
            memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
 
4874
        }
 
4875
        group->num_glyphs = num_glyphs;
 
4876
 
 
4877
        if (num_clusters) {
 
4878
            group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
 
4879
            if (group->clusters == NULL) {
 
4880
                _cairo_pdf_smask_group_destroy (group);
 
4881
                return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
4882
            }
 
4883
            memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
 
4884
        }
 
4885
        group->num_clusters = num_clusters;
 
4886
 
 
4887
        group->scaled_font = cairo_scaled_font_reference (scaled_font);
 
4888
        status = _cairo_pdf_surface_add_smask_group (surface, group);
 
4889
        if (status) {
 
4890
            _cairo_pdf_smask_group_destroy (group);
 
4891
            return status;
 
4892
        }
 
4893
 
 
4894
        status = _cairo_pdf_surface_add_smask (surface, gstate_res);
 
4895
        if (status)
 
4896
            return status;
 
4897
 
 
4898
        status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
 
4899
        if (status)
 
4900
            return status;
 
4901
 
 
4902
        status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
4903
        if (status)
 
4904
            return status;
 
4905
 
 
4906
        _cairo_output_stream_printf (surface->output,
 
4907
                                     "q /s%d gs /x%d Do Q\n",
 
4908
                                     gstate_res.id,
 
4909
                                     group->group_res.id);
 
4910
    } else {
 
4911
        status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
 
4912
        if (status)
 
4913
            return status;
 
4914
 
 
4915
        /* Each call to show_glyphs() with a transclucent pattern must
 
4916
         * be in a separate text object otherwise overlapping text
 
4917
         * from separate calls to show_glyphs will not composite with
 
4918
         * each other. */
 
4919
        if (! _cairo_pattern_is_opaque (source)) {
 
4920
            status = _cairo_pdf_operators_flush (&surface->pdf_operators);
 
4921
            if (status)
 
4922
                return status;
 
4923
        }
 
4924
 
 
4925
        status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
 
4926
                                                        utf8, utf8_len,
 
4927
                                                        glyphs, num_glyphs,
 
4928
                                                        clusters, num_clusters,
 
4929
                                                        cluster_flags,
 
4930
                                                        scaled_font);
 
4931
        if (status)
 
4932
            return status;
 
4933
 
 
4934
        status = _cairo_pdf_surface_unselect_pattern (surface);
 
4935
        if (status)
 
4936
            return status;
 
4937
    }
 
4938
 
 
4939
    return _cairo_output_stream_get_status (surface->output);
 
4940
}
 
4941
 
 
4942
 
 
4943
static void
 
4944
_cairo_pdf_surface_set_paginated_mode (void                     *abstract_surface,
 
4945
                                       cairo_paginated_mode_t    paginated_mode)
 
4946
{
 
4947
    cairo_pdf_surface_t *surface = abstract_surface;
 
4948
 
 
4949
    surface->paginated_mode = paginated_mode;
 
4950
}
 
4951
 
 
4952
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
 
4953
    CAIRO_SURFACE_TYPE_PDF,
 
4954
    _cairo_pdf_surface_create_similar,
 
4955
    _cairo_pdf_surface_finish,
 
4956
    NULL, /* acquire_source_image */
 
4957
    NULL, /* release_source_image */
 
4958
    NULL, /* acquire_dest_image */
 
4959
    NULL, /* release_dest_image */
 
4960
    NULL, /* clone_similar */
 
4961
    NULL, /* composite */
 
4962
    NULL, /* fill_rectangles */
 
4963
    NULL, /* composite_trapezoids */
 
4964
    NULL,  /* _cairo_pdf_surface_copy_page */
 
4965
    _cairo_pdf_surface_show_page,
 
4966
    NULL, /* set_clip_region */
 
4967
    _cairo_pdf_surface_intersect_clip_path,
 
4968
    _cairo_pdf_surface_get_extents,
 
4969
    NULL, /* old_show_glyphs */
 
4970
    _cairo_pdf_surface_get_font_options,
 
4971
    NULL, /* flush */
 
4972
    NULL, /* mark_dirty_rectangle */
 
4973
    NULL, /* scaled_font_fini */
 
4974
    NULL, /* scaled_glyph_fini */
 
4975
 
 
4976
    /* Here are the drawing functions */
 
4977
 
 
4978
    _cairo_pdf_surface_paint,
 
4979
    _cairo_pdf_surface_mask,
 
4980
    _cairo_pdf_surface_stroke,
 
4981
    _cairo_pdf_surface_fill,
 
4982
    NULL, /* show_glyphs */
 
4983
    NULL, /* snapshot */
 
4984
 
 
4985
    NULL, /* is_compatible */
 
4986
    NULL, /* reset */
 
4987
    _cairo_pdf_surface_fill_stroke,
 
4988
    NULL, /* create_solid_pattern_surface */
 
4989
    _cairo_pdf_surface_has_show_text_glyphs,
 
4990
    _cairo_pdf_surface_show_text_glyphs,
 
4991
};
 
4992
 
 
4993
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
 
4994
    _cairo_pdf_surface_start_page,
 
4995
    _cairo_pdf_surface_set_paginated_mode,
 
4996
    NULL, /* set_bounding_box */
 
4997
    _cairo_pdf_surface_has_fallback_images,
 
4998
};