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
4
* Copyright Ā© 2004 Red Hat, Inc
5
* Copyright Ā© 2006 Red Hat, Inc
6
* Copyright Ā© 2007, 2008 Adrian Johnson
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.
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
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/
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.
31
* The Original Code is the cairo graphics library.
33
* The Initial Developer of the Original Code is University of Southern
37
* Kristian HĆøgsberg <krh@redhat.com>
38
* Carl Worth <cworth@cworth.org>
39
* Adrian Johnson <ajohnson@redneon.com>
42
#define _BSD_SOURCE /* for snprintf() */
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"
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.
62
* - Backend specific meta data.
66
* Page Structure of the Generated PDF:
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
77
* This PDF surface has three types of streams:
82
* Calling _cairo_output_stream_printf (surface->output, ...) will
83
* write to the currently open 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 ()
90
* PDF Streams are written directly to the PDF file. They are used for
91
* fonts, images and patterns.
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 ()
98
* The Content Stream contains the text and graphics operators.
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 ()
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.
112
typedef struct _cairo_pdf_object {
114
} cairo_pdf_object_t;
116
typedef struct _cairo_pdf_font {
117
unsigned int font_id;
118
unsigned int subset_id;
119
cairo_pdf_resource_t subset_resource;
122
typedef struct _cairo_pdf_rgb_linear_function {
123
cairo_pdf_resource_t resource;
126
} cairo_pdf_rgb_linear_function_t;
128
typedef struct _cairo_pdf_alpha_linear_function {
129
cairo_pdf_resource_t resource;
132
} cairo_pdf_alpha_linear_function_t;
134
static cairo_pdf_resource_t
135
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
138
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
141
_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
143
static cairo_status_t
144
_cairo_pdf_surface_add_font (unsigned int font_id,
145
unsigned int subset_id,
149
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
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,
156
...) CAIRO_PRINTF_FORMAT(4, 5);
157
static cairo_status_t
158
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface);
160
static cairo_status_t
161
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
164
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
166
static cairo_pdf_resource_t
167
_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface);
169
static cairo_pdf_resource_t
170
_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface);
173
_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
175
static cairo_status_t
176
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
178
static cairo_status_t
179
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
181
static const cairo_surface_backend_t cairo_pdf_surface_backend;
182
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
184
static cairo_pdf_resource_t
185
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
187
cairo_pdf_resource_t resource;
188
cairo_status_t status;
189
cairo_pdf_object_t object;
191
object.offset = _cairo_output_stream_get_position (surface->output);
193
status = _cairo_array_append (&surface->objects, &object);
199
resource = surface->next_available_resource;
200
surface->next_available_resource.id++;
206
_cairo_pdf_surface_update_object (cairo_pdf_surface_t *surface,
207
cairo_pdf_resource_t resource)
209
cairo_pdf_object_t *object;
211
object = _cairo_array_index (&surface->objects, resource.id - 1);
212
object->offset = _cairo_output_stream_get_position (surface->output);
216
_cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
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);
227
static cairo_surface_t *
228
_cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
232
cairo_pdf_surface_t *surface;
233
cairo_status_t status, status_ignored;
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));
242
_cairo_surface_init (&surface->base, &cairo_pdf_surface_backend,
243
CAIRO_CONTENT_COLOR_ALPHA);
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);
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));
259
_cairo_pdf_group_resources_init (&surface->resources);
261
surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
262
if (! surface->font_subsets) {
263
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
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);
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;
281
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
283
surface->force_fallbacks = FALSE;
284
surface->select_pattern_gstate_saved = FALSE;
285
surface->current_pattern_is_solid_color = FALSE;
287
_cairo_pdf_operators_init (&surface->pdf_operators,
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,
295
/* Document header */
296
_cairo_output_stream_printf (surface->output,
298
_cairo_output_stream_printf (surface->output,
299
"%%%c%c%c%c\n", 181, 237, 174, 251);
301
surface->paginated_surface = _cairo_paginated_surface_create (
303
CAIRO_CONTENT_COLOR_ALPHA,
305
&cairo_pdf_surface_paginated_backend);
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;
315
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
317
_cairo_array_fini (&surface->objects);
320
/* destroy stream on behalf of caller */
321
status_ignored = _cairo_output_stream_destroy (output);
323
return _cairo_surface_create_in_error (status);
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)
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.
336
* Return value: a pointer to the newly created surface. The caller
337
* owns the surface and should call cairo_surface_destroy() when done
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.
347
cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func,
349
double width_in_points,
350
double height_in_points)
352
cairo_output_stream_t *output;
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));
358
return _cairo_pdf_surface_create_for_stream_internal (output,
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)
369
* Creates a PDF surface of the specified size in points to be written
372
* Return value: a pointer to the newly created surface. The caller
373
* owns the surface and should call cairo_surface_destroy() when done
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.
383
cairo_pdf_surface_create (const char *filename,
384
double width_in_points,
385
double height_in_points)
387
cairo_output_stream_t *output;
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));
393
return _cairo_pdf_surface_create_for_stream_internal (output,
399
_cairo_surface_is_pdf (cairo_surface_t *surface)
401
return surface->backend == &cairo_pdf_surface_backend;
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.
408
static cairo_status_t
409
_extract_pdf_surface (cairo_surface_t *surface,
410
cairo_pdf_surface_t **pdf_surface)
412
cairo_surface_t *target;
415
return surface->status;
417
if (! _cairo_surface_is_paginated (surface))
418
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
420
target = _cairo_paginated_surface_get_target (surface);
422
return target->status;
424
if (! _cairo_surface_is_pdf (target))
425
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
427
*pdf_surface = (cairo_pdf_surface_t *) target;
429
return CAIRO_STATUS_SUCCESS;
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)
438
* Changes the size of a PDF surface for the current (and
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().
450
cairo_pdf_surface_set_size (cairo_surface_t *surface,
451
double width_in_points,
452
double height_in_points)
454
cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
455
cairo_status_t status;
457
status = _extract_pdf_surface (surface, &pdf_surface);
459
status = _cairo_surface_set_error (surface, status);
463
_cairo_pdf_surface_set_size_internal (pdf_surface,
466
status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
470
status = _cairo_surface_set_error (surface, status);
474
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
477
cairo_pdf_pattern_t *pattern;
478
cairo_pdf_smask_group_t *group;
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);
485
_cairo_array_truncate (&surface->patterns, 0);
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);
492
_cairo_array_truncate (&surface->smask_groups, 0);
493
_cairo_array_truncate (&surface->knockout_group, 0);
497
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
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));
507
_cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
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);
517
_cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
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);
526
static cairo_status_t
527
_cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
533
cairo_status_t status;
534
cairo_pdf_group_resources_t *res = &surface->resources;
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) {
541
return CAIRO_STATUS_SUCCESS;
545
status = _cairo_array_append (&res->alphas, &alpha);
549
*index = _cairo_array_num_elements (&res->alphas) - 1;
551
return CAIRO_STATUS_SUCCESS;
554
static cairo_status_t
555
_cairo_pdf_surface_add_smask (cairo_pdf_surface_t *surface,
556
cairo_pdf_resource_t smask)
558
return _cairo_array_append (&(surface->resources.smasks), &smask);
561
static cairo_status_t
562
_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t *surface,
563
cairo_pdf_resource_t pattern)
565
return _cairo_array_append (&(surface->resources.patterns), &pattern);
568
static cairo_status_t
569
_cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface,
570
cairo_pdf_resource_t xobject)
572
return _cairo_array_append (&(surface->resources.xobjects), &xobject);
575
static cairo_status_t
576
_cairo_pdf_surface_add_font (unsigned int font_id,
577
unsigned int subset_id,
580
cairo_pdf_surface_t *surface = closure;
581
cairo_pdf_font_t font;
583
cairo_status_t status;
584
cairo_pdf_group_resources_t *res = &surface->resources;
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;
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);
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);
608
status = _cairo_array_append (&surface->fonts, &font);
612
return _cairo_array_append (&res->fonts, &font);
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)
620
cairo_pdf_font_t font;
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;
630
font.subset_resource.id = 0;
631
return font.subset_resource;
635
_cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface,
636
cairo_pdf_group_resources_t *res)
638
int num_alphas, num_smasks, num_resources, i;
640
cairo_pdf_resource_t *smask, *pattern, *xobject;
641
cairo_pdf_font_t *font;
643
_cairo_output_stream_printf (surface->output, "<<\n");
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,
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",
658
for (i = 0; i < num_smasks; i++) {
659
smask = _cairo_array_index (&res->smasks, i);
660
_cairo_output_stream_printf (surface->output,
662
smask->id, smask->id);
665
_cairo_output_stream_printf (surface->output,
669
num_resources = _cairo_array_num_elements (&res->patterns);
670
if (num_resources > 0) {
671
_cairo_output_stream_printf (surface->output,
673
for (i = 0; i < num_resources; i++) {
674
pattern = _cairo_array_index (&res->patterns, i);
675
_cairo_output_stream_printf (surface->output,
677
pattern->id, pattern->id);
680
_cairo_output_stream_printf (surface->output,
684
num_resources = _cairo_array_num_elements (&res->xobjects);
685
if (num_resources > 0) {
686
_cairo_output_stream_printf (surface->output,
689
for (i = 0; i < num_resources; i++) {
690
xobject = _cairo_array_index (&res->xobjects, i);
691
_cairo_output_stream_printf (surface->output,
693
xobject->id, xobject->id);
696
_cairo_output_stream_printf (surface->output,
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",
709
font->subset_resource.id);
711
_cairo_output_stream_printf (surface->output, " >>\n");
714
_cairo_output_stream_printf (surface->output,
718
static cairo_pdf_smask_group_t *
719
_cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t *surface)
721
cairo_pdf_smask_group_t *group;
723
group = calloc (1, sizeof (cairo_pdf_smask_group_t));
725
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
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);
735
group->width = surface->width;
736
group->height = surface->height;
742
_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
744
if (group->operation == PDF_FILL || group->operation == PDF_STROKE)
745
_cairo_path_fixed_fini (&group->path);
747
cairo_pattern_destroy (group->source);
749
cairo_pattern_destroy (group->mask);
753
free (group->glyphs);
755
free (group->clusters);
756
if (group->scaled_font)
757
cairo_scaled_font_destroy (group->scaled_font);
761
static cairo_status_t
762
_cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t *surface,
763
cairo_pdf_smask_group_t *group)
765
return _cairo_array_append (&surface->smask_groups, &group);
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)
774
cairo_pdf_pattern_t pdf_pattern;
775
cairo_status_t status;
777
/* Solid colors are emitted into the content stream */
778
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
781
return CAIRO_STATUS_SUCCESS;
784
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
785
pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
787
cairo_gradient_pattern_t *gradient;
789
gradient = (cairo_gradient_pattern_t *) pattern;
791
/* Gradients with zero stops do not produce any output */
792
if (gradient->n_stops == 0)
793
return CAIRO_INT_STATUS_NOTHING_TO_DO;
795
/* Gradients with one stop are the same as solid colors */
796
if (gradient->n_stops == 1) {
799
return CAIRO_STATUS_SUCCESS;
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);
810
pdf_pattern.gstate_res.id = 0;
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);
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;
829
status = _cairo_array_append (&surface->patterns, &pdf_pattern);
831
cairo_pattern_destroy (pattern);
835
return CAIRO_STATUS_SUCCESS;
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,
846
cairo_pdf_resource_t self, length;
847
cairo_output_stream_t *output = NULL;
851
_cairo_pdf_surface_update_object (surface, self);
853
self = _cairo_pdf_surface_new_object (surface);
855
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
858
length = _cairo_pdf_surface_new_object (surface);
860
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
863
output = _cairo_deflate_stream_create (surface->output);
864
if (_cairo_output_stream_get_status (output))
865
return _cairo_output_stream_destroy (output);
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);
875
_cairo_output_stream_printf (surface->output,
877
"<< /Length %d 0 R\n",
878
surface->pdf_stream.self.id,
879
surface->pdf_stream.length.id);
881
_cairo_output_stream_printf (surface->output,
882
" /Filter /FlateDecode\n");
886
_cairo_output_stream_vprintf (surface->output, fmt, ap);
890
_cairo_output_stream_printf (surface->output,
894
surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
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);
903
return _cairo_output_stream_get_status (surface->output);
906
static cairo_status_t
907
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
909
cairo_status_t status = CAIRO_STATUS_SUCCESS;
912
if (! surface->pdf_stream.active)
913
return CAIRO_STATUS_SUCCESS;
915
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
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,
928
length = _cairo_output_stream_get_position (surface->output) -
929
surface->pdf_stream.start_offset;
930
_cairo_output_stream_printf (surface->output,
934
_cairo_pdf_surface_update_object (surface,
935
surface->pdf_stream.length);
936
_cairo_output_stream_printf (surface->output,
940
surface->pdf_stream.length.id,
943
surface->pdf_stream.active = FALSE;
945
if (status == CAIRO_STATUS_SUCCESS)
946
status = _cairo_output_stream_get_status (surface->output);
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)
958
_cairo_pdf_surface_update_object (surface, resource);
960
_cairo_output_stream_printf (surface->output,
962
"<< /Type /XObject\n"
965
_cairo_memory_stream_length (mem_stream));
967
if (surface->compress_content) {
968
_cairo_output_stream_printf (surface->output,
969
" /Filter /FlateDecode\n");
972
_cairo_output_stream_printf (surface->output,
974
" /BBox [ 0 0 %f %f ]\n"
977
" /S /Transparency\n"
982
if (is_knockout_group)
983
_cairo_output_stream_printf (surface->output,
986
_cairo_output_stream_printf (surface->output,
989
_cairo_pdf_surface_emit_group_resources (surface, resources);
990
_cairo_output_stream_printf (surface->output,
993
_cairo_memory_stream_copy (mem_stream, surface->output);
994
_cairo_output_stream_printf (surface->output,
999
static cairo_status_t
1000
_cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
1001
cairo_pdf_resource_t *resource)
1003
cairo_status_t status;
1005
assert (surface->pdf_stream.active == FALSE);
1006
assert (surface->group_stream.active == FALSE);
1008
surface->group_stream.active = TRUE;
1009
surface->current_pattern_is_solid_color = FALSE;
1010
_cairo_pdf_operators_reset (&surface->pdf_operators);
1012
surface->group_stream.mem_stream = _cairo_memory_stream_create ();
1014
if (surface->compress_content) {
1015
surface->group_stream.stream =
1016
_cairo_deflate_stream_create (surface->group_stream.mem_stream);
1018
surface->group_stream.stream = surface->group_stream.mem_stream;
1020
status = _cairo_output_stream_get_status (surface->group_stream.stream);
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);
1028
surface->group_stream.resource = *resource;
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);
1034
surface->group_stream.is_knockout = FALSE;
1039
static cairo_status_t
1040
_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface)
1042
cairo_status_t status;
1044
status = _cairo_pdf_surface_open_group (surface, NULL);
1048
surface->group_stream.is_knockout = TRUE;
1050
return CAIRO_STATUS_SUCCESS;
1053
static cairo_status_t
1054
_cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
1055
cairo_pdf_resource_t *group)
1057
cairo_status_t status = CAIRO_STATUS_SUCCESS, status2;
1059
assert (surface->pdf_stream.active == FALSE);
1060
assert (surface->group_stream.active == TRUE);
1062
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1066
if (surface->compress_content) {
1067
status = _cairo_output_stream_destroy (surface->group_stream.stream);
1068
surface->group_stream.stream = NULL;
1070
_cairo_output_stream_printf (surface->group_stream.mem_stream,
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);
1082
*group = surface->group_stream.resource;
1084
status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
1085
if (status == CAIRO_STATUS_SUCCESS)
1088
surface->group_stream.mem_stream = NULL;
1089
surface->group_stream.stream = NULL;
1094
static cairo_status_t
1095
_cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
1096
cairo_bool_t is_form)
1098
cairo_status_t status;
1100
assert (surface->pdf_stream.active == FALSE);
1101
assert (surface->group_stream.active == FALSE);
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);
1109
_cairo_pdf_surface_open_stream (surface,
1111
surface->compress_content,
1114
" /BBox [ 0 0 %f %f ]\n"
1117
" /S /Transparency\n"
1120
" /Resources %d 0 R\n",
1123
surface->content_resources.id);
1126
_cairo_pdf_surface_open_stream (surface,
1128
surface->compress_content,
1134
surface->content = surface->pdf_stream.self;
1136
_cairo_output_stream_printf (surface->output, "q\n");
1138
return _cairo_output_stream_get_status (surface->output);
1141
static cairo_status_t
1142
_cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
1144
cairo_status_t status;
1146
assert (surface->pdf_stream.active == TRUE);
1147
assert (surface->group_stream.active == FALSE);
1149
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1153
_cairo_output_stream_printf (surface->output, "Q\n");
1154
status = _cairo_pdf_surface_close_stream (surface);
1158
_cairo_pdf_surface_update_object (surface, surface->content_resources);
1159
_cairo_output_stream_printf (surface->output,
1161
surface->content_resources.id);
1162
_cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
1163
_cairo_output_stream_printf (surface->output,
1166
return _cairo_output_stream_get_status (surface->output);
1169
static cairo_surface_t *
1170
_cairo_pdf_surface_create_similar (void *abstract_surface,
1171
cairo_content_t content,
1175
return _cairo_meta_surface_create (content, width, height);
1178
static cairo_status_t
1179
_cairo_pdf_surface_finish (void *abstract_surface)
1181
cairo_pdf_surface_t *surface = abstract_surface;
1183
cairo_pdf_resource_t info, catalog;
1184
cairo_status_t status, status2;
1186
status = surface->base.status;
1187
if (status == CAIRO_STATUS_SUCCESS)
1188
status = _cairo_pdf_surface_emit_font_subsets (surface);
1190
_cairo_pdf_surface_write_pages (surface);
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);
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);
1200
offset = _cairo_pdf_surface_write_xref (surface);
1202
_cairo_output_stream_printf (surface->output,
1208
surface->next_available_resource.id,
1212
_cairo_output_stream_printf (surface->output,
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);
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)
1228
if (surface->group_stream.stream != NULL) {
1229
status2 = _cairo_output_stream_destroy (surface->group_stream.stream);
1230
if (status == CAIRO_STATUS_SUCCESS)
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)
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;
1243
/* and finish the pdf surface */
1244
status2 = _cairo_output_stream_destroy (surface->output);
1245
if (status == CAIRO_STATUS_SUCCESS)
1248
_cairo_pdf_surface_clear (surface);
1249
_cairo_pdf_group_resources_fini (&surface->resources);
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);
1260
if (surface->font_subsets) {
1261
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
1262
surface->font_subsets = NULL;
1268
static cairo_int_status_t
1269
_cairo_pdf_surface_start_page (void *abstract_surface)
1271
cairo_pdf_surface_t *surface = abstract_surface;
1273
_cairo_pdf_group_resources_clear (&surface->resources);
1275
return CAIRO_STATUS_SUCCESS;
1278
static cairo_int_status_t
1279
_cairo_pdf_surface_has_fallback_images (void *abstract_surface,
1280
cairo_bool_t has_fallbacks)
1282
cairo_status_t status;
1283
cairo_pdf_surface_t *surface = abstract_surface;
1285
surface->has_fallback_images = has_fallbacks;
1286
status = _cairo_pdf_surface_open_content_stream (surface, has_fallbacks);
1290
return CAIRO_STATUS_SUCCESS;
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.
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.
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)
1304
cairo_status_t status = CAIRO_STATUS_SUCCESS;
1306
unsigned long alpha_size;
1310
cairo_bool_t opaque;
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 );
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);
1324
alpha_size = image->height * image->width;
1325
alpha = _cairo_malloc_ab (image->height, image->width);
1328
if (alpha == NULL) {
1329
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1335
for (y = 0; y < image->height; y++) {
1336
if (image->format == CAIRO_FORMAT_ARGB32) {
1337
pixel32 = (uint32_t *) (image->data + y * image->stride);
1339
for (x = 0; x < image->width; x++, pixel32++) {
1340
a = (*pixel32 & 0xff000000) >> 24;
1345
} else if (image->format == CAIRO_FORMAT_A8){
1346
pixel8 = (uint8_t *) (image->data + y * image->stride);
1348
for (x = 0; x < image->width; x++, pixel8++) {
1354
} else { /* image->format == CAIRO_FORMAT_A1 */
1355
pixel8 = (uint8_t *) (image->data + y * image->stride);
1357
for (x = 0; x < (image->width + 7) / 8; x++, pixel8++) {
1359
a = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a);
1367
/* Bail out without emitting smask if it's all opaque. */
1371
status = _cairo_pdf_surface_open_stream (surface,
1375
" /Subtype /Image\n"
1378
" /ColorSpace /DeviceGray\n"
1379
" /BitsPerComponent %d\n",
1380
image->width, image->height,
1381
image->format == CAIRO_FORMAT_A1 ? 1 : 8);
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);
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)
1402
cairo_status_t status = CAIRO_STATUS_SUCCESS;
1404
unsigned long rgb_size;
1407
cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
1408
cairo_bool_t need_smask;
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.
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);
1420
rgb_size = image->height * image->width * 3;
1421
rgb = _cairo_malloc_abc (image->width, image->height, 3);
1423
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1428
for (y = 0; y < image->height; y++) {
1429
pixel = (uint32_t *) (image->data + y * image->stride);
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
1437
if (image->format == CAIRO_FORMAT_ARGB32) {
1439
a = (*pixel & 0xff000000) >> 24;
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;
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;
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);
1473
#define IMAGE_DICTIONARY " /Type /XObject\n" \
1474
" /Subtype /Image\n" \
1477
" /ColorSpace /DeviceRGB\n" \
1478
" /BitsPerComponent 8\n"
1481
status = _cairo_pdf_surface_open_stream (surface,
1486
image->width, image->height,
1489
status = _cairo_pdf_surface_open_stream (surface,
1493
image->width, image->height);
1497
#undef IMAGE_DICTIONARY
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);
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,
1516
cairo_image_surface_t *image;
1518
cairo_status_t status;
1520
status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
1524
status = _cairo_pdf_surface_emit_image (surface, image, resource);
1528
*width = image->width;
1529
*height = image->height;
1532
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
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)
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;
1549
status = _cairo_surface_get_extents (meta_surface, &meta_extents);
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,
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.
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);
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);
1576
_cairo_output_stream_printf (surface->output,
1577
"q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
1583
status = _cairo_meta_surface_replay_region (meta_surface, &surface->base,
1584
CAIRO_META_REGION_NATIVE);
1585
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
1589
status = _cairo_surface_set_clip (&surface->base, old_clip);
1593
status = _cairo_pdf_surface_close_content_stream (surface);
1595
_cairo_pdf_surface_set_size_internal (surface,
1598
surface->paginated_mode = old_paginated_mode;
1603
static cairo_status_t
1604
_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
1605
cairo_pdf_pattern_t *pdf_pattern)
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 */
1617
char draw_surface[200];
1619
if (_cairo_surface_is_meta (pattern->surface)) {
1620
cairo_surface_t *meta_surface = pattern->surface;
1621
cairo_rectangle_int_t pattern_extents;
1623
status = _cairo_pdf_surface_emit_meta_surface (surface,
1629
status = _cairo_surface_get_extents (meta_surface, &pattern_extents);
1633
pattern_width = pattern_extents.width;
1634
pattern_height = pattern_extents.height;
1636
status = _cairo_pdf_surface_emit_image_surface (surface,
1645
status = _cairo_surface_get_extents (&surface->base, &surface_extents);
1649
bbox_x = pattern_width;
1650
bbox_y = pattern_height;
1652
/* We implement EXTEND_PAD like EXTEND_NONE for now */
1653
case CAIRO_EXTEND_PAD:
1654
case CAIRO_EXTEND_NONE:
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
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
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,
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);
1682
case CAIRO_EXTEND_REPEAT:
1683
xstep = pattern_width;
1684
ystep = pattern_height;
1686
case CAIRO_EXTEND_REFLECT:
1687
bbox_x = pattern_width*2;
1688
bbox_y = pattern_height*2;
1692
/* All the rest (if any) should have been analyzed away, so this
1693
* case should be unreachable. */
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).
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.
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.
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
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);
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);
1739
_cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
1740
status = _cairo_pdf_surface_open_stream (surface,
1741
&pdf_pattern->pattern_res,
1744
" /BBox [0 0 %d %d]\n"
1749
" /Matrix [ %f %f %f %f %f %f ]\n"
1750
" /Resources << /XObject << /x%d %d 0 R >> >>\n",
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);
1761
if (_cairo_surface_is_meta (pattern->surface)) {
1762
snprintf(draw_surface,
1763
sizeof (draw_surface),
1765
pattern_resource.id);
1767
snprintf(draw_surface,
1768
sizeof (draw_surface),
1769
"q %d 0 0 %d 0 0 cm /x%d Do Q",
1772
pattern_resource.id);
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,
1783
pattern_width*2, pattern_width, pattern_height,
1785
pattern_height*2, pattern_width, pattern_height,
1787
pattern_width*2, pattern_height*2, pattern_width, pattern_height,
1790
_cairo_output_stream_printf (surface->output,
1795
status = _cairo_pdf_surface_close_stream (surface);
1799
return _cairo_output_stream_get_status (surface->output);
1802
typedef struct _cairo_pdf_color_stop {
1805
cairo_pdf_resource_t resource;
1806
} cairo_pdf_color_stop_t;
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)
1815
cairo_pdf_rgb_linear_function_t elem;
1816
cairo_pdf_resource_t res;
1817
cairo_status_t status;
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)
1824
if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0)
1826
*function = elem.resource;
1827
return CAIRO_STATUS_SUCCESS;
1830
res = _cairo_pdf_surface_new_object (surface);
1832
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1834
_cairo_output_stream_printf (surface->output,
1836
"<< /FunctionType 2\n"
1837
" /Domain [ 0 1 ]\n"
1838
" /C0 [ %f %f %f ]\n"
1839
" /C1 [ %f %f %f ]\n"
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);
1855
status = _cairo_array_append (&surface->rgb_linear_functions, &elem);
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)
1868
cairo_pdf_alpha_linear_function_t elem;
1869
cairo_pdf_resource_t res;
1870
cairo_status_t status;
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])
1877
if (elem.alpha2 != stop2->color[3])
1879
*function = elem.resource;
1880
return CAIRO_STATUS_SUCCESS;
1883
res = _cairo_pdf_surface_new_object (surface);
1885
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1887
_cairo_output_stream_printf (surface->output,
1889
"<< /FunctionType 2\n"
1890
" /Domain [ 0 1 ]\n"
1900
elem.resource = res;
1901
elem.alpha1 = stop1->color[3];
1902
elem.alpha2 = stop2->color[3];
1904
status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
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)
1917
cairo_pdf_resource_t res;
1919
cairo_status_t status;
1921
/* emit linear gradients between pairs of subsequent stops... */
1922
for (i = 0; i < n_stops-1; i++) {
1924
status = cairo_pdf_surface_emit_alpha_linear_function (surface,
1927
&stops[i].resource);
1931
status = cairo_pdf_surface_emit_rgb_linear_function (surface,
1934
&stops[i].resource);
1940
/* ... and stitch them together */
1941
res = _cairo_pdf_surface_new_object (surface);
1943
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1945
_cairo_output_stream_printf (surface->output,
1947
"<< /FunctionType 3\n"
1948
" /Domain [ %f %f ]\n",
1951
stops[n_stops - 1].offset);
1953
_cairo_output_stream_printf (surface->output,
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,
1961
_cairo_output_stream_printf (surface->output,
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,
1969
_cairo_output_stream_printf (surface->output,
1971
for (i = 1; i < n_stops; i++)
1972
_cairo_output_stream_printf (surface->output,
1974
_cairo_output_stream_printf (surface->output,
1977
_cairo_output_stream_printf (surface->output,
1983
return _cairo_output_stream_get_status (surface->output);
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)
1993
double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
1995
for (i = 0; i < 4; i++)
1996
new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
1999
#define COLOR_STOP_EPSILON 1e-6
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)
2007
cairo_pdf_color_stop_t *allstops, *stops;
2008
unsigned int n_stops;
2010
cairo_bool_t emit_alpha = FALSE;
2011
cairo_status_t status;
2013
color_function->id = 0;
2014
alpha_function->id = 0;
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);
2020
stops = &allstops[1];
2021
n_stops = pattern->n_stops;
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]))
2030
stops[i].offset = pattern->stops[i].offset;
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));
2039
calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
2043
stops[0].offset = 0.0;
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));
2051
calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
2055
stops[n_stops-1].offset = 1.0;
2059
/* no need for stitched function */
2060
status = cairo_pdf_surface_emit_rgb_linear_function (surface,
2068
status = cairo_pdf_surface_emit_alpha_linear_function (surface,
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,
2087
status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
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,
2109
cairo_pdf_resource_t res;
2112
res = _cairo_pdf_surface_new_object (surface);
2114
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2116
_cairo_output_stream_printf (surface->output,
2118
"<< /FunctionType 3\n"
2119
" /Domain [ %d %d ]\n",
2124
_cairo_output_stream_printf (surface->output,
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,
2132
_cairo_output_stream_printf (surface->output,
2134
for (i = begin + 1; i < end; i++)
2135
_cairo_output_stream_printf (surface->output,
2137
_cairo_output_stream_printf (surface->output,
2140
_cairo_output_stream_printf (surface->output,
2142
for (i = begin; i < end; i++) {
2143
if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) {
2144
_cairo_output_stream_printf (surface->output,
2147
_cairo_output_stream_printf (surface->output,
2151
_cairo_output_stream_printf (surface->output,
2154
_cairo_output_stream_printf (surface->output,
2160
return _cairo_output_stream_get_status (surface->output);
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)
2168
cairo_pdf_resource_t smask_resource;
2169
cairo_status_t status;
2171
status = _cairo_pdf_surface_open_stream (surface,
2173
surface->compress_content,
2177
" /BBox [ 0 0 %f %f ]\n"
2180
" << /a0 << /ca 1 /CA 1 >>"
2183
" << /p%d %d 0 R >>\n"
2186
" << /Type /Group\n"
2187
" /S /Transparency\n"
2188
" /CS /DeviceGray\n"
2197
_cairo_output_stream_printf (surface->output,
2200
"/Pattern cs /p%d scn\n"
2208
status = _cairo_pdf_surface_close_stream (surface);
2212
smask_resource = _cairo_pdf_surface_new_object (surface);
2213
if (smask_resource.id == 0)
2214
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2216
_cairo_output_stream_printf (surface->output,
2224
surface->pdf_stream.self.id);
2226
/* Create GState which uses the transparency group as an SMask. */
2227
_cairo_pdf_surface_update_object (surface, gstate_resource);
2229
_cairo_output_stream_printf (surface->output,
2231
"<< /Type /ExtGState\n"
2241
return _cairo_output_stream_get_status (surface->output);
2244
static cairo_status_t
2245
_cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
2246
cairo_pdf_pattern_t *pdf_pattern)
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;
2259
assert (pattern->base.n_stops != 0);
2261
extend = cairo_pattern_get_extend (pdf_pattern->pattern);
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);
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;
2272
if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
2273
pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
2275
int x_rep = 0, y_rep = 0;
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);
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);
2285
dx = fabs (x2 - x1);
2286
dy = fabs (y2 - y1);
2288
x_rep = (int) ceil (surface->width/dx);
2290
y_rep = (int) ceil (surface->height/dy);
2292
repeat_end = MAX (x_rep, y_rep);
2293
repeat_begin = -repeat_end;
2294
first_stop = repeat_begin;
2295
last_stop = repeat_end;
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);
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;
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) {
2328
status = _cairo_pdf_surface_emit_pattern_stops (surface,
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,
2345
if (alpha_function.id != 0) {
2346
status = _cairo_pdf_surface_emit_repeating_function (surface,
2356
_cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
2357
_cairo_output_stream_printf (surface->output,
2359
"<< /Type /Pattern\n"
2361
" /Matrix [ %f %f %f %f %f %f ]\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,
2373
first_stop, last_stop,
2376
if (extend == CAIRO_EXTEND_PAD) {
2377
_cairo_output_stream_printf (surface->output,
2378
" /Extend [ true true ]\n");
2380
_cairo_output_stream_printf (surface->output,
2381
" /Extend [ false false ]\n");
2384
_cairo_output_stream_printf (surface->output,
2389
if (alpha_function.id != 0) {
2390
cairo_pdf_resource_t mask_resource;
2392
assert (pdf_pattern->gstate_res.id != 0);
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);
2399
_cairo_output_stream_printf (surface->output,
2401
"<< /Type /Pattern\n"
2403
" /Matrix [ %f %f %f %f %f %f ]\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",
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,
2415
first_stop, last_stop,
2418
if (extend == CAIRO_EXTEND_PAD) {
2419
_cairo_output_stream_printf (surface->output,
2420
" /Extend [ true true ]\n");
2422
_cairo_output_stream_printf (surface->output,
2423
" /Extend [ false false ]\n");
2426
_cairo_output_stream_printf (surface->output,
2430
status = _cairo_pdf_surface_add_pattern (surface, mask_resource);
2434
status = cairo_pdf_surface_emit_transparency_group (surface,
2435
pdf_pattern->gstate_res,
2441
return _cairo_output_stream_get_status (surface->output);
2444
static cairo_status_t
2445
_cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface,
2446
cairo_pdf_pattern_t *pdf_pattern)
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;
2455
assert (pattern->base.n_stops != 0);
2457
extend = cairo_pattern_get_extend (pdf_pattern->pattern);
2459
status = _cairo_pdf_surface_emit_pattern_stops (surface,
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);
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);
2479
_cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
2481
_cairo_output_stream_printf (surface->output,
2483
"<< /Type /Pattern\n"
2485
" /Matrix [ %f %f %f %f %f %f ]\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,
2498
if (extend == CAIRO_EXTEND_PAD) {
2499
_cairo_output_stream_printf (surface->output,
2500
" /Extend [ true true ]\n");
2502
_cairo_output_stream_printf (surface->output,
2503
" /Extend [ false false ]\n");
2506
_cairo_output_stream_printf (surface->output,
2511
if (alpha_function.id != 0) {
2512
cairo_pdf_resource_t mask_resource;
2514
assert (pdf_pattern->gstate_res.id != 0);
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);
2521
_cairo_output_stream_printf (surface->output,
2523
"<< /Type /Pattern\n"
2525
" /Matrix [ %f %f %f %f %f %f ]\n"
2527
" << /ShadingType 3\n"
2528
" /ColorSpace /DeviceGray\n"
2529
" /Coords [ %f %f %f %f %f %f ]\n"
2530
" /Function %d 0 R\n",
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,
2538
if (extend == CAIRO_EXTEND_PAD) {
2539
_cairo_output_stream_printf (surface->output,
2540
" /Extend [ true true ]\n");
2542
_cairo_output_stream_printf (surface->output,
2543
" /Extend [ false false ]\n");
2546
_cairo_output_stream_printf (surface->output,
2551
status = cairo_pdf_surface_emit_transparency_group (surface,
2552
pdf_pattern->gstate_res,
2558
return _cairo_output_stream_get_status (surface->output);
2561
static cairo_status_t
2562
_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
2564
double old_width, old_height;
2565
cairo_status_t status;
2567
old_width = surface->width;
2568
old_height = surface->height;
2569
_cairo_pdf_surface_set_size_internal (surface,
2571
pdf_pattern->height);
2573
switch (pdf_pattern->pattern->type) {
2574
case CAIRO_PATTERN_TYPE_SOLID:
2576
status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
2579
case CAIRO_PATTERN_TYPE_SURFACE:
2580
status = _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
2583
case CAIRO_PATTERN_TYPE_LINEAR:
2584
status = _cairo_pdf_surface_emit_linear_pattern (surface, pdf_pattern);
2587
case CAIRO_PATTERN_TYPE_RADIAL:
2588
status = _cairo_pdf_surface_emit_radial_pattern (surface, pdf_pattern);
2593
status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
2597
_cairo_pdf_surface_set_size_internal (surface,
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)
2610
cairo_status_t status;
2612
cairo_color_t *solid_color = NULL;
2614
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
2615
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
2617
solid_color = &solid->color;
2620
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
2621
pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
2623
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
2625
if (gradient->n_stops == 1)
2626
solid_color = &gradient->stops[0].color;
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)
2636
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
2640
_cairo_output_stream_printf (surface->output,
2647
_cairo_output_stream_printf (surface->output, "RG ");
2649
_cairo_output_stream_printf (surface->output, "rg ");
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;
2657
if (surface->current_pattern_is_solid_color == FALSE ||
2658
surface->current_color_alpha != solid_color->alpha)
2660
status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha);
2664
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
2668
_cairo_output_stream_printf (surface->output,
2671
surface->current_color_alpha = solid_color->alpha;
2674
surface->current_pattern_is_solid_color = TRUE;
2676
status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
2680
status = _cairo_pdf_surface_add_pattern (surface, pattern_res);
2684
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
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 ");
2694
_cairo_output_stream_printf (surface->output,
2695
"/Pattern CS /p%d SCN ",
2698
_cairo_output_stream_printf (surface->output,
2699
"/Pattern cs /p%d scn ",
2702
_cairo_output_stream_printf (surface->output,
2705
surface->select_pattern_gstate_saved = TRUE;
2706
surface->current_pattern_is_solid_color = FALSE;
2709
return _cairo_output_stream_get_status (surface->output);
2712
static cairo_int_status_t
2713
_cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
2715
cairo_int_status_t status;
2717
if (surface->select_pattern_gstate_saved) {
2718
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
2722
_cairo_output_stream_printf (surface->output, "Q\n");
2723
_cairo_pdf_operators_reset (&surface->pdf_operators);
2725
surface->select_pattern_gstate_saved = FALSE;
2727
return CAIRO_STATUS_SUCCESS;
2730
static cairo_int_status_t
2731
_cairo_pdf_surface_show_page (void *abstract_surface)
2733
cairo_pdf_surface_t *surface = abstract_surface;
2734
cairo_int_status_t status;
2736
status = _cairo_pdf_surface_close_content_stream (surface);
2740
status = _cairo_pdf_surface_write_page (surface);
2744
_cairo_pdf_surface_clear (surface);
2746
return CAIRO_STATUS_SUCCESS;
2749
static cairo_int_status_t
2750
_cairo_pdf_surface_get_extents (void *abstract_surface,
2751
cairo_rectangle_int_t *rectangle)
2753
cairo_pdf_surface_t *surface = abstract_surface;
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.
2762
rectangle->width = (int) ceil (surface->width);
2763
rectangle->height = (int) ceil (surface->height);
2765
return CAIRO_STATUS_SUCCESS;
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,
2773
cairo_antialias_t antialias)
2775
cairo_pdf_surface_t *surface = abstract_surface;
2776
cairo_int_status_t status;
2779
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
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);
2787
return CAIRO_STATUS_SUCCESS;
2790
return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
2794
_cairo_pdf_surface_get_font_options (void *abstract_surface,
2795
cairo_font_options_t *options)
2797
_cairo_font_options_init_default (options);
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);
2804
static cairo_pdf_resource_t
2805
_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface)
2807
cairo_pdf_resource_t info;
2809
info = _cairo_pdf_surface_new_object (surface);
2813
_cairo_output_stream_printf (surface->output,
2815
"<< /Creator (cairo %s (http://cairographics.org))\n"
2816
" /Producer (cairo %s (http://cairographics.org))\n"
2820
cairo_version_string (),
2821
cairo_version_string ());
2827
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
2829
cairo_pdf_resource_t page;
2832
_cairo_pdf_surface_update_object (surface, surface->pages_resource);
2833
_cairo_output_stream_printf (surface->output,
2837
surface->pages_resource.id);
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);
2845
_cairo_output_stream_printf (surface->output, "]\n");
2846
_cairo_output_stream_printf (surface->output, " /Count %d\n", num_pages);
2849
/* TODO: Figure out which other defaults to be inherited by /Page
2851
_cairo_output_stream_printf (surface->output,
2856
static cairo_status_t
2857
_cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t *surface,
2860
uint16_t *utf16 = NULL;
2862
cairo_status_t status;
2865
if (utf8 && *utf8) {
2866
status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
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
2876
* Glyphs that do not map to a Unicode code point must be
2877
* mapped to 0xfffd "REPLACEMENT CHARACTER".
2879
_cairo_output_stream_printf (surface->output,
2882
for (i = 0; i < utf16_len; i++)
2883
_cairo_output_stream_printf (surface->output,
2884
"%04x", (int) (utf16[i]));
2886
_cairo_output_stream_printf (surface->output, ">");
2891
return CAIRO_STATUS_SUCCESS;
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)
2900
unsigned int i, num_bfchar;
2901
cairo_int_status_t status;
2905
status = _cairo_pdf_surface_open_stream (surface,
2907
surface->compress_content,
2912
_cairo_output_stream_printf (surface->output,
2913
"/CIDInit /ProcSet findresource begin\n"
2917
"<< /Registry (Adobe)\n"
2918
" /Ordering (UCS)\n"
2921
"/CMapName /Adobe-Identity-UCS def\n"
2923
"1 begincodespacerange\n");
2926
_cairo_output_stream_printf (surface->output,
2929
_cairo_output_stream_printf (surface->output,
2933
_cairo_output_stream_printf (surface->output,
2934
"endcodespacerange\n");
2936
num_bfchar = font_subset->num_glyphs - 1;
2938
/* The CMap specification has a limit of 100 characters per beginbfchar operator */
2939
_cairo_output_stream_printf (surface->output,
2941
num_bfchar > 100 ? 100 : num_bfchar);
2943
for (i = 0; i < num_bfchar; i++) {
2944
if (i != 0 && i % 100 == 0) {
2945
_cairo_output_stream_printf (surface->output,
2948
num_bfchar - i > 100 ? 100 : num_bfchar - i);
2951
_cairo_output_stream_printf (surface->output,
2955
_cairo_output_stream_printf (surface->output,
2959
_cairo_pdf_surface_emit_unicode_for_glyph (surface, font_subset->utf8[i + 1]);
2960
_cairo_output_stream_printf (surface->output,
2963
_cairo_output_stream_printf (surface->output,
2966
_cairo_output_stream_printf (surface->output,
2968
"CMapName currentdict /CMap defineresource pop\n"
2972
*stream = surface->pdf_stream.self;
2973
return _cairo_pdf_surface_close_stream (surface);
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)
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;
2985
cairo_status_t status;
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;
2993
status = _cairo_pdf_surface_open_stream (surface,
2996
" /Subtype /CIDFontType0C\n");
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);
3007
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
3009
&to_unicode_stream);
3010
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
3013
descriptor = _cairo_pdf_surface_new_object (surface);
3014
if (descriptor.id == 0)
3015
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3017
_cairo_output_stream_printf (surface->output,
3019
"<< /Type /FontDescriptor\n"
3022
" /FontBBox [ %ld %ld %ld %ld ]\n"
3029
" /FontFile3 %u 0 R\n"
3042
cidfont_dict = _cairo_pdf_surface_new_object (surface);
3043
if (cidfont_dict.id == 0)
3044
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3046
_cairo_output_stream_printf (surface->output,
3049
" /Subtype /CIDFontType0\n"
3052
" << /Registry (Adobe)\n"
3053
" /Ordering (Identity)\n"
3056
" /FontDescriptor %d 0 R\n"
3062
for (i = 0; i < font_subset->num_glyphs; i++)
3063
_cairo_output_stream_printf (surface->output,
3067
_cairo_output_stream_printf (surface->output,
3072
_cairo_pdf_surface_update_object (surface, subset_resource);
3073
_cairo_output_stream_printf (surface->output,
3076
" /Subtype /Type0\n"
3078
" /Encoding /Identity-H\n"
3079
" /DescendantFonts [ %d 0 R]\n",
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);
3089
_cairo_output_stream_printf (surface->output,
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);
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)
3105
cairo_status_t status;
3106
cairo_cff_subset_t subset;
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);
3115
status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
3117
_cairo_cff_subset_fini (&subset);
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)
3126
cairo_status_t status;
3127
cairo_cff_subset_t subset;
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);
3136
status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
3138
_cairo_cff_fallback_fini (&subset);
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)
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;
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;
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,
3168
subset->header_length,
3169
subset->data_length);
3173
stream = surface->pdf_stream.self;
3174
_cairo_output_stream_write (surface->output, subset->data, length);
3175
status = _cairo_pdf_surface_close_stream (surface);
3179
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
3181
&to_unicode_stream);
3182
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
3185
descriptor = _cairo_pdf_surface_new_object (surface);
3186
if (descriptor.id == 0)
3187
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3189
_cairo_output_stream_printf (surface->output,
3191
"<< /Type /FontDescriptor\n"
3194
" /FontBBox [ %ld %ld %ld %ld ]\n"
3201
" /FontFile %u 0 R\n"
3214
_cairo_pdf_surface_update_object (surface, subset_resource);
3215
_cairo_output_stream_printf (surface->output,
3218
" /Subtype /Type1\n"
3222
" /FontDescriptor %d 0 R\n"
3226
font_subset->num_glyphs - 1,
3229
for (i = 0; i < font_subset->num_glyphs; i++)
3230
_cairo_output_stream_printf (surface->output,
3234
_cairo_output_stream_printf (surface->output,
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);
3242
_cairo_output_stream_printf (surface->output,
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);
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)
3257
cairo_status_t status;
3258
cairo_type1_subset_t subset;
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);
3267
status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
3269
_cairo_type1_subset_fini (&subset);
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)
3278
cairo_status_t status;
3279
cairo_type1_subset_t subset;
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);
3288
status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
3290
_cairo_type1_fallback_fini (&subset);
3294
#define PDF_UNITS_PER_EM 1000
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)
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;
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;
3313
status = _cairo_truetype_subset_init (&subset, font_subset);
3317
status = _cairo_pdf_surface_open_stream (surface,
3321
subset.data_length);
3323
_cairo_truetype_subset_fini (&subset);
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);
3332
_cairo_truetype_subset_fini (&subset);
3336
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
3338
&to_unicode_stream);
3339
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) {
3340
_cairo_truetype_subset_fini (&subset);
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);
3350
_cairo_output_stream_printf (surface->output,
3352
"<< /Type /FontDescriptor\n"
3355
" /FontBBox [ %ld %ld %ld %ld ]\n"
3362
" /FontFile2 %u 0 R\n"
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),
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);
3382
_cairo_output_stream_printf (surface->output,
3385
" /Subtype /CIDFontType2\n"
3388
" << /Registry (Adobe)\n"
3389
" /Ordering (Identity)\n"
3392
" /FontDescriptor %d 0 R\n"
3398
for (i = 0; i < font_subset->num_glyphs; i++)
3399
_cairo_output_stream_printf (surface->output,
3401
(long)(subset.widths[i]*PDF_UNITS_PER_EM));
3403
_cairo_output_stream_printf (surface->output,
3408
_cairo_pdf_surface_update_object (surface, subset_resource);
3409
_cairo_output_stream_printf (surface->output,
3412
" /Subtype /Type0\n"
3414
" /Encoding /Identity-H\n"
3415
" /DescendantFonts [ %d 0 R]\n",
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);
3425
_cairo_output_stream_printf (surface->output,
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);
3434
_cairo_truetype_subset_fini (&subset);
3439
static cairo_status_t
3440
_cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
3441
cairo_output_stream_t *stream)
3443
uint8_t *byte, output_byte;
3444
int row, col, num_cols;
3446
/* The only image type supported by Type 3 fonts are 1-bit image
3448
assert (image->format == CAIRO_FORMAT_A1);
3450
_cairo_output_stream_printf (stream,
3460
_cairo_output_stream_printf (stream,
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);
3473
_cairo_output_stream_printf (stream,
3476
return _cairo_output_stream_get_status (stream);
3479
static cairo_status_t
3480
_cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
3483
cairo_pdf_surface_t *surface = closure;
3484
cairo_status_t status = CAIRO_STATUS_SUCCESS;
3485
cairo_status_t status2;
3487
cairo_surface_t *type3_surface;
3488
cairo_output_stream_t *null_stream;
3490
null_stream = _cairo_null_stream_create ();
3491
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
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,
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]);
3506
cairo_surface_destroy (type3_surface);
3507
status2 = _cairo_output_stream_destroy (null_stream);
3508
if (status == CAIRO_STATUS_SUCCESS)
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)
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;
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;
3527
if (font_subset->num_glyphs == 0)
3528
return CAIRO_STATUS_SUCCESS;
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;
3536
glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
3538
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3540
widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
3541
if (widths == NULL) {
3543
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3546
_cairo_pdf_group_resources_clear (&surface->resources);
3547
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
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,
3555
for (i = 0; i < font_subset->num_glyphs; i++) {
3556
status = _cairo_pdf_surface_open_stream (surface,
3558
surface->compress_content,
3563
glyphs[i] = surface->pdf_stream.self;
3565
status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
3570
status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
3572
font_subset->glyphs[i],
3579
status = _cairo_pdf_surface_close_stream (surface);
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;
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;
3599
cairo_surface_destroy (type3_surface);
3606
encoding = _cairo_pdf_surface_new_object (surface);
3607
if (encoding.id == 0) {
3610
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3613
_cairo_output_stream_printf (surface->output,
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,
3620
_cairo_output_stream_printf (surface->output,
3625
char_procs = _cairo_pdf_surface_new_object (surface);
3626
if (char_procs.id == 0) {
3629
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3632
_cairo_output_stream_printf (surface->output,
3634
"<<\n", char_procs.id);
3635
for (i = 0; i < font_subset->num_glyphs; i++)
3636
_cairo_output_stream_printf (surface->output,
3639
_cairo_output_stream_printf (surface->output,
3645
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
3647
&to_unicode_stream);
3648
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) {
3653
_cairo_pdf_surface_update_object (surface, subset_resource);
3654
_cairo_output_stream_printf (surface->output,
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"
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),
3671
font_subset->num_glyphs - 1);
3673
_cairo_output_stream_printf (surface->output,
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,
3681
_cairo_output_stream_printf (surface->output,
3683
_cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
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);
3690
_cairo_output_stream_printf (surface->output,
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);
3700
static cairo_status_t
3701
_cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
3704
cairo_pdf_surface_t *surface = closure;
3705
cairo_status_t status;
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)
3712
status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
3713
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3716
status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
3717
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
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)
3726
status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
3727
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3733
return CAIRO_STATUS_SUCCESS;
3736
static cairo_status_t
3737
_cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
3740
cairo_pdf_surface_t *surface = closure;
3741
cairo_status_t status;
3743
status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
3744
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3748
return CAIRO_STATUS_SUCCESS;
3751
static cairo_status_t
3752
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
3754
cairo_status_t status;
3756
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
3757
_cairo_pdf_surface_analyze_user_font_subset,
3762
status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
3763
_cairo_pdf_surface_emit_unscaled_font_subset,
3768
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
3769
_cairo_pdf_surface_emit_scaled_font_subset,
3774
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
3775
_cairo_pdf_surface_emit_scaled_font_subset,
3779
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
3780
surface->font_subsets = NULL;
3785
static cairo_pdf_resource_t
3786
_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface)
3788
cairo_pdf_resource_t catalog;
3790
catalog = _cairo_pdf_surface_new_object (surface);
3791
if (catalog.id == 0)
3794
_cairo_output_stream_printf (surface->output,
3796
"<< /Type /Catalog\n"
3801
surface->pages_resource.id);
3807
_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
3809
cairo_pdf_object_t *object;
3814
num_objects = _cairo_array_num_elements (&surface->objects);
3816
offset = _cairo_output_stream_get_position (surface->output);
3817
_cairo_output_stream_printf (surface->output,
3820
0, num_objects + 1);
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);
3834
static cairo_status_t
3835
_cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
3836
cairo_pdf_smask_group_t *group)
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;
3844
/* Create mask group */
3845
status = _cairo_pdf_surface_open_group (surface, NULL);
3851
status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, &pattern_res, &gstate_res);
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);
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);
3865
_cairo_pdf_smask_group_destroy (smask_group);
3869
status = _cairo_pdf_surface_add_smask (surface, gstate_res);
3873
status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
3877
_cairo_output_stream_printf (surface->output,
3878
"q /s%d gs /x%d Do Q\n",
3880
smask_group->group_res.id);
3882
status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE);
3886
_cairo_output_stream_printf (surface->output,
3888
surface->width, surface->height);
3890
status = _cairo_pdf_surface_unselect_pattern (surface);
3895
status = _cairo_pdf_surface_close_group (surface, &mask_group);
3899
/* Create source group */
3900
status = _cairo_pdf_surface_open_group (surface, &group->source_res);
3906
status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, &pattern_res, &gstate_res);
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);
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);
3920
_cairo_pdf_smask_group_destroy (smask_group);
3924
status = _cairo_pdf_surface_add_smask (surface, gstate_res);
3928
status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
3932
_cairo_output_stream_printf (surface->output,
3933
"q /s%d gs /x%d Do Q\n",
3935
smask_group->group_res.id);
3937
status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE);
3941
_cairo_output_stream_printf (surface->output,
3943
surface->width, surface->height);
3945
status = _cairo_pdf_surface_unselect_pattern (surface);
3950
status = _cairo_pdf_surface_close_group (surface, NULL);
3954
/* Create an smask based on the alpha component of mask_group */
3955
smask = _cairo_pdf_surface_new_object (surface);
3957
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3959
_cairo_output_stream_printf (surface->output,
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,
3973
"<< /Type /ExtGState\n"
3980
group->group_res.id,
3983
return _cairo_output_stream_get_status (surface->output);
3986
static cairo_status_t
3987
_cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
3988
cairo_pdf_smask_group_t *group)
3990
double old_width, old_height;
3991
cairo_status_t status;
3993
old_width = surface->width;
3994
old_height = surface->height;
3995
_cairo_pdf_surface_set_size_internal (surface,
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);
4003
status = _cairo_pdf_surface_open_group (surface, &group->group_res);
4007
status = _cairo_pdf_surface_select_pattern (surface,
4010
group->operation == PDF_STROKE);
4014
switch (group->operation) {
4016
_cairo_output_stream_printf (surface->output,
4018
surface->width, surface->height);
4024
status = _cairo_pdf_operators_fill (&surface->pdf_operators,
4029
status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
4033
&group->ctm_inverse);
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);
4047
status = _cairo_pdf_surface_unselect_pattern (surface);
4051
status = _cairo_pdf_surface_close_group (surface, NULL);
4053
_cairo_pdf_surface_set_size_internal (surface,
4060
static cairo_status_t
4061
_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface)
4063
cairo_pdf_pattern_t pattern;
4064
cairo_pdf_smask_group_t *group;
4065
int pattern_index, group_index;
4066
cairo_status_t status;
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.
4072
* Writing meta surface patterns will cause additional patterns
4073
* and groups to be appended.
4077
while ((pattern_index < _cairo_array_num_elements (&surface->patterns)) ||
4078
(group_index < _cairo_array_num_elements (&surface->smask_groups)))
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);
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);
4095
return CAIRO_STATUS_SUCCESS;
4098
static cairo_status_t
4099
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
4101
cairo_pdf_resource_t page, knockout, res;
4102
cairo_status_t status;
4105
_cairo_pdf_group_resources_clear (&surface->resources);
4106
if (surface->has_fallback_images) {
4107
status = _cairo_pdf_surface_open_knockout_group (surface);
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,
4117
status = _cairo_pdf_surface_add_xobject (surface, res);
4121
_cairo_output_stream_printf (surface->output,
4123
surface->content.id);
4124
status = _cairo_pdf_surface_add_xobject (surface, surface->content);
4128
status = _cairo_pdf_surface_close_group (surface, &knockout);
4132
_cairo_pdf_group_resources_clear (&surface->resources);
4133
status = _cairo_pdf_surface_open_content_stream (surface, FALSE);
4137
_cairo_output_stream_printf (surface->output,
4140
status = _cairo_pdf_surface_add_xobject (surface, knockout);
4144
status = _cairo_pdf_surface_close_content_stream (surface);
4149
page = _cairo_pdf_surface_new_object (surface);
4151
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4153
_cairo_output_stream_printf (surface->output,
4157
" /MediaBox [ 0 0 %f %f ]\n"
4158
" /Contents %d 0 R\n"
4161
" /S /Transparency\n"
4164
" /Resources %d 0 R\n"
4168
surface->pages_resource.id,
4171
surface->content.id,
4172
surface->content_resources.id);
4174
status = _cairo_array_append (&surface->pages, &page);
4178
status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface);
4182
return CAIRO_STATUS_SUCCESS;
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)
4189
cairo_image_surface_t *image;
4191
cairo_int_status_t status;
4192
cairo_image_transparency_t transparency;
4194
status = _cairo_surface_acquire_source_image (pattern->surface,
4200
if (image->base.status)
4201
return image->base.status;
4203
transparency = _cairo_image_analyze_transparency (image);
4204
if (transparency == CAIRO_IMAGE_IS_OPAQUE)
4205
status = CAIRO_STATUS_SUCCESS;
4207
status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
4209
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
4215
_surface_pattern_supported (cairo_surface_pattern_t *pattern)
4217
cairo_extend_t extend;
4219
if (_cairo_surface_is_meta (pattern->surface))
4222
if (pattern->surface->backend->acquire_source_image == NULL)
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. */
4228
/* XXX: Need to write this function here...
4229
content = cairo_surface_get_content (pattern->surface);
4230
if (content == CAIRO_CONTENT_ALPHA)
4234
extend = cairo_pattern_get_extend (&pattern->base);
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:
4250
_gradient_pattern_supported (cairo_pattern_t *pattern)
4252
cairo_extend_t extend;
4254
extend = cairo_pattern_get_extend (pattern);
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;
4263
if (extend == CAIRO_EXTEND_REPEAT ||
4264
extend == CAIRO_EXTEND_REFLECT) {
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);
4275
d = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
4276
if (d > fabs(r2 - r1)) {
4285
_pattern_supported (cairo_pattern_t *pattern)
4287
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
4290
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
4291
pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
4292
return _gradient_pattern_supported (pattern);
4294
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
4295
return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
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)
4305
if (surface->force_fallbacks && surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
4306
return CAIRO_INT_STATUS_UNSUPPORTED;
4308
if (! _pattern_supported (pattern))
4309
return CAIRO_INT_STATUS_UNSUPPORTED;
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;
4315
if ( _cairo_surface_is_meta (surface_pattern->surface))
4316
return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
4320
if (op == CAIRO_OPERATOR_OVER)
4321
return CAIRO_STATUS_SUCCESS;
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;
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;
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
4341
return CAIRO_INT_STATUS_UNSUPPORTED;
4344
return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
4349
if (_cairo_pattern_is_opaque (pattern))
4350
return CAIRO_STATUS_SUCCESS;
4352
return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
4355
return CAIRO_INT_STATUS_UNSUPPORTED;
4359
_cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
4360
cairo_operator_t op,
4361
cairo_pattern_t *pattern)
4363
if (_cairo_pdf_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
4369
static cairo_int_status_t
4370
_cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
4372
cairo_status_t status;
4374
status = _cairo_pdf_surface_close_content_stream (surface);
4378
status = _cairo_array_append (&surface->knockout_group, &surface->content);
4382
_cairo_pdf_group_resources_clear (&surface->resources);
4383
return _cairo_pdf_surface_open_content_stream (surface, TRUE);
4386
static cairo_int_status_t
4387
_cairo_pdf_surface_paint (void *abstract_surface,
4388
cairo_operator_t op,
4389
cairo_pattern_t *source)
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;
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);
4404
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
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;
4414
if (gstate_res.id != 0) {
4415
group = _cairo_pdf_surface_create_smask_group (surface);
4417
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
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);
4424
_cairo_pdf_smask_group_destroy (group);
4428
status = _cairo_pdf_surface_add_smask (surface, gstate_res);
4432
status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
4436
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4440
_cairo_output_stream_printf (surface->output,
4441
"q /s%d gs /x%d Do Q\n",
4443
group->group_res.id);
4445
status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
4449
_cairo_output_stream_printf (surface->output,
4451
surface->width, surface->height);
4453
status = _cairo_pdf_surface_unselect_pattern (surface);
4458
return _cairo_output_stream_get_status (surface->output);
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)
4467
cairo_pdf_surface_t *surface = abstract_surface;
4468
cairo_pdf_smask_group_t *group;
4469
cairo_status_t status;
4471
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
4472
cairo_status_t source_status, mask_status;
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;
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)
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;
4489
if (source_status == CAIRO_INT_STATUS_IMAGE_FALLBACK ||
4490
mask_status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
4491
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
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;
4497
return CAIRO_STATUS_SUCCESS;
4498
} else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
4499
status = _cairo_pdf_surface_start_fallback (surface);
4504
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
4505
assert (_cairo_pdf_surface_operation_supported (surface, op, mask));
4507
group = _cairo_pdf_surface_create_smask_group (surface);
4509
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
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);
4520
status = _cairo_pdf_surface_add_smask_group (surface, group);
4522
_cairo_pdf_smask_group_destroy (group);
4526
status = _cairo_pdf_surface_add_smask (surface, group->group_res);
4530
status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
4534
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
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);
4543
return _cairo_output_stream_get_status (surface->output);
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,
4555
cairo_antialias_t antialias)
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;
4562
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
4563
return _cairo_pdf_surface_analyze_operation (surface, op, source);
4565
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
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;
4575
if (gstate_res.id != 0) {
4576
group = _cairo_pdf_surface_create_smask_group (surface);
4578
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
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);
4585
_cairo_pdf_smask_group_destroy (group);
4589
group->style = style;
4591
group->ctm_inverse = *ctm_inverse;
4592
status = _cairo_pdf_surface_add_smask_group (surface, group);
4594
_cairo_pdf_smask_group_destroy (group);
4598
status = _cairo_pdf_surface_add_smask (surface, gstate_res);
4602
status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
4606
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4610
_cairo_output_stream_printf (surface->output,
4611
"q /s%d gs /x%d Do Q\n",
4613
group->group_res.id);
4615
status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
4619
status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
4627
status = _cairo_pdf_surface_unselect_pattern (surface);
4632
return _cairo_output_stream_get_status (surface->output);
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,
4642
cairo_antialias_t antialias)
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;
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);
4657
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
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;
4667
if (gstate_res.id != 0) {
4668
group = _cairo_pdf_surface_create_smask_group (surface);
4670
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
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);
4677
_cairo_pdf_smask_group_destroy (group);
4681
group->fill_rule = fill_rule;
4682
status = _cairo_pdf_surface_add_smask_group (surface, group);
4684
_cairo_pdf_smask_group_destroy (group);
4688
status = _cairo_pdf_surface_add_smask (surface, gstate_res);
4692
status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
4696
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4700
_cairo_output_stream_printf (surface->output,
4701
"q /s%d gs /x%d Do Q\n",
4703
group->group_res.id);
4705
status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
4709
status = _cairo_pdf_operators_fill (&surface->pdf_operators,
4715
status = _cairo_pdf_surface_unselect_pattern (surface);
4720
return _cairo_output_stream_get_status (surface->output);
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)
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;
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
4750
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
4751
return CAIRO_INT_STATUS_UNSUPPORTED;
4753
/* PDF rendering of fill-stroke is not the same as cairo when
4754
* either the fill or stroke is not opaque.
4756
if ( !_cairo_pattern_is_opaque (fill_source) ||
4757
!_cairo_pattern_is_opaque (stroke_source))
4759
return CAIRO_INT_STATUS_UNSUPPORTED;
4762
fill_pattern_res.id = 0;
4764
status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
4770
assert (gstate_res.id == 0);
4772
stroke_pattern_res.id = 0;
4774
status = _cairo_pdf_surface_add_pdf_pattern (surface,
4776
&stroke_pattern_res,
4781
assert (gstate_res.id == 0);
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);
4790
status = _cairo_pdf_surface_select_pattern (surface, stroke_source,
4791
stroke_pattern_res, TRUE);
4795
status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators,
4800
stroke_ctm_inverse);
4804
status = _cairo_pdf_surface_unselect_pattern (surface);
4808
return _cairo_output_stream_get_status (surface->output);
4812
_cairo_pdf_surface_has_show_text_glyphs (void *abstract_surface)
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,
4823
cairo_glyph_t *glyphs,
4825
const cairo_text_cluster_t *clusters,
4827
cairo_text_cluster_flags_t cluster_flags,
4828
cairo_scaled_font_t *scaled_font)
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;
4835
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
4836
return _cairo_pdf_surface_analyze_operation (surface, op, source);
4838
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
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;
4848
if (gstate_res.id != 0) {
4849
group = _cairo_pdf_surface_create_smask_group (surface);
4851
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4853
group->operation = PDF_SHOW_GLYPHS;
4854
group->source = cairo_pattern_reference (source);
4855
group->source_res = pattern_res;
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);
4863
memcpy (group->utf8, utf8, utf8_len);
4865
group->utf8_len = utf8_len;
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);
4873
memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
4875
group->num_glyphs = num_glyphs;
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);
4883
memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
4885
group->num_clusters = num_clusters;
4887
group->scaled_font = cairo_scaled_font_reference (scaled_font);
4888
status = _cairo_pdf_surface_add_smask_group (surface, group);
4890
_cairo_pdf_smask_group_destroy (group);
4894
status = _cairo_pdf_surface_add_smask (surface, gstate_res);
4898
status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
4902
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4906
_cairo_output_stream_printf (surface->output,
4907
"q /s%d gs /x%d Do Q\n",
4909
group->group_res.id);
4911
status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
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
4919
if (! _cairo_pattern_is_opaque (source)) {
4920
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4925
status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
4928
clusters, num_clusters,
4934
status = _cairo_pdf_surface_unselect_pattern (surface);
4939
return _cairo_output_stream_get_status (surface->output);
4944
_cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
4945
cairo_paginated_mode_t paginated_mode)
4947
cairo_pdf_surface_t *surface = abstract_surface;
4949
surface->paginated_mode = paginated_mode;
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,
4972
NULL, /* mark_dirty_rectangle */
4973
NULL, /* scaled_font_fini */
4974
NULL, /* scaled_glyph_fini */
4976
/* Here are the drawing functions */
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 */
4985
NULL, /* is_compatible */
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,
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,