1
/* cairo - a vector graphics library with display and print output
3
* Copyright © 2004 Red Hat, Inc
4
* Copyright © 2006 Red Hat, Inc
5
* Copyright © 2007 Adrian Johnson
7
* This library is free software; you can redistribute it and/or
8
* modify it either under the terms of the GNU Lesser General Public
9
* License version 2.1 as published by the Free Software Foundation
10
* (the "LGPL") or, at your option, under the terms of the Mozilla
11
* Public License Version 1.1 (the "MPL"). If you do not alter this
12
* notice, a recipient may use your version of this file under either
13
* the MPL or the LGPL.
15
* You should have received a copy of the LGPL along with this library
16
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
* You should have received a copy of the MPL along with this library
19
* in the file COPYING-MPL-1.1
21
* The contents of this file are subject to the Mozilla Public License
22
* Version 1.1 (the "License"); you may not use this file except in
23
* compliance with the License. You may obtain a copy of the License at
24
* http://www.mozilla.org/MPL/
26
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
28
* the specific language governing rights and limitations.
30
* The Original Code is the cairo graphics library.
32
* The Initial Developer of the Original Code is University of Southern
36
* Kristian Høgsberg <krh@redhat.com>
37
* Carl Worth <cworth@cworth.org>
38
* Adrian Johnson <ajohnson@redneon.com>
42
#include "cairo-pdf.h"
43
#include "cairo-pdf-surface-private.h"
44
#include "cairo-scaled-font-subsets-private.h"
45
#include "cairo-paginated-private.h"
46
#include "cairo-path-fixed-private.h"
47
#include "cairo-output-stream-private.h"
48
#include "cairo-meta-surface-private.h"
55
* - We embed an image in the stream each time it's composited. We
56
* could add generation counters to surfaces and remember the stream
57
* ID for a particular generation for a particular surface.
59
* - Images of other formats than 8 bit RGBA.
61
* - Backend specific meta data.
65
* - Should/does cairo support drawing into a scratch surface and then
66
* using that as a fill pattern? For this backend, that would involve
67
* using a tiling pattern (4.6.2). How do you create such a scratch
68
* surface? cairo_surface_create_similar() ?
70
* - What if you create a similar surface and does show_page and then
71
* does show_surface on another surface?
73
* - Add test case for RGBA images.
75
* - Add test case for RGBA gradients.
77
* - Coordinate space for create_similar() args?
81
* Page Structure of the Generated PDF:
83
* Each page requiring fallbacks images contains a knockout group at
84
* the top level. The first operation of the knockout group paints a
85
* group containing all the supported drawing operations. Fallback
86
* images (if any) are painted in the knockout group. This ensures
87
* that fallback images do not composite with any content under the
90
* The group containing the supported operations (content_group_list
91
* in the example below) does not do any drawing directly. Instead it
92
* paints groups containing the drawing operations and performs
93
* clipping. The reason for this is that clipping operations performed
94
* in a group do not affect the parent group.
96
* Example PDF Page Structure:
104
* /content_group_list Do
105
* /fallback_image_1 Do
106
* /fallback_image_2 Do
112
* /content_group_1 Do
113
* /content_group_2 Do
114
* 10 10 m 10 20 l 20 20 l 20 10 l h W # clip
115
* /content_group_3 Do
117
* /content_group_4 Do
123
* This PDF surface has three types of streams:
128
* Calling _cairo_output_stream_printf (surface->output, ...) will
129
* write to the currently open stream.
132
* A PDF Stream may be opened and closed with the following functions:
133
* _cairo_pdf_surface_open_stream ()
134
* _cairo_pdf_surface_close_stream ()
136
* PDF Streams are written directly to the PDF file. They are used for
137
* fonts, images and patterns.
140
* The Content Stream is opened and closed with the following functions:
141
* _cairo_pdf_surface_start_content_stream ()
142
* _cairo_pdf_surface_stop_content_stream ()
144
* The Content Stream is written to content_group_n groups (as shown
145
* in the page structure example). The Content Stream may be paused
146
* and resumed with the following functions:
147
* _cairo_pdf_surface_pause_content_stream ()
148
* _cairo_pdf_surface_resume_content_stream ()
150
* When the Content Stream is paused, a PDF Stream or Group Stream
151
* may be opened. After closing the PDF Stream or Group Stream the
152
* Content Stream may be resumed.
154
* The Content Stream contains the text and graphics operators. When
155
* a pattern is required the Content Stream is paused, a PDF Stream
156
* is opened, the pattern is written to a PDF Stream, the PDF Stream
157
* is closed, then the Content Stream is resumed.
159
* Each group comprising the Content Stream is stored in memory
160
* until the stream is closed or the maximum group size is
161
* exceeded. This is due to the need to list all resources used in
162
* the group in the group's stream dictionary.
165
* A Group Stream may be opened and closed with the following functions:
166
* _cairo_pdf_surface_open_group ()
167
* _cairo_pdf_surface_close_group ()
169
* A Group Stream is written to a separate group in the PDF file
170
* that is not part of the Content Stream. Group Streams are also
171
* stored in memory until the stream is closed due to the need to
172
* list the resources used in the group in the group's stream
175
* Group Streams are used for short sequences of graphics operations
176
* that need to be in a separate group from the Content Stream.
179
/* The group stream length is checked after each operation. When this
180
* limit is exceeded the group is written out to the pdf stream and a
181
* new group is created. */
182
#define GROUP_STREAM_LIMIT 65536
184
typedef struct _cairo_pdf_object {
186
} cairo_pdf_object_t;
188
typedef struct _cairo_pdf_font {
189
unsigned int font_id;
190
unsigned int subset_id;
191
cairo_pdf_resource_t subset_resource;
194
typedef struct _cairo_pdf_rgb_linear_function {
195
cairo_pdf_resource_t resource;
198
} cairo_pdf_rgb_linear_function_t;
200
typedef struct _cairo_pdf_alpha_linear_function {
201
cairo_pdf_resource_t resource;
204
} cairo_pdf_alpha_linear_function_t;
206
typedef enum group_element_type {
209
} group_element_type_t;
211
typedef struct _cairo_pdf_group_element {
212
group_element_type_t type;
213
cairo_pdf_resource_t group;
214
cairo_path_fixed_t *clip_path;
215
cairo_fill_rule_t fill_rule;
216
} cairo_pdf_group_element_t;
219
static cairo_pdf_resource_t
220
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
223
_cairo_pdf_group_element_array_finish (cairo_array_t *array);
226
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
229
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
231
static cairo_pdf_resource_t
232
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
233
cairo_bool_t compressed,
235
...) CAIRO_PRINTF_FORMAT(3, 4);
236
static cairo_status_t
237
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface);
239
static cairo_status_t
240
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
243
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
245
static cairo_pdf_resource_t
246
_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface);
248
static cairo_pdf_resource_t
249
_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface);
252
_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
254
static cairo_status_t
255
_cairo_pdf_surface_emit_clip (cairo_pdf_surface_t *surface,
256
cairo_path_fixed_t *path,
257
cairo_fill_rule_t fill_rule);
259
static cairo_status_t
260
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
262
static cairo_status_t
263
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
265
static const cairo_surface_backend_t cairo_pdf_surface_backend;
266
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
268
static cairo_pdf_resource_t
269
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
271
cairo_pdf_resource_t resource;
272
cairo_status_t status;
273
cairo_pdf_object_t object;
275
object.offset = _cairo_output_stream_get_position (surface->output);
277
status = _cairo_array_append (&surface->objects, &object);
283
resource = surface->next_available_resource;
284
surface->next_available_resource.id++;
290
_cairo_pdf_surface_update_object (cairo_pdf_surface_t *surface,
291
cairo_pdf_resource_t resource)
293
cairo_pdf_object_t *object;
295
object = _cairo_array_index (&surface->objects, resource.id - 1);
296
object->offset = _cairo_output_stream_get_position (surface->output);
299
static cairo_surface_t *
300
_cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
304
cairo_pdf_surface_t *surface;
305
cairo_status_t status;
307
surface = malloc (sizeof (cairo_pdf_surface_t));
308
if (surface == NULL) {
309
/* destroy stream on behalf of caller */
310
status = _cairo_output_stream_destroy (output);
311
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
312
return (cairo_surface_t*) &_cairo_surface_nil;
315
_cairo_surface_init (&surface->base, &cairo_pdf_surface_backend,
316
CAIRO_CONTENT_COLOR_ALPHA);
318
surface->output = output;
320
surface->width = width;
321
surface->height = height;
322
cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
324
_cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
325
_cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
326
_cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
327
_cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
328
_cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
329
_cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_group_element_t));
330
_cairo_array_init (&surface->content_group, sizeof (cairo_pdf_group_element_t));
332
_cairo_pdf_group_resources_init (&surface->group_stream.resources);
333
_cairo_pdf_group_resources_init (&surface->content_stream.resources);
335
surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
336
if (! surface->font_subsets) {
337
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
341
surface->next_available_resource.id = 1;
342
surface->pages_resource = _cairo_pdf_surface_new_object (surface);
343
if (surface->pages_resource.id == 0)
346
surface->compress_content = TRUE;
347
surface->pdf_stream.active = FALSE;
348
surface->pdf_stream.old_output = NULL;
349
surface->content_stream.active = FALSE;
350
surface->content_stream.stream = NULL;
351
surface->content_stream.mem_stream = NULL;
352
surface->group_stream.active = FALSE;
353
surface->group_stream.stream = NULL;
354
surface->group_stream.mem_stream = NULL;
356
surface->current_group = NULL;
357
surface->current_resources = NULL;
359
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
361
surface->force_fallbacks = FALSE;
363
/* Document header */
364
_cairo_output_stream_printf (surface->output,
366
_cairo_output_stream_printf (surface->output,
367
"%%%c%c%c%c\r\n", 181, 237, 174, 251);
369
surface->paginated_surface = _cairo_paginated_surface_create (
371
CAIRO_CONTENT_COLOR_ALPHA,
373
&cairo_pdf_surface_paginated_backend);
374
if (surface->paginated_surface->status == CAIRO_STATUS_SUCCESS)
375
return surface->paginated_surface;
378
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
380
_cairo_array_fini (&surface->objects);
383
/* destroy stream on behalf of caller */
384
status = _cairo_output_stream_destroy (output);
386
return (cairo_surface_t*) &_cairo_surface_nil;
390
* cairo_pdf_surface_create_for_stream:
391
* @write_func: a #cairo_write_func_t to accept the output data
392
* @closure: the closure argument for @write_func
393
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
394
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
396
* Creates a PDF surface of the specified size in points to be written
397
* incrementally to the stream represented by @write_func and @closure.
399
* Return value: a pointer to the newly created surface. The caller
400
* owns the surface and should call cairo_surface_destroy when done
403
* This function always returns a valid pointer, but it will return a
404
* pointer to a "nil" surface if an error such as out of memory
405
* occurs. You can use cairo_surface_status() to check for this.
410
cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func,
412
double width_in_points,
413
double height_in_points)
415
cairo_status_t status;
416
cairo_output_stream_t *output;
418
output = _cairo_output_stream_create (write_func, NULL, closure);
419
status = _cairo_output_stream_get_status (output);
421
return (cairo_surface_t*) &_cairo_surface_nil;
423
return _cairo_pdf_surface_create_for_stream_internal (output,
429
* cairo_pdf_surface_create:
430
* @filename: a filename for the PDF output (must be writable)
431
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
432
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
434
* Creates a PDF surface of the specified size in points to be written
437
* Return value: a pointer to the newly created surface. The caller
438
* owns the surface and should call cairo_surface_destroy when done
441
* This function always returns a valid pointer, but it will return a
442
* pointer to a "nil" surface if an error such as out of memory
443
* occurs. You can use cairo_surface_status() to check for this.
448
cairo_pdf_surface_create (const char *filename,
449
double width_in_points,
450
double height_in_points)
452
cairo_status_t status;
453
cairo_output_stream_t *output;
455
output = _cairo_output_stream_create_for_filename (filename);
456
status = _cairo_output_stream_get_status (output);
458
return (status == CAIRO_STATUS_WRITE_ERROR) ?
459
(cairo_surface_t*) &_cairo_surface_nil_write_error :
460
(cairo_surface_t*) &_cairo_surface_nil;
462
return _cairo_pdf_surface_create_for_stream_internal (output,
468
_cairo_surface_is_pdf (cairo_surface_t *surface)
470
return surface->backend == &cairo_pdf_surface_backend;
473
/* If the abstract_surface is a paginated surface, and that paginated
474
* surface's target is a pdf_surface, then set pdf_surface to that
475
* target. Otherwise return CAIRO_STATUS_SURFACE_TYPE_MISMATCH.
477
static cairo_status_t
478
_extract_pdf_surface (cairo_surface_t *surface,
479
cairo_pdf_surface_t **pdf_surface)
481
cairo_surface_t *target;
483
if (! _cairo_surface_is_paginated (surface))
484
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
486
target = _cairo_paginated_surface_get_target (surface);
488
if (! _cairo_surface_is_pdf (target))
489
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
491
*pdf_surface = (cairo_pdf_surface_t *) target;
493
return CAIRO_STATUS_SUCCESS;
497
* cairo_pdf_surface_set_size:
498
* @surface: a PDF cairo_surface_t
499
* @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
500
* @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
502
* Changes the size of a PDF surface for the current (and
505
* This function should only be called before any drawing operations
506
* have been performed on the current page. The simplest way to do
507
* this is to call this function immediately after creating the
508
* surface or immediately after completing a page with either
509
* cairo_show_page() or cairo_copy_page().
514
cairo_pdf_surface_set_size (cairo_surface_t *surface,
515
double width_in_points,
516
double height_in_points)
518
cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
519
cairo_status_t status;
521
status = _extract_pdf_surface (surface, &pdf_surface);
523
status = _cairo_surface_set_error (surface, status);
527
pdf_surface->width = width_in_points;
528
pdf_surface->height = height_in_points;
529
cairo_matrix_init (&pdf_surface->cairo_to_pdf, 1, 0, 0, -1, 0, height_in_points);
530
status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
534
status = _cairo_surface_set_error (surface, status);
538
_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
540
_cairo_pdf_group_element_array_finish (&surface->content_group);
541
_cairo_pdf_group_element_array_finish (&surface->knockout_group);
542
_cairo_array_truncate (&surface->content_group, 0);
543
_cairo_array_truncate (&surface->knockout_group, 0);
547
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
549
_cairo_array_init (&res->alphas, sizeof (double));
550
_cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t));
551
_cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t));
552
_cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t));
553
_cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t));
557
_cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
559
_cairo_array_fini (&res->alphas);
560
_cairo_array_fini (&res->smasks);
561
_cairo_array_fini (&res->patterns);
562
_cairo_array_fini (&res->xobjects);
563
_cairo_array_fini (&res->fonts);
567
_cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
569
_cairo_array_truncate (&res->alphas, 0);
570
_cairo_array_truncate (&res->smasks, 0);
571
_cairo_array_truncate (&res->patterns, 0);
572
_cairo_array_truncate (&res->xobjects, 0);
573
_cairo_array_truncate (&res->fonts, 0);
576
static cairo_status_t
577
_cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
583
cairo_status_t status;
584
cairo_pdf_group_resources_t *res = surface->current_resources;
586
num_alphas = _cairo_array_num_elements (&res->alphas);
587
for (i = 0; i < num_alphas; i++) {
588
_cairo_array_copy_element (&res->alphas, i, &other);
589
if (alpha == other) {
591
return CAIRO_STATUS_SUCCESS;
595
status = _cairo_array_append (&res->alphas, &alpha);
599
*index = _cairo_array_num_elements (&res->alphas) - 1;
601
return CAIRO_STATUS_SUCCESS;
604
static cairo_status_t
605
_cairo_pdf_surface_add_smask (cairo_pdf_surface_t *surface,
606
cairo_pdf_resource_t smask)
608
return _cairo_array_append (&surface->current_resources->smasks, &smask);
611
static cairo_status_t
612
_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t *surface,
613
cairo_pdf_resource_t pattern)
615
return _cairo_array_append (&surface->current_resources->patterns, &pattern);
618
static cairo_status_t
619
_cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface,
620
cairo_pdf_resource_t xobject)
622
return _cairo_array_append (&surface->current_resources->xobjects, &xobject);
625
static cairo_status_t
626
_cairo_pdf_surface_add_font (cairo_pdf_surface_t *surface,
627
unsigned int font_id,
628
unsigned int subset_id)
630
cairo_pdf_font_t font;
632
cairo_status_t status;
633
cairo_pdf_group_resources_t *res = surface->current_resources;
635
num_fonts = _cairo_array_num_elements (&res->fonts);
636
for (i = 0; i < num_fonts; i++) {
637
_cairo_array_copy_element (&res->fonts, i, &font);
638
if (font.font_id == font_id &&
639
font.subset_id == subset_id)
640
return CAIRO_STATUS_SUCCESS;
643
num_fonts = _cairo_array_num_elements (&surface->fonts);
644
for (i = 0; i < num_fonts; i++) {
645
_cairo_array_copy_element (&surface->fonts, i, &font);
646
if (font.font_id == font_id &&
647
font.subset_id == subset_id)
648
return _cairo_array_append (&res->fonts, &font);
651
font.font_id = font_id;
652
font.subset_id = subset_id;
653
font.subset_resource = _cairo_pdf_surface_new_object (surface);
654
if (font.subset_resource.id == 0)
655
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
657
status = _cairo_array_append (&surface->fonts, &font);
661
return _cairo_array_append (&res->fonts, &font);
664
static cairo_pdf_resource_t
665
_cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface,
666
unsigned int font_id,
667
unsigned int subset_id)
669
cairo_pdf_font_t font;
671
cairo_pdf_resource_t resource;
673
num_fonts = _cairo_array_num_elements (&surface->fonts);
674
for (i = 0; i < num_fonts; i++) {
675
_cairo_array_copy_element (&surface->fonts, i, &font);
676
if (font.font_id == font_id && font.subset_id == subset_id)
677
return font.subset_resource;
685
_cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface,
686
cairo_pdf_group_resources_t *res)
688
int num_alphas, num_smasks, num_resources, i;
690
cairo_pdf_resource_t *smask, *pattern, *xobject;
691
cairo_pdf_font_t *font;
693
_cairo_output_stream_printf (surface->output, " /Resources <<\r\n");
695
num_alphas = _cairo_array_num_elements (&res->alphas);
696
num_smasks = _cairo_array_num_elements (&res->smasks);
697
if (num_alphas > 0 || num_smasks > 0) {
698
_cairo_output_stream_printf (surface->output,
699
" /ExtGState <<\r\n");
701
for (i = 0; i < num_alphas; i++) {
702
_cairo_array_copy_element (&res->alphas, i, &alpha);
703
_cairo_output_stream_printf (surface->output,
704
" /a%d << /CA %f /ca %f >>\r\n",
708
for (i = 0; i < num_smasks; i++) {
709
smask = _cairo_array_index (&res->smasks, i);
710
_cairo_output_stream_printf (surface->output,
712
smask->id, smask->id);
715
_cairo_output_stream_printf (surface->output,
719
num_resources = _cairo_array_num_elements (&res->patterns);
720
if (num_resources > 0) {
721
_cairo_output_stream_printf (surface->output,
723
for (i = 0; i < num_resources; i++) {
724
pattern = _cairo_array_index (&res->patterns, i);
725
_cairo_output_stream_printf (surface->output,
727
pattern->id, pattern->id);
730
_cairo_output_stream_printf (surface->output,
734
num_resources = _cairo_array_num_elements (&res->xobjects);
735
if (num_resources > 0) {
736
_cairo_output_stream_printf (surface->output,
739
for (i = 0; i < num_resources; i++) {
740
xobject = _cairo_array_index (&res->xobjects, i);
741
_cairo_output_stream_printf (surface->output,
743
xobject->id, xobject->id);
746
_cairo_output_stream_printf (surface->output,
750
num_resources = _cairo_array_num_elements (&res->fonts);
751
if (num_resources > 0) {
752
_cairo_output_stream_printf (surface->output," /Font <<\r\n");
753
for (i = 0; i < num_resources; i++) {
754
font = _cairo_array_index (&res->fonts, i);
755
_cairo_output_stream_printf (surface->output,
756
" /f-%d-%d %d 0 R\r\n",
759
font->subset_resource.id);
761
_cairo_output_stream_printf (surface->output, " >>\r\n");
764
_cairo_output_stream_printf (surface->output,
768
static cairo_pdf_resource_t
769
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
770
cairo_bool_t compressed,
775
cairo_pdf_resource_t self, length;
776
cairo_output_stream_t *output = NULL;
778
self = _cairo_pdf_surface_new_object (surface);
782
length = _cairo_pdf_surface_new_object (surface);
787
output = _cairo_deflate_stream_create (surface->output);
788
if (_cairo_output_stream_get_status (output)) {
794
surface->pdf_stream.active = TRUE;
795
surface->pdf_stream.self = self;
796
surface->pdf_stream.length = length;
797
surface->pdf_stream.compressed = compressed;
799
_cairo_output_stream_printf (surface->output,
801
"<< /Length %d 0 R\r\n",
802
surface->pdf_stream.self.id,
803
surface->pdf_stream.length.id);
805
_cairo_output_stream_printf (surface->output,
806
" /Filter /FlateDecode\r\n");
810
_cairo_output_stream_vprintf (surface->output, fmt, ap);
814
_cairo_output_stream_printf (surface->output,
818
surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
821
assert (surface->pdf_stream.old_output == NULL);
822
surface->pdf_stream.old_output = surface->output;
823
surface->output = output;
826
return surface->pdf_stream.self;
829
static cairo_status_t
830
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
832
cairo_status_t status = CAIRO_STATUS_SUCCESS;
835
if (! surface->pdf_stream.active)
836
return CAIRO_STATUS_SUCCESS;
838
if (surface->pdf_stream.compressed) {
839
status = _cairo_output_stream_destroy (surface->output);
840
surface->output = surface->pdf_stream.old_output;
841
surface->pdf_stream.old_output = NULL;
842
_cairo_output_stream_printf (surface->output,
846
length = _cairo_output_stream_get_position (surface->output) -
847
surface->pdf_stream.start_offset;
848
_cairo_output_stream_printf (surface->output,
852
_cairo_pdf_surface_update_object (surface,
853
surface->pdf_stream.length);
854
_cairo_output_stream_printf (surface->output,
858
surface->pdf_stream.length.id,
861
surface->pdf_stream.active = FALSE;
866
static cairo_pdf_resource_t
867
_cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface,
868
cairo_output_stream_t *mem_stream,
869
cairo_pdf_group_resources_t *resources,
870
cairo_bool_t is_knockout_group)
872
cairo_pdf_resource_t group;
874
group = _cairo_pdf_surface_new_object (surface);
878
_cairo_output_stream_printf (surface->output,
880
"<< /Type /XObject\r\n"
883
_cairo_memory_stream_length (mem_stream));
885
if (surface->compress_content) {
886
_cairo_output_stream_printf (surface->output,
887
" /Filter /FlateDecode\r\n");
890
_cairo_output_stream_printf (surface->output,
891
" /Subtype /Form\r\n"
892
" /BBox [ 0 0 %f %f ]\r\n"
895
" /S /Transparency\r\n"
896
" /CS /DeviceRGB\r\n",
900
if (is_knockout_group)
901
_cairo_output_stream_printf (surface->output,
904
_cairo_output_stream_printf (surface->output,
906
_cairo_pdf_surface_emit_group_resources (surface, resources);
907
_cairo_output_stream_printf (surface->output,
910
_cairo_memory_stream_copy (mem_stream, surface->output);
911
_cairo_output_stream_printf (surface->output,
918
static cairo_status_t
919
_cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface)
921
cairo_status_t status;
923
assert (surface->pdf_stream.active == FALSE);
924
assert (surface->content_stream.active == FALSE);
925
assert (surface->group_stream.active == FALSE);
927
surface->group_stream.active = TRUE;
929
surface->group_stream.mem_stream = _cairo_memory_stream_create ();
931
if (surface->compress_content) {
932
surface->group_stream.stream =
933
_cairo_deflate_stream_create (surface->group_stream.mem_stream);
935
surface->group_stream.stream = surface->group_stream.mem_stream;
937
status = _cairo_output_stream_get_status (surface->group_stream.stream);
941
surface->group_stream.old_output = surface->output;
942
surface->output = surface->group_stream.stream;
943
_cairo_pdf_group_resources_clear (&surface->group_stream.resources);
944
surface->current_resources = &surface->group_stream.resources;
945
surface->group_stream.is_knockout = FALSE;
947
return CAIRO_STATUS_SUCCESS;
950
static cairo_status_t
951
_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface,
952
cairo_pdf_resource_t *first_object)
954
cairo_status_t status;
956
status = _cairo_pdf_surface_open_group (surface);
960
surface->group_stream.is_knockout = TRUE;
961
surface->group_stream.first_object = *first_object;
963
return CAIRO_STATUS_SUCCESS;
966
static cairo_status_t
967
_cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
968
cairo_pdf_resource_t *group)
970
cairo_status_t status;
972
assert (surface->pdf_stream.active == FALSE);
973
assert (surface->group_stream.active == TRUE);
975
if (surface->compress_content) {
976
status = _cairo_output_stream_destroy (surface->group_stream.stream);
980
_cairo_output_stream_printf (surface->group_stream.mem_stream,
983
surface->output = surface->group_stream.old_output;
984
surface->group_stream.active = FALSE;
985
*group = _cairo_pdf_surface_write_memory_stream (surface,
986
surface->group_stream.mem_stream,
987
&surface->group_stream.resources,
988
surface->group_stream.is_knockout);
990
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
992
return _cairo_output_stream_close (surface->group_stream.mem_stream);
995
static cairo_status_t
996
_cairo_pdf_surface_write_group_list (cairo_pdf_surface_t *surface,
997
cairo_array_t *group_list)
1000
cairo_pdf_group_element_t *elem;
1001
cairo_status_t status;
1003
_cairo_output_stream_printf (surface->output, "q\r\n");
1004
if (surface->group_stream.is_knockout) {
1005
_cairo_output_stream_printf (surface->output,
1007
surface->group_stream.first_object.id);
1008
status = _cairo_pdf_surface_add_xobject (surface, surface->group_stream.first_object);
1012
len = _cairo_array_num_elements (group_list);
1013
for (i = 0; i < len; i++) {
1014
elem = _cairo_array_index (group_list, i);
1015
if (elem->type == ELEM_GROUP) {
1016
_cairo_output_stream_printf (surface->output,
1019
status = _cairo_pdf_surface_add_xobject (surface, elem->group);
1022
} else if (elem->type == ELEM_CLIP) {
1023
status = _cairo_pdf_surface_emit_clip (surface, elem->clip_path, elem->fill_rule);
1028
_cairo_output_stream_printf (surface->output, "Q\r\n");
1030
return CAIRO_STATUS_SUCCESS;
1033
static cairo_status_t
1034
_cairo_pdf_surface_start_content_stream (cairo_pdf_surface_t *surface)
1036
cairo_status_t status;
1038
if (surface->content_stream.active)
1039
return CAIRO_STATUS_SUCCESS;
1041
assert (surface->pdf_stream.active == FALSE);
1042
assert (surface->content_stream.active == FALSE);
1043
assert (surface->group_stream.active == FALSE);
1045
surface->content_stream.active = TRUE;
1046
surface->content_stream.mem_stream = _cairo_memory_stream_create ();
1048
if (surface->compress_content) {
1049
surface->content_stream.stream =
1050
_cairo_deflate_stream_create (surface->content_stream.mem_stream);
1052
surface->content_stream.stream = surface->content_stream.mem_stream;
1054
status = _cairo_output_stream_get_status (surface->content_stream.stream);
1058
surface->content_stream.old_output = surface->output;
1059
surface->output = surface->content_stream.stream;
1060
_cairo_pdf_group_resources_clear (&surface->content_stream.resources);
1061
surface->current_resources = &surface->content_stream.resources;
1063
return CAIRO_STATUS_SUCCESS;
1066
static cairo_status_t
1067
_cairo_pdf_surface_add_group_to_content_stream (cairo_pdf_surface_t *surface,
1068
cairo_pdf_resource_t group)
1070
cairo_pdf_group_element_t elem;
1072
memset (&elem, 0, sizeof elem);
1073
elem.type = ELEM_GROUP;
1076
return _cairo_array_append (surface->current_group, &elem);
1080
_cairo_pdf_surface_pause_content_stream (cairo_pdf_surface_t *surface)
1082
assert (surface->pdf_stream.active == FALSE);
1084
if (surface->content_stream.active == FALSE)
1087
surface->output = surface->content_stream.old_output;
1088
surface->content_stream.active = FALSE;
1092
_cairo_pdf_surface_resume_content_stream (cairo_pdf_surface_t *surface)
1094
assert (surface->pdf_stream.active == FALSE);
1096
if (surface->content_stream.active == TRUE)
1099
surface->output = surface->content_stream.stream;
1100
surface->current_resources = &surface->content_stream.resources;
1101
surface->content_stream.active = TRUE;
1104
static cairo_status_t
1105
_cairo_pdf_surface_stop_content_stream (cairo_pdf_surface_t *surface)
1107
cairo_pdf_resource_t group;
1108
cairo_status_t status;
1110
assert (surface->pdf_stream.active == FALSE);
1111
assert (surface->content_stream.active == TRUE);
1113
if (surface->compress_content) {
1114
status = _cairo_output_stream_destroy (surface->content_stream.stream);
1118
_cairo_output_stream_printf (surface->content_stream.mem_stream,
1121
surface->output = surface->content_stream.old_output;
1122
surface->content_stream.active = FALSE;
1123
if (_cairo_memory_stream_length (surface->content_stream.mem_stream) > 0) {
1124
group = _cairo_pdf_surface_write_memory_stream (surface,
1125
surface->content_stream.mem_stream,
1126
&surface->content_stream.resources,
1129
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1131
status = _cairo_pdf_surface_add_group_to_content_stream (surface, group);
1135
surface->content_stream.active = FALSE;
1137
return _cairo_output_stream_close (surface->content_stream.mem_stream);
1140
static cairo_status_t
1141
_cairo_pdf_surface_check_content_stream_size (cairo_pdf_surface_t *surface)
1143
cairo_status_t status;
1145
if (surface->content_stream.active == FALSE)
1146
return CAIRO_STATUS_SUCCESS;
1148
if (_cairo_memory_stream_length (surface->content_stream.mem_stream) > GROUP_STREAM_LIMIT) {
1149
status = _cairo_pdf_surface_stop_content_stream (surface);
1153
status = _cairo_pdf_surface_start_content_stream (surface);
1158
return CAIRO_STATUS_SUCCESS;
1162
_cairo_pdf_group_element_array_finish (cairo_array_t *array)
1165
cairo_pdf_group_element_t *elem;
1167
len = _cairo_array_num_elements (array);
1168
for (i = 0; i < len; i++) {
1169
elem = _cairo_array_index (array, i);
1170
if (elem->type == ELEM_CLIP && elem->clip_path)
1171
_cairo_path_fixed_destroy (elem->clip_path);
1175
static cairo_surface_t *
1176
_cairo_pdf_surface_create_similar (void *abstract_surface,
1177
cairo_content_t content,
1181
return _cairo_meta_surface_create (content, width, height);
1184
static cairo_status_t
1185
_cairo_pdf_surface_finish (void *abstract_surface)
1187
cairo_status_t status, status2;
1188
cairo_pdf_surface_t *surface = abstract_surface;
1190
cairo_pdf_resource_t info, catalog;
1192
status = _cairo_pdf_surface_emit_font_subsets (surface);
1194
_cairo_pdf_surface_write_pages (surface);
1196
info = _cairo_pdf_surface_write_info (surface);
1197
if (info.id == 0 && status == CAIRO_STATUS_SUCCESS)
1198
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1200
catalog = _cairo_pdf_surface_write_catalog (surface);
1201
if (catalog.id == 0 && status == CAIRO_STATUS_SUCCESS)
1202
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1204
offset = _cairo_pdf_surface_write_xref (surface);
1206
_cairo_output_stream_printf (surface->output,
1212
surface->next_available_resource.id,
1216
_cairo_output_stream_printf (surface->output,
1222
status2 = _cairo_output_stream_destroy (surface->output);
1223
if (status == CAIRO_STATUS_SUCCESS)
1226
_cairo_array_fini (&surface->objects);
1227
_cairo_array_fini (&surface->pages);
1228
_cairo_array_fini (&surface->rgb_linear_functions);
1229
_cairo_array_fini (&surface->alpha_linear_functions);
1230
_cairo_array_fini (&surface->fonts);
1232
_cairo_pdf_group_resources_fini (&surface->group_stream.resources);
1233
_cairo_pdf_group_resources_fini (&surface->content_stream.resources);
1235
_cairo_pdf_group_element_array_finish (&surface->knockout_group);
1236
_cairo_array_fini (&surface->knockout_group);
1238
_cairo_pdf_group_element_array_finish (&surface->content_group);
1239
_cairo_array_fini (&surface->content_group);
1241
if (surface->font_subsets) {
1242
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
1243
surface->font_subsets = NULL;
1249
static cairo_int_status_t
1250
_cairo_pdf_surface_start_page (void *abstract_surface)
1252
cairo_status_t status;
1253
cairo_pdf_surface_t *surface = abstract_surface;
1255
surface->current_group = &surface->content_group;
1256
status = _cairo_pdf_surface_start_content_stream (surface);
1261
return CAIRO_STATUS_SUCCESS;
1265
compress_dup (const void *data, unsigned long data_size,
1266
unsigned long *compressed_size)
1270
/* Bound calculation taken from zlib. */
1271
*compressed_size = data_size + (data_size >> 12) + (data_size >> 14) + 11;
1272
compressed = malloc (*compressed_size);
1273
if (compressed == NULL) {
1274
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1278
if (compress (compressed, compressed_size, data, data_size) != Z_OK) {
1279
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1287
/* Emit alpha channel from the image into the given data, providing
1288
* an id that can be used to reference the resulting SMask object.
1290
* In the case that the alpha channel happens to be all opaque, then
1291
* no SMask object will be emitted and *id_ret will be set to 0.
1293
static cairo_status_t
1294
_cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
1295
cairo_image_surface_t *image,
1296
cairo_pdf_resource_t *stream_ret)
1298
cairo_status_t status = CAIRO_STATUS_SUCCESS;
1299
char *alpha, *alpha_compressed;
1300
unsigned long alpha_size, alpha_compressed_size;
1304
cairo_bool_t opaque;
1306
int src_bit, dst_bit;
1308
/* This is the only image format we support, which simplfies things. */
1309
assert (image->format == CAIRO_FORMAT_ARGB32 ||
1310
image->format == CAIRO_FORMAT_A8 ||
1311
image->format == CAIRO_FORMAT_A1 );
1313
if (image->format == CAIRO_FORMAT_A1)
1314
alpha_size = (image->height * image->width + 7)/8;
1316
alpha_size = image->height * image->width;
1317
alpha = malloc (alpha_size);
1318
if (alpha == NULL) {
1319
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1327
for (y = 0; y < image->height; y++) {
1328
if (image->format == CAIRO_FORMAT_ARGB32) {
1329
pixel32 = (uint32_t *) (image->data + y * image->stride);
1331
for (x = 0; x < image->width; x++, pixel32++) {
1332
a = (*pixel32 & 0xff000000) >> 24;
1337
} else if (image->format == CAIRO_FORMAT_A8){
1338
pixel8 = (uint8_t *) (image->data + y * image->stride);
1340
for (x = 0; x < image->width; x++, pixel8++) {
1346
} else { /* image->format == CAIRO_FORMAT_A1 */
1347
pixel8 = (uint8_t *) (image->data + y * image->stride);
1349
for (x = 0; x < image->width; x++, pixel8++) {
1352
if ((*pixel8 >> src_bit) & 1) {
1354
alpha[i] |= (1 << dst_bit);
1356
if (++src_bit > 7) {
1360
if (--dst_bit < 0) {
1368
/* Bail out without emitting smask if it's all opaque. */
1374
alpha_compressed = compress_dup (alpha, alpha_size, &alpha_compressed_size);
1375
if (alpha_compressed == NULL) {
1376
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1380
*stream_ret = _cairo_pdf_surface_open_stream (surface,
1382
" /Type /XObject\r\n"
1383
" /Subtype /Image\r\n"
1386
" /ColorSpace /DeviceGray\r\n"
1387
" /BitsPerComponent %d\r\n"
1388
" /Filter /FlateDecode\r\n",
1389
image->width, image->height,
1390
image->format == CAIRO_FORMAT_A1 ? 1 : 8);
1391
if (stream_ret->id == 0) {
1392
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1393
goto CLEANUP_ALPHA_COMPRESSED;
1396
_cairo_output_stream_write (surface->output, alpha_compressed, alpha_compressed_size);
1397
_cairo_output_stream_printf (surface->output, "\r\n");
1398
status = _cairo_pdf_surface_close_stream (surface);
1400
CLEANUP_ALPHA_COMPRESSED:
1401
free (alpha_compressed);
1408
/* Emit image data into the given surface, providing a resource that
1409
* can be used to reference the data in image_ret. */
1410
static cairo_status_t
1411
_cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
1412
cairo_image_surface_t *image,
1413
cairo_pdf_resource_t *image_ret)
1415
cairo_status_t status = CAIRO_STATUS_SUCCESS;
1416
char *rgb, *compressed;
1417
unsigned long rgb_size, compressed_size;
1420
cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
1421
cairo_bool_t need_smask;
1423
/* XXX: Need to rewrite this as a pdf_surface function with
1424
* pause/resume of content_stream, (currently the only caller does
1425
* the pause/resume already, but that is expected to change in the
1428
/* These are the only image formats we currently support, (which
1429
* makes things a lot simpler here). This is enforced through
1430
* _cairo_pdf_surface_analyze_operation which only accept source surfaces of
1431
* CONTENT_COLOR or CONTENT_COLOR_ALPHA.
1433
assert (image->format == CAIRO_FORMAT_RGB24 ||
1434
image->format == CAIRO_FORMAT_ARGB32 ||
1435
image->format == CAIRO_FORMAT_A8 ||
1436
image->format == CAIRO_FORMAT_A1);
1438
rgb_size = image->height * image->width * 3;
1439
rgb = malloc (rgb_size);
1441
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1446
for (y = 0; y < image->height; y++) {
1447
pixel = (uint32_t *) (image->data + y * image->stride);
1449
for (x = 0; x < image->width; x++, pixel++) {
1450
/* XXX: We're un-premultiplying alpha here. My reading of the PDF
1451
* specification suggests that we should be able to avoid having
1452
* to do this by filling in the SMask's Matte dictionary
1453
* appropriately, but my attempts to do that so far have
1455
if (image->format == CAIRO_FORMAT_ARGB32) {
1457
a = (*pixel & 0xff000000) >> 24;
1463
rgb[i++] = (((*pixel & 0xff0000) >> 16) * 255 + a / 2) / a;
1464
rgb[i++] = (((*pixel & 0x00ff00) >> 8) * 255 + a / 2) / a;
1465
rgb[i++] = (((*pixel & 0x0000ff) >> 0) * 255 + a / 2) / a;
1467
} else if (image->format == CAIRO_FORMAT_RGB24) {
1468
rgb[i++] = (*pixel & 0x00ff0000) >> 16;
1469
rgb[i++] = (*pixel & 0x0000ff00) >> 8;
1470
rgb[i++] = (*pixel & 0x000000ff) >> 0;
1479
compressed = compress_dup (rgb, rgb_size, &compressed_size);
1480
if (compressed == NULL) {
1481
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1486
if (image->format == CAIRO_FORMAT_ARGB32 ||
1487
image->format == CAIRO_FORMAT_A8 ||
1488
image->format == CAIRO_FORMAT_A1) {
1489
status = _cairo_pdf_surface_emit_smask (surface, image, &smask);
1491
goto CLEANUP_COMPRESSED;
1497
#define IMAGE_DICTIONARY " /Type /XObject\r\n" \
1498
" /Subtype /Image\r\n" \
1501
" /ColorSpace /DeviceRGB\r\n" \
1502
" /BitsPerComponent 8\r\n" \
1503
" /Filter /FlateDecode\r\n"
1506
*image_ret = _cairo_pdf_surface_open_stream (surface,
1509
" /SMask %d 0 R\r\n",
1510
image->width, image->height,
1513
*image_ret = _cairo_pdf_surface_open_stream (surface,
1516
image->width, image->height);
1517
if (image_ret->id == 0){
1518
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1519
goto CLEANUP_COMPRESSED;
1522
#undef IMAGE_DICTIONARY
1524
_cairo_output_stream_write (surface->output, compressed, compressed_size);
1525
_cairo_output_stream_printf (surface->output, "\r\n");
1526
status = _cairo_pdf_surface_close_stream (surface);
1536
static cairo_status_t
1537
_cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
1538
cairo_surface_pattern_t *pattern,
1539
cairo_pdf_resource_t *resource,
1543
cairo_surface_t *pat_surface;
1544
cairo_surface_attributes_t pat_attr;
1545
cairo_image_surface_t *image;
1547
cairo_status_t status = CAIRO_STATUS_SUCCESS;
1549
status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
1550
(cairo_surface_t *)surface,
1552
&pat_surface, &pat_attr);
1556
status = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra);
1560
status = _cairo_pdf_surface_emit_image (surface, image, resource);
1564
*width = image->width;
1565
*height = image->height;
1568
_cairo_surface_release_source_image (pat_surface, image, image_extra);
1570
_cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr);
1575
static cairo_status_t
1576
_cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
1577
cairo_surface_t *meta_surface,
1578
cairo_pdf_resource_t *resource)
1580
cairo_array_t group;
1581
cairo_array_t *old_group;
1582
double old_width, old_height;
1583
cairo_matrix_t old_cairo_to_pdf;
1584
cairo_rectangle_int16_t meta_extents;
1585
cairo_status_t status;
1588
status = _cairo_surface_get_extents (meta_surface, &meta_extents);
1592
_cairo_pdf_surface_resume_content_stream (surface);
1593
status = _cairo_pdf_surface_stop_content_stream (surface);
1597
_cairo_array_init (&group, sizeof (cairo_pdf_group_element_t));
1598
old_group = surface->current_group;
1599
old_width = surface->width;
1600
old_height = surface->height;
1601
old_cairo_to_pdf = surface->cairo_to_pdf;
1602
surface->current_group = &group;
1603
surface->width = meta_extents.width;
1604
surface->height = meta_extents.height;
1605
cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height);
1607
status = _cairo_pdf_surface_start_content_stream (surface);
1611
if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
1612
status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
1616
_cairo_output_stream_printf (surface->output,
1617
"q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\r\n",
1623
status = _cairo_meta_surface_replay (meta_surface, &surface->base);
1627
status = _cairo_pdf_surface_stop_content_stream (surface);
1631
status = _cairo_pdf_surface_open_group (surface);
1635
status = _cairo_pdf_surface_write_group_list (surface, &group);
1639
status = _cairo_pdf_surface_close_group (surface, resource);
1644
surface->current_group = old_group;
1645
surface->width = old_width;
1646
surface->height = old_height;
1647
surface->cairo_to_pdf = old_cairo_to_pdf;
1649
_cairo_pdf_group_element_array_finish (&group);
1650
_cairo_array_fini (&group);
1654
status = _cairo_pdf_surface_start_content_stream (surface);
1658
_cairo_pdf_surface_pause_content_stream (surface);
1660
return CAIRO_STATUS_SUCCESS;
1664
_cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t *surface,
1665
cairo_solid_pattern_t *pattern)
1667
surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_SOLID;
1668
surface->emitted_pattern.red = pattern->color.red;
1669
surface->emitted_pattern.green = pattern->color.green;
1670
surface->emitted_pattern.blue = pattern->color.blue;
1671
surface->emitted_pattern.alpha = pattern->color.alpha;
1672
surface->emitted_pattern.smask.id = 0;
1673
surface->emitted_pattern.pattern.id = 0;
1676
static cairo_status_t
1677
_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
1678
cairo_surface_pattern_t *pattern)
1680
cairo_pdf_resource_t stream;
1681
cairo_status_t status = CAIRO_STATUS_SUCCESS;
1682
cairo_pdf_resource_t pattern_resource = {0}; /* squelch bogus compiler warning */
1683
cairo_matrix_t cairo_p2d, pdf_p2d;
1684
cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
1685
double xstep, ystep;
1686
cairo_rectangle_int16_t surface_extents;
1687
int pattern_width = 0; /* squelch bogus compiler warning */
1688
int pattern_height = 0; /* squelch bogus compiler warning */
1691
_cairo_pdf_surface_pause_content_stream (surface);
1693
if (_cairo_surface_is_meta (pattern->surface)) {
1694
cairo_surface_t *meta_surface = pattern->surface;
1695
cairo_rectangle_int16_t pattern_extents;
1697
status = _cairo_pdf_surface_emit_meta_surface (surface,
1703
status = _cairo_surface_get_extents (meta_surface, &pattern_extents);
1707
pattern_width = pattern_extents.width;
1708
pattern_height = pattern_extents.height;
1710
status = _cairo_pdf_surface_emit_image_surface (surface,
1719
status = _cairo_surface_get_extents (&surface->base, &surface_extents);
1723
bbox_x = pattern_width;
1724
bbox_y = pattern_height;
1726
/* We implement EXTEND_PAD like EXTEND_NONE for now */
1727
case CAIRO_EXTEND_PAD:
1728
case CAIRO_EXTEND_NONE:
1730
/* In PS/PDF, (as far as I can tell), all patterns are
1731
* repeating. So we support cairo's EXTEND_NONE semantics
1732
* by setting the repeat step size to a size large enough
1733
* to guarantee that no more than a single occurrence will
1736
* First, map the surface extents into pattern space (since
1737
* xstep and ystep are in pattern space). Then use an upper
1738
* bound on the length of the diagonal of the pattern image
1739
* and the surface as repeat size. This guarantees to never
1742
double x1 = 0.0, y1 = 0.0;
1743
double x2 = surface->width, y2 = surface->height;
1744
_cairo_matrix_transform_bounding_box (&pattern->base.matrix,
1748
/* Rather than computing precise bounds of the union, just
1749
* add the surface extents unconditionally. We only
1750
* required an answer that's large enough, we don't really
1751
* care if it's not as tight as possible.*/
1752
xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
1753
pattern_width + pattern_height);
1756
case CAIRO_EXTEND_REPEAT:
1757
xstep = pattern_width;
1758
ystep = pattern_height;
1760
case CAIRO_EXTEND_REFLECT:
1761
bbox_x = pattern_width*2;
1762
bbox_y = pattern_height*2;
1766
/* All the rest (if any) should have been analyzed away, so this
1767
* case should be unreachable. */
1774
/* At this point, (that is, within the surface backend interface),
1775
* the pattern's matrix maps from cairo's device space to cairo's
1776
* pattern space, (both with their origin at the upper-left, and
1777
* cairo's pattern space of size width,height).
1779
* Then, we must emit a PDF pattern object that maps from its own
1780
* pattern space, (which has a size that we establish in the BBox
1781
* dictionary entry), to the PDF page's *initial* space, (which
1782
* does not benefit from the Y-axis flipping matrix that we emit
1783
* on each page). So the PDF patterns matrix maps from a
1784
* (width,height) pattern space to a device space with the origin
1785
* in the lower-left corner.
1787
* So to handle all of that, we start with an identity matrix for
1788
* the PDF pattern to device matrix. We translate it up by the
1789
* image height then flip it in the Y direction, (moving us from
1790
* the PDF origin to cairo's origin). We then multiply in the
1791
* inverse of the cairo pattern matrix, (since it maps from device
1792
* to pattern, while we're setting up pattern to device). Finally,
1793
* we translate back down by the image height and flip again to
1794
* end up at the lower-left origin that PDF expects.
1796
* Additionally, within the stream that paints the pattern itself,
1797
* we are using a PDF image object that has a size of (1,1) so we
1798
* have to scale it up by the image width and height to fill our
1801
cairo_p2d = pattern->base.matrix;
1802
status = cairo_matrix_invert (&cairo_p2d);
1803
/* cairo_pattern_set_matrix ensures the matrix is invertible */
1804
assert (status == CAIRO_STATUS_SUCCESS);
1806
cairo_matrix_init_identity (&pdf_p2d);
1807
cairo_matrix_translate (&pdf_p2d, 0.0, surface_extents.height);
1808
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
1809
cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
1810
cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
1811
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
1813
stream = _cairo_pdf_surface_open_stream (surface,
1815
" /BBox [0 0 %d %d]\r\n"
1818
" /PatternType 1\r\n"
1819
" /TilingType 1\r\n"
1821
" /Matrix [ %f %f %f %f %f %f ]\r\n"
1822
" /Resources << /XObject << /x%d %d 0 R >> >>\r\n",
1825
pdf_p2d.xx, pdf_p2d.yx,
1826
pdf_p2d.xy, pdf_p2d.yy,
1827
pdf_p2d.x0, pdf_p2d.y0,
1828
pattern_resource.id,
1829
pattern_resource.id);
1831
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1833
if (_cairo_surface_is_meta (pattern->surface)) {
1834
if (extend == CAIRO_EXTEND_REFLECT) {
1835
_cairo_output_stream_printf (surface->output,
1836
"q 0 0 %d %d re W n /x%d Do Q\r\n"
1837
"q -1 0 0 1 %d 0 cm 0 0 %d %d re W n /x%d Do Q\r\n"
1838
"q 1 0 0 -1 0 %d cm 0 0 %d %d re W n /x%d Do Q\r\n"
1839
"q -1 0 0 -1 %d %d cm 0 0 %d %d re W n /x%d Do Q\r\n",
1840
pattern_width, pattern_height,
1841
pattern_resource.id,
1842
pattern_width*2, pattern_width, pattern_height,
1843
pattern_resource.id,
1844
pattern_height*2, pattern_width, pattern_height,
1845
pattern_resource.id,
1846
pattern_width*2, pattern_height*2, pattern_width, pattern_height,
1847
pattern_resource.id);
1849
_cairo_output_stream_printf (surface->output,
1851
pattern_resource.id);
1854
_cairo_output_stream_printf (surface->output,
1855
"q %d 0 0 %d 0 0 cm /x%d Do Q\r\n",
1856
pattern_width, pattern_height,
1857
pattern_resource.id);
1860
status = _cairo_pdf_surface_close_stream (surface);
1864
_cairo_pdf_surface_resume_content_stream (surface);
1866
surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_SURFACE;
1867
surface->emitted_pattern.smask.id = 0;
1868
surface->emitted_pattern.pattern = stream;
1869
surface->emitted_pattern.alpha = 1.0;
1871
return CAIRO_STATUS_SUCCESS;
1874
typedef struct _cairo_pdf_color_stop {
1877
cairo_pdf_resource_t resource;
1878
} cairo_pdf_color_stop_t;
1880
static cairo_status_t
1881
cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t *surface,
1882
cairo_pdf_color_stop_t *stop1,
1883
cairo_pdf_color_stop_t *stop2,
1884
cairo_pdf_resource_t *function)
1887
cairo_pdf_rgb_linear_function_t elem;
1888
cairo_pdf_resource_t res;
1889
cairo_status_t status;
1891
num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions);
1892
for (i = 0; i < num_elems; i++) {
1893
_cairo_array_copy_element (&surface->rgb_linear_functions, i, &elem);
1894
if (memcmp (&elem.color1[0], &stop1->color[0], sizeof (double)*3) != 0)
1896
if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0)
1898
*function = elem.resource;
1899
return CAIRO_STATUS_SUCCESS;
1902
res = _cairo_pdf_surface_new_object (surface);
1904
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1906
_cairo_output_stream_printf (surface->output,
1908
"<< /FunctionType 2\r\n"
1909
" /Domain [ 0 1 ]\r\n"
1910
" /C0 [ %f %f %f ]\r\n"
1911
" /C1 [ %f %f %f ]\r\n"
1923
elem.resource = res;
1924
memcpy (&elem.color1[0], &stop1->color[0], sizeof (double)*3);
1925
memcpy (&elem.color2[0], &stop2->color[0], sizeof (double)*3);
1927
status = _cairo_array_append (&surface->rgb_linear_functions, &elem);
1933
static cairo_status_t
1934
cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t *surface,
1935
cairo_pdf_color_stop_t *stop1,
1936
cairo_pdf_color_stop_t *stop2,
1937
cairo_pdf_resource_t *function)
1940
cairo_pdf_alpha_linear_function_t elem;
1941
cairo_pdf_resource_t res;
1942
cairo_status_t status;
1944
num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions);
1945
for (i = 0; i < num_elems; i++) {
1946
_cairo_array_copy_element (&surface->alpha_linear_functions, i, &elem);
1947
if (elem.alpha1 != stop1->color[3])
1949
if (elem.alpha2 != stop2->color[3])
1951
*function = elem.resource;
1952
return CAIRO_STATUS_SUCCESS;
1955
res = _cairo_pdf_surface_new_object (surface);
1957
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1959
_cairo_output_stream_printf (surface->output,
1961
"<< /FunctionType 2\r\n"
1962
" /Domain [ 0 1 ]\r\n"
1972
elem.resource = res;
1973
elem.alpha1 = stop1->color[3];
1974
elem.alpha2 = stop2->color[3];
1976
status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
1982
static cairo_status_t
1983
_cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
1984
unsigned int n_stops,
1985
cairo_pdf_color_stop_t *stops,
1986
cairo_bool_t is_alpha,
1987
cairo_pdf_resource_t *function)
1989
cairo_pdf_resource_t res;
1991
cairo_status_t status;
1993
/* emit linear gradients between pairs of subsequent stops... */
1994
for (i = 0; i < n_stops-1; i++) {
1996
status = cairo_pdf_surface_emit_alpha_linear_function (surface,
1999
&stops[i].resource);
2003
status = cairo_pdf_surface_emit_rgb_linear_function (surface,
2006
&stops[i].resource);
2012
/* ... and stitch them together */
2013
res = _cairo_pdf_surface_new_object (surface);
2015
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2017
_cairo_output_stream_printf (surface->output,
2019
"<< /FunctionType 3\r\n"
2020
" /Domain [ %f %f ]\r\n",
2023
stops[n_stops - 1].offset);
2025
_cairo_output_stream_printf (surface->output,
2027
for (i = 0; i < n_stops-1; i++)
2028
_cairo_output_stream_printf (surface->output,
2029
"%d 0 R ", stops[i].resource.id);
2030
_cairo_output_stream_printf (surface->output,
2033
_cairo_output_stream_printf (surface->output,
2035
for (i = 1; i < n_stops-1; i++)
2036
_cairo_output_stream_printf (surface->output,
2037
"%f ", stops[i].offset);
2038
_cairo_output_stream_printf (surface->output,
2041
_cairo_output_stream_printf (surface->output,
2043
for (i = 1; i < n_stops; i++)
2044
_cairo_output_stream_printf (surface->output,
2046
_cairo_output_stream_printf (surface->output,
2049
_cairo_output_stream_printf (surface->output,
2055
return CAIRO_STATUS_SUCCESS;
2060
calc_gradient_color (cairo_pdf_color_stop_t *new_stop,
2061
cairo_pdf_color_stop_t *stop1,
2062
cairo_pdf_color_stop_t *stop2)
2065
double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
2067
for (i = 0; i < 4; i++)
2068
new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
2071
#define COLOR_STOP_EPSILON 1e-6
2073
static cairo_status_t
2074
_cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
2075
cairo_gradient_pattern_t *pattern,
2076
cairo_pdf_resource_t *color_function,
2077
cairo_pdf_resource_t *alpha_function)
2079
cairo_pdf_color_stop_t *allstops, *stops;
2080
unsigned int n_stops;
2082
cairo_bool_t emit_alpha = FALSE;
2083
cairo_status_t status;
2085
color_function->id = 0;
2086
alpha_function->id = 0;
2088
allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t));
2089
if (allstops == NULL)
2090
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2092
stops = &allstops[1];
2093
n_stops = pattern->n_stops;
2095
for (i = 0; i < n_stops; i++) {
2096
stops[i].color[0] = pattern->stops[i].color.red;
2097
stops[i].color[1] = pattern->stops[i].color.green;
2098
stops[i].color[2] = pattern->stops[i].color.blue;
2099
stops[i].color[3] = pattern->stops[i].color.alpha;
2100
if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
2102
stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
2105
if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
2106
pattern->base.extend == CAIRO_EXTEND_REFLECT) {
2107
if (stops[0].offset > COLOR_STOP_EPSILON) {
2108
if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
2109
memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
2111
calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
2115
stops[0].offset = 0.0;
2117
if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
2118
if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
2119
memcpy (&stops[n_stops],
2120
&stops[n_stops - 1],
2121
sizeof (cairo_pdf_color_stop_t));
2123
calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
2127
stops[n_stops-1].offset = 1.0;
2131
/* no need for stitched function */
2132
status = cairo_pdf_surface_emit_rgb_linear_function (surface,
2140
status = cairo_pdf_surface_emit_alpha_linear_function (surface,
2148
/* multiple stops: stitch. XXX possible optimization: regulary spaced
2149
* stops do not require stitching. XXX */
2150
status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
2159
status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
2174
static cairo_status_t
2175
_cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface,
2176
cairo_gradient_pattern_t *pattern,
2177
cairo_pdf_resource_t *function,
2181
cairo_pdf_resource_t res;
2184
res = _cairo_pdf_surface_new_object (surface);
2186
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2188
_cairo_output_stream_printf (surface->output,
2190
"<< /FunctionType 3\r\n"
2191
" /Domain [ %d %d ]\r\n",
2196
_cairo_output_stream_printf (surface->output,
2198
for (i = begin; i < end; i++)
2199
_cairo_output_stream_printf (surface->output,
2200
"%d 0 R ", function->id);
2201
_cairo_output_stream_printf (surface->output,
2204
_cairo_output_stream_printf (surface->output,
2206
for (i = begin + 1; i < end; i++)
2207
_cairo_output_stream_printf (surface->output,
2209
_cairo_output_stream_printf (surface->output,
2212
_cairo_output_stream_printf (surface->output,
2214
for (i = begin; i < end; i++) {
2215
if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) {
2216
_cairo_output_stream_printf (surface->output,
2219
_cairo_output_stream_printf (surface->output,
2223
_cairo_output_stream_printf (surface->output,
2226
_cairo_output_stream_printf (surface->output,
2232
return CAIRO_STATUS_SUCCESS;
2235
static cairo_pdf_resource_t
2236
cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
2237
cairo_pdf_resource_t gradient_mask)
2239
cairo_pdf_resource_t xobj_resource, smask_resource, gstate_resource;
2241
xobj_resource = _cairo_pdf_surface_open_stream (surface,
2242
surface->compress_content,
2243
" /Type /XObject\r\n"
2244
" /Subtype /Form\r\n"
2246
" /BBox [ 0 0 %f %f ]\r\n"
2248
" << /ExtGState\r\n"
2249
" << /a0 << /ca 1 /CA 1 >>"
2252
" << /p%d %d 0 R >>\r\n"
2255
" << /Type /Group\r\n"
2256
" /S /Transparency\r\n"
2257
" /CS /DeviceGray\r\n"
2263
if (xobj_resource.id == 0)
2264
return xobj_resource;
2266
_cairo_output_stream_printf (surface->output,
2269
"/Pattern cs /p%d scn\r\n"
2277
if (_cairo_pdf_surface_close_stream (surface)) {
2278
smask_resource.id = 0;
2279
return smask_resource;
2282
smask_resource = _cairo_pdf_surface_new_object (surface);
2283
if (smask_resource.id == 0)
2284
return smask_resource;
2286
_cairo_output_stream_printf (surface->output,
2288
"<< /Type /Mask\r\n"
2289
" /S /Luminosity\r\n"
2296
/* Create GState which uses the transparency group as an SMask. */
2297
gstate_resource = _cairo_pdf_surface_new_object (surface);
2298
if (gstate_resource.id == 0)
2299
return gstate_resource;
2301
_cairo_output_stream_printf (surface->output,
2303
"<< /Type /ExtGState\r\n"
2304
" /SMask %d 0 R\r\n"
2313
return gstate_resource;
2316
static cairo_status_t
2317
_cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
2318
cairo_linear_pattern_t *pattern)
2320
cairo_pdf_resource_t pattern_resource, smask;
2321
cairo_pdf_resource_t color_function, alpha_function;
2322
double x1, y1, x2, y2;
2323
double _x1, _y1, _x2, _y2;
2324
cairo_matrix_t pat_to_pdf;
2325
cairo_extend_t extend;
2326
cairo_status_t status;
2327
cairo_gradient_pattern_t *gradient = &pattern->base;
2328
double first_stop, last_stop;
2329
int repeat_begin = 0, repeat_end = 1;
2331
extend = cairo_pattern_get_extend (&pattern->base.base);
2332
_cairo_pdf_surface_pause_content_stream (surface);
2334
pat_to_pdf = pattern->base.base.matrix;
2335
status = cairo_matrix_invert (&pat_to_pdf);
2336
/* cairo_pattern_set_matrix ensures the matrix is invertible */
2337
assert (status == CAIRO_STATUS_SUCCESS);
2339
cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
2340
first_stop = _cairo_fixed_to_double (gradient->stops[0].x);
2341
last_stop = _cairo_fixed_to_double (gradient->stops[gradient->n_stops - 1].x);
2343
if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
2344
pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
2346
int x_rep = 0, y_rep = 0;
2348
x1 = _cairo_fixed_to_double (pattern->p1.x);
2349
y1 = _cairo_fixed_to_double (pattern->p1.y);
2350
cairo_matrix_transform_point (&pat_to_pdf, &x1, &y1);
2352
x2 = _cairo_fixed_to_double (pattern->p2.x);
2353
y2 = _cairo_fixed_to_double (pattern->p2.y);
2354
cairo_matrix_transform_point (&pat_to_pdf, &x2, &y2);
2356
dx = fabs (x2 - x1);
2357
dy = fabs (y2 - y1);
2359
x_rep = (int) ceil (surface->width/dx);
2361
y_rep = (int) ceil (surface->height/dy);
2363
repeat_end = MAX (x_rep, y_rep);
2364
repeat_begin = -repeat_end;
2365
first_stop = repeat_begin;
2366
last_stop = repeat_end;
2369
/* PDF requires the first and last stop to be the same as the line
2370
* coordinates. For repeating patterns this moves the line
2371
* coordinates out to the begin/end of the repeating function. For
2372
* non repeating patterns this may move the line coordinates in if
2373
* there are not stops at offset 0 and 1. */
2374
x1 = _cairo_fixed_to_double (pattern->p1.x);
2375
y1 = _cairo_fixed_to_double (pattern->p1.y);
2376
x2 = _cairo_fixed_to_double (pattern->p2.x);
2377
y2 = _cairo_fixed_to_double (pattern->p2.y);
2379
_x1 = x1 + (x2 - x1)*first_stop;
2380
_y1 = y1 + (y2 - y1)*first_stop;
2381
_x2 = x1 + (x2 - x1)*last_stop;
2382
_y2 = y1 + (y2 - y1)*last_stop;
2389
/* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
2390
* Type 2 function is used by itself without a stitching
2391
* function. Type 2 functions always have the domain [0 1] */
2392
if ((pattern->base.base.extend == CAIRO_EXTEND_NONE ||
2393
pattern->base.base.extend == CAIRO_EXTEND_PAD) &&
2394
gradient->n_stops == 2) {
2399
status = _cairo_pdf_surface_emit_pattern_stops (surface,
2406
if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
2407
pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
2408
status = _cairo_pdf_surface_emit_repeating_function (surface,
2416
if (alpha_function.id != 0) {
2417
status = _cairo_pdf_surface_emit_repeating_function (surface,
2427
pattern_resource = _cairo_pdf_surface_new_object (surface);
2428
if (pattern_resource.id == 0)
2429
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2431
_cairo_output_stream_printf (surface->output,
2433
"<< /Type /Pattern\r\n"
2434
" /PatternType 2\r\n"
2435
" /Matrix [ %f %f %f %f %f %f ]\r\n"
2437
" << /ShadingType 2\r\n"
2438
" /ColorSpace /DeviceRGB\r\n"
2439
" /Coords [ %f %f %f %f ]\r\n"
2440
" /Domain [ %f %f ]\r\n"
2441
" /Function %d 0 R\r\n",
2442
pattern_resource.id,
2443
pat_to_pdf.xx, pat_to_pdf.yx,
2444
pat_to_pdf.xy, pat_to_pdf.yy,
2445
pat_to_pdf.x0, pat_to_pdf.y0,
2447
first_stop, last_stop,
2450
if (extend == CAIRO_EXTEND_PAD) {
2451
_cairo_output_stream_printf (surface->output,
2452
" /Extend [ true true ]\r\n");
2454
_cairo_output_stream_printf (surface->output,
2455
" /Extend [ false false ]\r\n");
2458
_cairo_output_stream_printf (surface->output,
2463
if (alpha_function.id == 0) {
2464
surface->emitted_pattern.smask.id = 0;
2466
cairo_pdf_resource_t mask_resource;
2468
/* Create pattern for SMask. */
2469
mask_resource = _cairo_pdf_surface_new_object (surface);
2470
if (mask_resource.id == 0)
2471
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2473
_cairo_output_stream_printf (surface->output,
2475
"<< /Type /Pattern\r\n"
2476
" /PatternType 2\r\n"
2477
" /Matrix [ %f %f %f %f %f %f ]\r\n"
2479
" << /ShadingType 2\r\n"
2480
" /ColorSpace /DeviceGray\r\n"
2481
" /Coords [ %f %f %f %f ]\r\n"
2482
" /Domain [ %f %f ]\r\n"
2483
" /Function %d 0 R\r\n",
2485
pat_to_pdf.xx, pat_to_pdf.yx,
2486
pat_to_pdf.xy, pat_to_pdf.yy,
2487
pat_to_pdf.x0, pat_to_pdf.y0,
2489
first_stop, last_stop,
2492
if (extend == CAIRO_EXTEND_PAD) {
2493
_cairo_output_stream_printf (surface->output,
2494
" /Extend [ true true ]\r\n");
2496
_cairo_output_stream_printf (surface->output,
2497
" /Extend [ false false ]\r\n");
2500
_cairo_output_stream_printf (surface->output,
2504
status = _cairo_pdf_surface_add_pattern (surface, mask_resource);
2508
smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource);
2510
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2512
surface->emitted_pattern.smask = smask;
2515
surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_LINEAR;
2516
surface->emitted_pattern.pattern = pattern_resource;
2517
surface->emitted_pattern.alpha = 1.0;
2519
_cairo_pdf_surface_resume_content_stream (surface);
2524
static cairo_status_t
2525
_cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface,
2526
cairo_radial_pattern_t *pattern)
2528
cairo_pdf_resource_t pattern_resource, smask;
2529
cairo_pdf_resource_t color_function, alpha_function;
2530
double x1, y1, x2, y2, r1, r2;
2531
cairo_matrix_t pat_to_pdf;
2532
cairo_extend_t extend;
2533
cairo_status_t status;
2535
extend = cairo_pattern_get_extend (&pattern->base.base);
2536
_cairo_pdf_surface_pause_content_stream (surface);
2538
status = _cairo_pdf_surface_emit_pattern_stops (surface,
2545
pat_to_pdf = pattern->base.base.matrix;
2546
status = cairo_matrix_invert (&pat_to_pdf);
2547
/* cairo_pattern_set_matrix ensures the matrix is invertible */
2548
assert (status == CAIRO_STATUS_SUCCESS);
2550
cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
2551
x1 = _cairo_fixed_to_double (pattern->c1.x);
2552
y1 = _cairo_fixed_to_double (pattern->c1.y);
2553
r1 = _cairo_fixed_to_double (pattern->r1);
2554
x2 = _cairo_fixed_to_double (pattern->c2.x);
2555
y2 = _cairo_fixed_to_double (pattern->c2.y);
2556
r2 = _cairo_fixed_to_double (pattern->r2);
2558
pattern_resource = _cairo_pdf_surface_new_object (surface);
2559
if (pattern_resource.id == 0)
2560
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2562
_cairo_output_stream_printf (surface->output,
2564
"<< /Type /Pattern\r\n"
2565
" /PatternType 2\r\n"
2566
" /Matrix [ %f %f %f %f %f %f ]\r\n"
2568
" << /ShadingType 3\r\n"
2569
" /ColorSpace /DeviceRGB\r\n"
2570
" /Coords [ %f %f %f %f %f %f ]\r\n"
2571
" /Function %d 0 R\r\n",
2572
pattern_resource.id,
2573
pat_to_pdf.xx, pat_to_pdf.yx,
2574
pat_to_pdf.xy, pat_to_pdf.yy,
2575
pat_to_pdf.x0, pat_to_pdf.y0,
2576
x1, y1, r1, x2, y2, r2,
2579
if (extend == CAIRO_EXTEND_PAD) {
2580
_cairo_output_stream_printf (surface->output,
2581
" /Extend [ true true ]\r\n");
2583
_cairo_output_stream_printf (surface->output,
2584
" /Extend [ false false ]\r\n");
2587
_cairo_output_stream_printf (surface->output,
2592
if (alpha_function.id == 0) {
2593
surface->emitted_pattern.smask.id = 0;
2595
cairo_pdf_resource_t mask_resource;
2597
/* Create pattern for SMask. */
2598
mask_resource = _cairo_pdf_surface_new_object (surface);
2599
if (mask_resource.id == 0)
2600
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2602
_cairo_output_stream_printf (surface->output,
2604
"<< /Type /Pattern\r\n"
2605
" /PatternType 2\r\n"
2606
" /Matrix [ %f %f %f %f %f %f ]\r\n"
2608
" << /ShadingType 3\r\n"
2609
" /ColorSpace /DeviceGray\r\n"
2610
" /Coords [ %f %f %f %f %f %f ]\r\n"
2611
" /Function %d 0 R\r\n",
2613
pat_to_pdf.xx, pat_to_pdf.yx,
2614
pat_to_pdf.xy, pat_to_pdf.yy,
2615
pat_to_pdf.x0, pat_to_pdf.y0,
2616
x1, y1, r1, x2, y2, r2,
2619
if (extend == CAIRO_EXTEND_PAD) {
2620
_cairo_output_stream_printf (surface->output,
2621
" /Extend [ true true ]\r\n");
2623
_cairo_output_stream_printf (surface->output,
2624
" /Extend [ false false ]\r\n");
2627
_cairo_output_stream_printf (surface->output,
2632
smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource);
2634
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2636
surface->emitted_pattern.smask = smask;
2639
surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_RADIAL;
2640
surface->emitted_pattern.pattern = pattern_resource;
2641
surface->emitted_pattern.alpha = 1.0;
2643
_cairo_pdf_surface_resume_content_stream (surface);
2648
static cairo_status_t
2649
_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
2651
switch (pattern->type) {
2652
case CAIRO_PATTERN_TYPE_SOLID:
2653
_cairo_pdf_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
2654
return CAIRO_STATUS_SUCCESS;
2656
case CAIRO_PATTERN_TYPE_SURFACE:
2657
return _cairo_pdf_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
2659
case CAIRO_PATTERN_TYPE_LINEAR:
2660
return _cairo_pdf_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
2662
case CAIRO_PATTERN_TYPE_RADIAL:
2663
return _cairo_pdf_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
2667
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
2670
static cairo_status_t
2671
_cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
2672
cairo_bool_t is_stroke)
2674
cairo_status_t status;
2677
status = _cairo_pdf_surface_add_alpha (surface, surface->emitted_pattern.alpha, &alpha);
2681
if (surface->emitted_pattern.type == CAIRO_PATTERN_TYPE_SOLID) {
2682
_cairo_output_stream_printf (surface->output,
2684
surface->emitted_pattern.red,
2685
surface->emitted_pattern.green,
2686
surface->emitted_pattern.blue);
2689
_cairo_output_stream_printf (surface->output, "RG ");
2691
_cairo_output_stream_printf (surface->output, "rg ");
2693
_cairo_output_stream_printf (surface->output,
2698
_cairo_output_stream_printf (surface->output,
2699
"/Pattern CS /p%d SCN ",
2700
surface->emitted_pattern.pattern.id);
2702
_cairo_output_stream_printf (surface->output,
2703
"/Pattern cs /p%d scn ",
2704
surface->emitted_pattern.pattern.id);
2706
status = _cairo_pdf_surface_add_pattern (surface, surface->emitted_pattern.pattern);
2710
_cairo_output_stream_printf (surface->output,
2714
_cairo_output_stream_printf (surface->output, "\r\n");
2717
return _cairo_output_stream_get_status (surface->output);
2720
static cairo_int_status_t
2721
_cairo_pdf_surface_copy_page (void *abstract_surface)
2723
cairo_pdf_surface_t *surface = abstract_surface;
2724
cairo_int_status_t status;
2726
status = _cairo_pdf_surface_stop_content_stream (surface);
2730
return _cairo_pdf_surface_write_page (surface);
2733
static cairo_int_status_t
2734
_cairo_pdf_surface_show_page (void *abstract_surface)
2736
cairo_pdf_surface_t *surface = abstract_surface;
2737
cairo_int_status_t status;
2739
status = _cairo_pdf_surface_stop_content_stream (surface);
2743
status = _cairo_pdf_surface_write_page (surface);
2747
_cairo_pdf_surface_clear (surface);
2749
return CAIRO_STATUS_SUCCESS;
2752
static cairo_int_status_t
2753
_cairo_pdf_surface_get_extents (void *abstract_surface,
2754
cairo_rectangle_int_t *rectangle)
2756
cairo_pdf_surface_t *surface = abstract_surface;
2761
/* XXX: The conversion to integers here is pretty bogus, (not to
2762
* mention the aribitray limitation of width to a short(!). We
2763
* may need to come up with a better interface for get_size.
2765
rectangle->width = (int) ceil (surface->width);
2766
rectangle->height = (int) ceil (surface->height);
2768
return CAIRO_STATUS_SUCCESS;
2771
typedef struct _pdf_path_info {
2772
cairo_output_stream_t *output;
2773
cairo_matrix_t *cairo_to_pdf;
2774
cairo_matrix_t *ctm_inverse;
2777
static cairo_status_t
2778
_cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
2780
pdf_path_info_t *info = closure;
2781
double x = _cairo_fixed_to_double (point->x);
2782
double y = _cairo_fixed_to_double (point->y);
2784
if (info->cairo_to_pdf)
2785
cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
2786
if (info->ctm_inverse)
2787
cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
2789
_cairo_output_stream_printf (info->output,
2792
return CAIRO_STATUS_SUCCESS;
2795
static cairo_status_t
2796
_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
2798
pdf_path_info_t *info = closure;
2799
double x = _cairo_fixed_to_double (point->x);
2800
double y = _cairo_fixed_to_double (point->y);
2802
if (info->cairo_to_pdf)
2803
cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
2804
if (info->ctm_inverse)
2805
cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
2807
_cairo_output_stream_printf (info->output,
2809
return CAIRO_STATUS_SUCCESS;
2812
static cairo_status_t
2813
_cairo_pdf_path_curve_to (void *closure,
2818
pdf_path_info_t *info = closure;
2819
double bx = _cairo_fixed_to_double (b->x);
2820
double by = _cairo_fixed_to_double (b->y);
2821
double cx = _cairo_fixed_to_double (c->x);
2822
double cy = _cairo_fixed_to_double (c->y);
2823
double dx = _cairo_fixed_to_double (d->x);
2824
double dy = _cairo_fixed_to_double (d->y);
2826
if (info->cairo_to_pdf) {
2827
cairo_matrix_transform_point (info->cairo_to_pdf, &bx, &by);
2828
cairo_matrix_transform_point (info->cairo_to_pdf, &cx, &cy);
2829
cairo_matrix_transform_point (info->cairo_to_pdf, &dx, &dy);
2831
if (info->ctm_inverse) {
2832
cairo_matrix_transform_point (info->ctm_inverse, &bx, &by);
2833
cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy);
2834
cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy);
2837
_cairo_output_stream_printf (info->output,
2838
"%f %f %f %f %f %f c ",
2839
bx, by, cx, cy, dx, dy);
2840
return CAIRO_STATUS_SUCCESS;
2843
static cairo_status_t
2844
_cairo_pdf_path_close_path (void *closure)
2846
pdf_path_info_t *info = closure;
2848
_cairo_output_stream_printf (info->output,
2851
return CAIRO_STATUS_SUCCESS;
2854
static cairo_status_t
2855
_cairo_pdf_surface_add_clip (cairo_pdf_surface_t *surface,
2856
cairo_path_fixed_t *path,
2857
cairo_fill_rule_t fill_rule)
2859
cairo_pdf_group_element_t elem;
2860
cairo_status_t status;
2862
memset (&elem, 0, sizeof elem);
2863
elem.type = ELEM_CLIP;
2866
elem.clip_path = NULL;
2868
elem.clip_path = _cairo_path_fixed_create ();
2869
if (elem.clip_path == NULL)
2870
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2872
status = _cairo_path_fixed_init_copy (elem.clip_path, path);
2874
_cairo_path_fixed_destroy (elem.clip_path);
2878
elem.fill_rule = fill_rule;
2880
status = _cairo_pdf_surface_stop_content_stream (surface);
2882
if (elem.clip_path != NULL)
2883
_cairo_path_fixed_destroy (elem.clip_path);
2887
status = _cairo_array_append (surface->current_group, &elem);
2889
if (elem.clip_path != NULL)
2890
_cairo_path_fixed_destroy (elem.clip_path);
2894
status = _cairo_pdf_surface_start_content_stream (surface);
2898
return CAIRO_STATUS_SUCCESS;
2901
static cairo_int_status_t
2902
_cairo_pdf_surface_intersect_clip_path (void *abstract_surface,
2903
cairo_path_fixed_t *path,
2904
cairo_fill_rule_t fill_rule,
2906
cairo_antialias_t antialias)
2908
cairo_pdf_surface_t *surface = abstract_surface;
2910
return _cairo_pdf_surface_add_clip (surface, path, fill_rule);
2914
_cairo_pdf_surface_get_font_options (void *abstract_surface,
2915
cairo_font_options_t *options)
2917
_cairo_font_options_init_default (options);
2919
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
2920
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
2921
cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
2924
static cairo_pdf_resource_t
2925
_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface)
2927
cairo_pdf_resource_t info;
2929
info = _cairo_pdf_surface_new_object (surface);
2933
_cairo_output_stream_printf (surface->output,
2935
"<< /Creator (cairo %s (http://cairographics.org))\r\n"
2936
" /Producer (cairo %s (http://cairographics.org))\r\n"
2940
cairo_version_string (),
2941
cairo_version_string ());
2947
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
2949
cairo_pdf_resource_t page;
2952
_cairo_pdf_surface_update_object (surface, surface->pages_resource);
2953
_cairo_output_stream_printf (surface->output,
2955
"<< /Type /Pages\r\n"
2957
surface->pages_resource.id);
2959
num_pages = _cairo_array_num_elements (&surface->pages);
2960
for (i = 0; i < num_pages; i++) {
2961
_cairo_array_copy_element (&surface->pages, i, &page);
2962
_cairo_output_stream_printf (surface->output, "%d 0 R ", page.id);
2965
_cairo_output_stream_printf (surface->output, "]\r\n");
2966
_cairo_output_stream_printf (surface->output, " /Count %d\r\n", num_pages);
2969
/* TODO: Figure out wich other defaults to be inherited by /Page
2971
_cairo_output_stream_printf (surface->output,
2976
static cairo_int_status_t
2977
_cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
2978
cairo_scaled_font_subset_t *font_subset,
2979
cairo_bool_t is_composite,
2980
cairo_pdf_resource_t *stream)
2982
const cairo_scaled_font_backend_t *backend;
2983
unsigned int i, num_bfchar;
2986
if (font_subset->to_unicode == NULL)
2987
return CAIRO_INT_STATUS_UNSUPPORTED;
2989
if (_cairo_truetype_create_glyph_to_unicode_map (font_subset) != CAIRO_STATUS_SUCCESS) {
2990
backend = font_subset->scaled_font->backend;
2991
if (backend->map_glyphs_to_unicode == NULL)
2992
return CAIRO_INT_STATUS_UNSUPPORTED;
2994
backend->map_glyphs_to_unicode (font_subset->scaled_font, font_subset);
2997
*stream = _cairo_pdf_surface_open_stream (surface,
2998
surface->compress_content,
3000
if (stream->id == 0)
3001
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3003
_cairo_output_stream_printf (surface->output,
3004
"/CIDInit /ProcSet findresource begin\r\n"
3007
"/CIDSystemInfo\r\n"
3008
"<< /Registry (Adobe)\r\n"
3009
" /Ordering (UCS)\r\n"
3010
" /Supplement 0\r\n"
3012
"/CMapName /Adobe-Identity-UCS def\r\n"
3013
"/CMapType 2 def\r\n"
3014
"1 begincodespacerange\r\n");
3017
_cairo_output_stream_printf (surface->output,
3018
"<0000> <ffff>\r\n");
3020
_cairo_output_stream_printf (surface->output,
3024
_cairo_output_stream_printf (surface->output,
3025
"endcodespacerange\r\n");
3027
num_bfchar = font_subset->num_glyphs - 1;
3028
/* The CMap specification has a limit of 100 characters per beginbfchar operator */
3029
_cairo_output_stream_printf (surface->output,
3030
"%d beginbfchar\r\n",
3031
num_bfchar > 100 ? 100 : num_bfchar);
3032
for (i = 0; i < num_bfchar; i++) {
3033
if (i != 0 && i % 100 == 0) {
3034
_cairo_output_stream_printf (surface->output,
3036
"%d beginbfchar\r\n",
3037
num_bfchar - i > 100 ? 100 : num_bfchar - i);
3040
_cairo_output_stream_printf (surface->output,
3041
"<%04x> <%04x>\r\n",
3042
i + 1, font_subset->to_unicode[i + 1]);
3044
_cairo_output_stream_printf (surface->output,
3045
"<%02x> <%04x>\r\n",
3046
i + 1, font_subset->to_unicode[i + 1]);
3049
_cairo_output_stream_printf (surface->output,
3052
_cairo_output_stream_printf (surface->output,
3054
"CMapName currentdict /CMap defineresource pop\r\n"
3058
return _cairo_pdf_surface_close_stream (surface);
3061
static cairo_status_t
3062
_cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
3063
cairo_scaled_font_subset_t *font_subset,
3064
cairo_cff_subset_t *subset)
3066
cairo_pdf_resource_t stream, descriptor, cidfont_dict;
3067
cairo_pdf_resource_t subset_resource, to_unicode_stream;
3068
cairo_pdf_font_t font;
3069
unsigned long compressed_length;
3072
cairo_status_t status;
3074
compressed = compress_dup (subset->data, subset->data_length, &compressed_length);
3075
if (compressed == NULL)
3076
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3078
stream = _cairo_pdf_surface_new_object (surface);
3079
if (stream.id == 0) {
3081
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3084
_cairo_output_stream_printf (surface->output,
3086
"<< /Filter /FlateDecode\r\n"
3088
" /Subtype /CIDFontType0C\r\n"
3093
_cairo_output_stream_write (surface->output, compressed, compressed_length);
3094
_cairo_output_stream_printf (surface->output,
3100
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
3102
&to_unicode_stream);
3103
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
3106
descriptor = _cairo_pdf_surface_new_object (surface);
3107
if (descriptor.id == 0)
3108
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3110
_cairo_output_stream_printf (surface->output,
3112
"<< /Type /FontDescriptor\r\n"
3113
" /FontName /%s\r\n"
3115
" /FontBBox [ %ld %ld %ld %ld ]\r\n"
3116
" /ItalicAngle 0\r\n"
3119
" /CapHeight 500\r\n"
3122
" /FontFile3 %u 0 R\r\n"
3135
cidfont_dict = _cairo_pdf_surface_new_object (surface);
3136
if (cidfont_dict.id == 0)
3137
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3139
_cairo_output_stream_printf (surface->output,
3141
"<< /Type /Font\r\n"
3142
" /Subtype /CIDFontType0\r\n"
3143
" /BaseFont /%s\r\n"
3144
" /CIDSystemInfo\r\n"
3145
" << /Registry (Adobe)\r\n"
3146
" /Ordering (Identity)\r\n"
3147
" /Supplement 0\r\n"
3149
" /FontDescriptor %d 0 R\r\n"
3155
for (i = 0; i < font_subset->num_glyphs; i++)
3156
_cairo_output_stream_printf (surface->output,
3160
_cairo_output_stream_printf (surface->output,
3165
subset_resource = _cairo_pdf_surface_get_font_resource (surface,
3166
font_subset->font_id,
3167
font_subset->subset_id);
3168
_cairo_pdf_surface_update_object (surface, subset_resource);
3169
_cairo_output_stream_printf (surface->output,
3171
"<< /Type /Font\r\n"
3172
" /Subtype /Type0\r\n"
3173
" /BaseFont /%s\r\n"
3174
" /Encoding /Identity-H\r\n"
3175
" /DescendantFonts [ %d 0 R]\r\n",
3180
if (to_unicode_stream.id != 0)
3181
_cairo_output_stream_printf (surface->output,
3182
" /ToUnicode %d 0 R\r\n",
3183
to_unicode_stream.id);
3185
_cairo_output_stream_printf (surface->output,
3189
font.font_id = font_subset->font_id;
3190
font.subset_id = font_subset->subset_id;
3191
font.subset_resource = subset_resource;
3192
status = _cairo_array_append (&surface->fonts, &font);
3197
static cairo_status_t
3198
_cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
3199
cairo_scaled_font_subset_t *font_subset)
3201
cairo_status_t status;
3202
cairo_cff_subset_t subset;
3205
snprintf (name, sizeof name, "CairoFont-%d-%d",
3206
font_subset->font_id, font_subset->subset_id);
3207
status = _cairo_cff_subset_init (&subset, name, font_subset);
3211
status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
3213
_cairo_cff_subset_fini (&subset);
3218
static cairo_status_t
3219
_cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t *surface,
3220
cairo_scaled_font_subset_t *font_subset)
3222
cairo_status_t status;
3223
cairo_cff_subset_t subset;
3226
snprintf (name, sizeof name, "CairoFont-%d-%d",
3227
font_subset->font_id, font_subset->subset_id);
3228
status = _cairo_cff_fallback_init (&subset, name, font_subset);
3232
status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
3234
_cairo_cff_fallback_fini (&subset);
3239
static cairo_status_t
3240
_cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
3241
cairo_scaled_font_subset_t *font_subset,
3242
cairo_type1_subset_t *subset)
3244
cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
3245
cairo_pdf_font_t font;
3246
cairo_status_t status;
3247
unsigned long length, compressed_length;
3252
/* We ignore the zero-trailer and set Length3 to 0. */
3253
length = subset->header_length + subset->data_length;
3254
compressed = compress_dup (subset->data, length, &compressed_length);
3255
if (compressed == NULL)
3256
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3258
stream = _cairo_pdf_surface_new_object (surface);
3259
if (stream.id == 0) {
3261
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3264
_cairo_output_stream_printf (surface->output,
3266
"<< /Filter /FlateDecode\r\n"
3275
subset->header_length,
3276
subset->data_length);
3277
_cairo_output_stream_write (surface->output, compressed, compressed_length);
3278
_cairo_output_stream_printf (surface->output,
3284
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
3286
&to_unicode_stream);
3287
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
3290
descriptor = _cairo_pdf_surface_new_object (surface);
3291
if (descriptor.id == 0)
3292
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3294
_cairo_output_stream_printf (surface->output,
3296
"<< /Type /FontDescriptor\r\n"
3297
" /FontName /%s\r\n"
3299
" /FontBBox [ %ld %ld %ld %ld ]\r\n"
3300
" /ItalicAngle 0\r\n"
3303
" /CapHeight 500\r\n"
3306
" /FontFile %u 0 R\r\n"
3319
subset_resource = _cairo_pdf_surface_get_font_resource (surface,
3320
font_subset->font_id,
3321
font_subset->subset_id);
3322
_cairo_pdf_surface_update_object (surface, subset_resource);
3323
_cairo_output_stream_printf (surface->output,
3325
"<< /Type /Font\r\n"
3326
" /Subtype /Type1\r\n"
3327
" /BaseFont /%s\r\n"
3330
" /FontDescriptor %d 0 R\r\n"
3334
font_subset->num_glyphs - 1,
3337
for (i = 0; i < font_subset->num_glyphs; i++)
3338
_cairo_output_stream_printf (surface->output,
3342
_cairo_output_stream_printf (surface->output,
3345
if (to_unicode_stream.id != 0)
3346
_cairo_output_stream_printf (surface->output,
3347
" /ToUnicode %d 0 R\r\n",
3348
to_unicode_stream.id);
3350
_cairo_output_stream_printf (surface->output,
3354
font.font_id = font_subset->font_id;
3355
font.subset_id = font_subset->subset_id;
3356
font.subset_resource = subset_resource;
3357
return _cairo_array_append (&surface->fonts, &font);
3360
#if CAIRO_HAS_FT_FONT
3361
static cairo_status_t
3362
_cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
3363
cairo_scaled_font_subset_t *font_subset)
3365
cairo_status_t status;
3366
cairo_type1_subset_t subset;
3369
snprintf (name, sizeof name, "CairoFont-%d-%d",
3370
font_subset->font_id, font_subset->subset_id);
3371
status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE);
3375
status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
3377
_cairo_type1_subset_fini (&subset);
3382
static cairo_status_t
3383
_cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
3384
cairo_scaled_font_subset_t *font_subset)
3386
cairo_status_t status;
3387
cairo_type1_subset_t subset;
3390
snprintf (name, sizeof name, "CairoFont-%d-%d",
3391
font_subset->font_id, font_subset->subset_id);
3392
status = _cairo_type1_fallback_init_binary (&subset, name, font_subset);
3396
status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
3398
_cairo_type1_fallback_fini (&subset);
3402
#define PDF_UNITS_PER_EM 1000
3404
static cairo_status_t
3405
_cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
3406
cairo_scaled_font_subset_t *font_subset)
3408
cairo_pdf_resource_t stream, descriptor, cidfont_dict;
3409
cairo_pdf_resource_t subset_resource, to_unicode_stream;
3410
cairo_status_t status;
3411
cairo_pdf_font_t font;
3412
cairo_truetype_subset_t subset;
3413
unsigned long compressed_length;
3417
status = _cairo_truetype_subset_init (&subset, font_subset);
3421
compressed = compress_dup (subset.data, subset.data_length,
3422
&compressed_length);
3423
if (compressed == NULL) {
3424
_cairo_truetype_subset_fini (&subset);
3425
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3428
stream = _cairo_pdf_surface_new_object (surface);
3429
if (stream.id == 0) {
3431
_cairo_truetype_subset_fini (&subset);
3432
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3434
_cairo_output_stream_printf (surface->output,
3436
"<< /Filter /FlateDecode\r\n"
3443
subset.data_length);
3444
_cairo_output_stream_write (surface->output, compressed, compressed_length);
3445
_cairo_output_stream_printf (surface->output,
3451
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
3453
&to_unicode_stream);
3454
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) {
3455
_cairo_truetype_subset_fini (&subset);
3459
descriptor = _cairo_pdf_surface_new_object (surface);
3460
if (descriptor.id == 0) {
3461
_cairo_truetype_subset_fini (&subset);
3462
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3465
_cairo_output_stream_printf (surface->output,
3467
"<< /Type /FontDescriptor\r\n"
3468
" /FontName /%s\r\n"
3470
" /FontBBox [ %ld %ld %ld %ld ]\r\n"
3471
" /ItalicAngle 0\r\n"
3474
" /CapHeight %ld\r\n"
3477
" /FontFile2 %u 0 R\r\n"
3482
(long)(subset.x_min*PDF_UNITS_PER_EM),
3483
(long)(subset.y_min*PDF_UNITS_PER_EM),
3484
(long)(subset.x_max*PDF_UNITS_PER_EM),
3485
(long)(subset.y_max*PDF_UNITS_PER_EM),
3486
(long)(subset.ascent*PDF_UNITS_PER_EM),
3487
(long)(subset.descent*PDF_UNITS_PER_EM),
3488
(long)(subset.y_max*PDF_UNITS_PER_EM),
3491
cidfont_dict = _cairo_pdf_surface_new_object (surface);
3492
if (cidfont_dict.id == 0) {
3493
_cairo_truetype_subset_fini (&subset);
3494
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3497
_cairo_output_stream_printf (surface->output,
3499
"<< /Type /Font\r\n"
3500
" /Subtype /CIDFontType2\r\n"
3501
" /BaseFont /%s\r\n"
3502
" /CIDSystemInfo\r\n"
3503
" << /Registry (Adobe)\r\n"
3504
" /Ordering (Identity)\r\n"
3505
" /Supplement 0\r\n"
3507
" /FontDescriptor %d 0 R\r\n"
3513
for (i = 0; i < font_subset->num_glyphs; i++)
3514
_cairo_output_stream_printf (surface->output,
3516
(long)(subset.widths[i]*PDF_UNITS_PER_EM));
3518
_cairo_output_stream_printf (surface->output,
3523
subset_resource = _cairo_pdf_surface_get_font_resource (surface,
3524
font_subset->font_id,
3525
font_subset->subset_id);
3526
_cairo_pdf_surface_update_object (surface, subset_resource);
3527
_cairo_output_stream_printf (surface->output,
3529
"<< /Type /Font\r\n"
3530
" /Subtype /Type0\r\n"
3531
" /BaseFont /%s\r\n"
3532
" /Encoding /Identity-H\r\n"
3533
" /DescendantFonts [ %d 0 R]\r\n",
3538
if (to_unicode_stream.id != 0)
3539
_cairo_output_stream_printf (surface->output,
3540
" /ToUnicode %d 0 R\r\n",
3541
to_unicode_stream.id);
3543
_cairo_output_stream_printf (surface->output,
3547
font.font_id = font_subset->font_id;
3548
font.subset_id = font_subset->subset_id;
3549
font.subset_resource = subset_resource;
3550
status = _cairo_array_append (&surface->fonts, &font);
3552
_cairo_truetype_subset_fini (&subset);
3557
static cairo_int_status_t
3558
_cairo_pdf_surface_emit_outline_glyph (cairo_pdf_surface_t *surface,
3559
cairo_scaled_font_t *scaled_font,
3560
unsigned long glyph_index,
3561
cairo_pdf_resource_t *glyph_ret)
3563
cairo_scaled_glyph_t *scaled_glyph;
3564
pdf_path_info_t info;
3565
cairo_status_t status = CAIRO_STATUS_SUCCESS;
3567
status = _cairo_scaled_glyph_lookup (scaled_font,
3569
CAIRO_SCALED_GLYPH_INFO_METRICS|
3570
CAIRO_SCALED_GLYPH_INFO_PATH,
3575
*glyph_ret = _cairo_pdf_surface_open_stream (surface,
3576
surface->compress_content,
3578
if (glyph_ret->id == 0)
3579
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3581
_cairo_output_stream_printf (surface->output,
3582
"0 0 %f %f %f %f d1\r\n",
3583
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
3584
-_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
3585
_cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
3586
-_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
3588
info.output = surface->output;
3589
info.cairo_to_pdf = &surface->cairo_to_pdf;
3590
info.ctm_inverse = NULL;
3592
status = _cairo_path_fixed_interpret (scaled_glyph->path,
3593
CAIRO_DIRECTION_FORWARD,
3594
_cairo_pdf_path_move_to,
3595
_cairo_pdf_path_line_to,
3596
_cairo_pdf_path_curve_to,
3597
_cairo_pdf_path_close_path,
3600
/* ignore status return as we are on the error path... */
3601
_cairo_pdf_surface_close_stream (surface);
3605
_cairo_output_stream_printf (surface->output,
3608
return _cairo_pdf_surface_close_stream (surface);
3611
static cairo_int_status_t
3612
_cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
3613
cairo_scaled_font_t *scaled_font,
3614
unsigned long glyph_index,
3615
cairo_pdf_resource_t *glyph_ret,
3619
cairo_scaled_glyph_t *scaled_glyph;
3620
cairo_status_t status;
3621
cairo_image_surface_t *image;
3622
unsigned char *row, *byte;
3624
double x_advance, y_advance;
3626
status = _cairo_scaled_glyph_lookup (scaled_font,
3628
CAIRO_SCALED_GLYPH_INFO_METRICS|
3629
CAIRO_SCALED_GLYPH_INFO_SURFACE,
3634
x_advance = scaled_glyph->metrics.x_advance;
3635
y_advance = scaled_glyph->metrics.y_advance;
3636
cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
3637
*bbox = scaled_glyph->bbox;
3640
image = scaled_glyph->surface;
3641
if (image->format != CAIRO_FORMAT_A1) {
3642
image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
3643
if (cairo_surface_status (&image->base))
3644
return cairo_surface_status (&image->base);
3647
*glyph_ret = _cairo_pdf_surface_open_stream (surface,
3648
surface->compress_content,
3650
if (glyph_ret->id == 0) {
3651
if (image != scaled_glyph->surface)
3652
cairo_surface_destroy (&image->base);
3653
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3656
_cairo_output_stream_printf (surface->output,
3657
"%f 0 %f %f %f %f d1\r\n",
3659
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
3660
_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
3661
_cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
3662
_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
3664
_cairo_output_stream_printf (surface->output,
3665
"%f 0 0 %f %f %f cm\r\n",
3666
_cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
3667
_cairo_fixed_to_double (scaled_glyph->bbox.p1.y) - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
3668
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
3669
_cairo_fixed_to_double (scaled_glyph->bbox.p2.y));
3671
_cairo_output_stream_printf (surface->output,
3681
_cairo_output_stream_printf (surface->output,
3683
for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
3684
for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
3685
unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
3686
_cairo_output_stream_write (surface->output, &output_byte, 1);
3689
_cairo_output_stream_printf (surface->output,
3692
status = _cairo_pdf_surface_close_stream (surface);
3694
if (image != scaled_glyph->surface)
3695
cairo_surface_destroy (&image->base);
3701
_cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t *surface,
3702
cairo_scaled_font_t *scaled_font,
3703
unsigned long glyph_index,
3704
cairo_pdf_resource_t *glyph_ret,
3708
cairo_status_t status;
3710
status = _cairo_pdf_surface_emit_outline_glyph (surface,
3714
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
3715
status = _cairo_pdf_surface_emit_bitmap_glyph (surface,
3723
status = _cairo_surface_set_error (&surface->base, status);
3726
static cairo_status_t
3727
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
3728
cairo_scaled_font_subset_t *font_subset)
3730
cairo_status_t status;
3731
cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
3732
cairo_pdf_font_t font;
3733
cairo_matrix_t matrix;
3736
cairo_box_t font_bbox = {{0,0},{0,0}};
3737
cairo_box_t bbox = {{0,0},{0,0}};
3739
glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
3741
return _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
3743
widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
3744
if (widths == NULL) {
3746
return _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
3749
for (i = 0; i < font_subset->num_glyphs; i++) {
3750
_cairo_pdf_surface_emit_glyph (surface,
3751
font_subset->scaled_font,
3752
font_subset->glyphs[i],
3757
font_bbox.p1.x = bbox.p1.x;
3758
font_bbox.p1.y = bbox.p1.y;
3759
font_bbox.p2.x = bbox.p2.x;
3760
font_bbox.p2.y = bbox.p2.y;
3762
if (bbox.p1.x < font_bbox.p1.x)
3763
font_bbox.p1.x = bbox.p1.x;
3764
if (bbox.p1.y < font_bbox.p1.y)
3765
font_bbox.p1.y = bbox.p1.y;
3766
if (bbox.p2.x > font_bbox.p2.x)
3767
font_bbox.p2.x = bbox.p2.x;
3768
if (bbox.p2.y > font_bbox.p2.y)
3769
font_bbox.p2.y = bbox.p2.y;
3773
encoding = _cairo_pdf_surface_new_object (surface);
3774
if (encoding.id == 0) {
3777
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3780
_cairo_output_stream_printf (surface->output,
3782
"<< /Type /Encoding\r\n"
3783
" /Differences [0", encoding.id);
3784
for (i = 0; i < font_subset->num_glyphs; i++)
3785
_cairo_output_stream_printf (surface->output,
3787
_cairo_output_stream_printf (surface->output,
3792
char_procs = _cairo_pdf_surface_new_object (surface);
3793
if (char_procs.id == 0) {
3796
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3799
_cairo_output_stream_printf (surface->output,
3801
"<<\r\n", char_procs.id);
3802
for (i = 0; i < font_subset->num_glyphs; i++)
3803
_cairo_output_stream_printf (surface->output,
3806
_cairo_output_stream_printf (surface->output,
3812
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
3814
&to_unicode_stream);
3815
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) {
3820
subset_resource = _cairo_pdf_surface_get_font_resource (surface,
3821
font_subset->font_id,
3822
font_subset->subset_id);
3823
_cairo_pdf_surface_update_object (surface, subset_resource);
3824
matrix = font_subset->scaled_font->scale;
3825
status = cairo_matrix_invert (&matrix);
3826
/* _cairo_scaled_font_init ensures the matrix is invertible */
3827
assert (status == CAIRO_STATUS_SUCCESS);
3828
_cairo_output_stream_printf (surface->output,
3830
"<< /Type /Font\r\n"
3831
" /Subtype /Type3\r\n"
3832
" /FontBBox [%f %f %f %f]\r\n"
3833
" /FontMatrix [ %f %f %f %f 0 0 ]\r\n"
3834
" /Encoding %d 0 R\r\n"
3835
" /CharProcs %d 0 R\r\n"
3837
" /LastChar %d\r\n",
3839
_cairo_fixed_to_double (font_bbox.p1.x),
3840
_cairo_fixed_to_double (font_bbox.p1.y),
3841
_cairo_fixed_to_double (font_bbox.p2.x),
3842
_cairo_fixed_to_double (font_bbox.p2.y),
3849
font_subset->num_glyphs - 1);
3851
_cairo_output_stream_printf (surface->output,
3853
for (i = 0; i < font_subset->num_glyphs; i++)
3854
_cairo_output_stream_printf (surface->output, " %f", widths[i]);
3855
_cairo_output_stream_printf (surface->output,
3859
if (to_unicode_stream.id != 0)
3860
_cairo_output_stream_printf (surface->output,
3861
" /ToUnicode %d 0 R\r\n",
3862
to_unicode_stream.id);
3864
_cairo_output_stream_printf (surface->output,
3868
font.font_id = font_subset->font_id;
3869
font.subset_id = font_subset->subset_id;
3870
font.subset_resource = subset_resource;
3871
return _cairo_array_append (&surface->fonts, &font);
3874
static cairo_status_t
3875
_cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
3878
cairo_pdf_surface_t *surface = closure;
3879
cairo_status_t status;
3881
if (font_subset->is_composite) {
3882
status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
3883
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3886
status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
3887
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3890
status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
3891
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3894
#if CAIRO_HAS_FT_FONT
3895
status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
3896
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3900
status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
3901
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3905
return CAIRO_STATUS_SUCCESS;
3908
static cairo_status_t
3909
_cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
3912
cairo_pdf_surface_t *surface = closure;
3913
cairo_status_t status;
3915
status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
3916
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3919
return CAIRO_STATUS_SUCCESS;
3922
static cairo_status_t
3923
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
3925
cairo_status_t status;
3927
status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
3928
_cairo_pdf_surface_emit_unscaled_font_subset,
3933
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
3934
_cairo_pdf_surface_emit_scaled_font_subset,
3938
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
3939
surface->font_subsets = NULL;
3944
static cairo_pdf_resource_t
3945
_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface)
3947
cairo_pdf_resource_t catalog;
3949
catalog = _cairo_pdf_surface_new_object (surface);
3950
if (catalog.id == 0)
3953
_cairo_output_stream_printf (surface->output,
3955
"<< /Type /Catalog\r\n"
3956
" /Pages %d 0 R\r\n"
3960
surface->pages_resource.id);
3966
_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
3968
cairo_pdf_object_t *object;
3973
num_objects = _cairo_array_num_elements (&surface->objects);
3975
offset = _cairo_output_stream_get_position (surface->output);
3976
_cairo_output_stream_printf (surface->output,
3979
0, num_objects + 1);
3981
_cairo_output_stream_printf (surface->output,
3982
"0000000000 65535 f\r\n");
3983
for (i = 0; i < num_objects; i++) {
3984
object = _cairo_array_index (&surface->objects, i);
3985
snprintf (buffer, sizeof buffer, "%010ld", object->offset);
3986
_cairo_output_stream_printf (surface->output,
3987
"%s 00000 n\r\n", buffer);
3993
static cairo_status_t
3994
_cairo_pdf_surface_emit_clip (cairo_pdf_surface_t *surface,
3995
cairo_path_fixed_t *path,
3996
cairo_fill_rule_t fill_rule)
3998
const char *pdf_operator;
4001
_cairo_output_stream_printf (surface->output, "Q q\r\n");
4002
return CAIRO_STATUS_SUCCESS;
4005
if (! path->has_current_point) {
4006
/* construct an empty path */
4007
_cairo_output_stream_printf (surface->output, "0 0 m ");
4009
pdf_path_info_t info;
4010
cairo_status_t status;
4012
info.output = surface->output;
4013
info.cairo_to_pdf = &surface->cairo_to_pdf;
4014
info.ctm_inverse = NULL;
4016
status = _cairo_path_fixed_interpret (path,
4017
CAIRO_DIRECTION_FORWARD,
4018
_cairo_pdf_path_move_to,
4019
_cairo_pdf_path_line_to,
4020
_cairo_pdf_path_curve_to,
4021
_cairo_pdf_path_close_path,
4027
switch (fill_rule) {
4028
case CAIRO_FILL_RULE_WINDING:
4031
case CAIRO_FILL_RULE_EVEN_ODD:
4032
pdf_operator = "W*";
4038
_cairo_output_stream_printf (surface->output,
4042
return CAIRO_STATUS_SUCCESS;
4045
static cairo_status_t
4046
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
4048
cairo_status_t status;
4049
cairo_pdf_resource_t page;
4050
cairo_pdf_resource_t content_group, knockout_group, page_content;
4051
cairo_bool_t has_fallback_images = FALSE;
4053
if (_cairo_array_num_elements (&surface->knockout_group) > 0)
4054
has_fallback_images = TRUE;
4056
status = _cairo_pdf_surface_open_group (surface);
4060
status = _cairo_pdf_surface_write_group_list (surface, &surface->content_group);
4064
status = _cairo_pdf_surface_close_group (surface, &content_group);
4068
if (has_fallback_images) {
4069
status = _cairo_pdf_surface_open_knockout_group (surface, &content_group);
4073
status = _cairo_pdf_surface_write_group_list (surface, &surface->knockout_group);
4077
status = _cairo_pdf_surface_close_group (surface, &knockout_group);
4082
page_content = _cairo_pdf_surface_open_stream (surface,
4084
" /Type /XObject\r\n"
4085
" /Subtype /Form\r\n"
4086
" /BBox [ 0 0 %f %f ]\r\n"
4089
" /S /Transparency\r\n"
4090
" /CS /DeviceRGB\r\n"
4094
if (page_content.id == 0)
4095
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4097
_cairo_output_stream_printf (surface->output,
4099
has_fallback_images ? knockout_group.id : content_group.id);
4100
status = _cairo_pdf_surface_close_stream (surface);
4104
page = _cairo_pdf_surface_new_object (surface);
4106
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4108
_cairo_output_stream_printf (surface->output,
4110
"<< /Type /Page\r\n"
4111
" /Parent %d 0 R\r\n"
4112
" /MediaBox [ 0 0 %f %f ]\r\n"
4113
" /Contents [ %d 0 R ]\r\n"
4116
" /S /Transparency\r\n"
4117
" /CS /DeviceRGB\r\n"
4119
" /Resources <<\r\n"
4120
" /XObject << /x%d %d 0 R >>\r\n"
4125
surface->pages_resource.id,
4129
has_fallback_images ? knockout_group.id : content_group.id,
4130
has_fallback_images ? knockout_group.id : content_group.id);
4132
status = _cairo_array_append (&surface->pages, &page);
4136
return CAIRO_STATUS_SUCCESS;
4140
_surface_pattern_supported (cairo_surface_pattern_t *pattern)
4142
cairo_extend_t extend;
4144
if (_cairo_surface_is_meta (pattern->surface))
4147
if (pattern->surface->backend->acquire_source_image == NULL)
4150
/* Does an ALPHA-only source surface even make sense? Maybe, but I
4151
* don't think it's worth the extra code to support it. */
4153
/* XXX: Need to write this function here...
4154
content = cairo_surface_get_content (pattern->surface);
4155
if (content == CAIRO_CONTENT_ALPHA)
4159
extend = cairo_pattern_get_extend (&pattern->base);
4161
case CAIRO_EXTEND_NONE:
4162
case CAIRO_EXTEND_REPEAT:
4163
case CAIRO_EXTEND_REFLECT:
4164
/* There's no point returning FALSE for EXTEND_PAD, as the image
4165
* surface does not currently implement it either */
4166
case CAIRO_EXTEND_PAD:
4175
_gradient_pattern_supported (cairo_pattern_t *pattern)
4177
cairo_extend_t extend;
4179
extend = cairo_pattern_get_extend (pattern);
4182
/* Radial gradients are currently only supported with EXTEND_NONE
4183
* and EXTEND_PAD and when one circle is inside the other. */
4184
if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
4185
double x1, y1, x2, y2, r1, r2, d;
4186
cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
4188
if (extend == CAIRO_EXTEND_REPEAT ||
4189
extend == CAIRO_EXTEND_REFLECT) {
4193
x1 = _cairo_fixed_to_double (radial->c1.x);
4194
y1 = _cairo_fixed_to_double (radial->c1.y);
4195
r1 = _cairo_fixed_to_double (radial->r1);
4196
x2 = _cairo_fixed_to_double (radial->c2.x);
4197
y2 = _cairo_fixed_to_double (radial->c2.y);
4198
r2 = _cairo_fixed_to_double (radial->r2);
4200
d = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
4201
if (d > fabs(r2 - r1)) {
4210
_pattern_supported (cairo_pattern_t *pattern)
4212
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
4215
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
4216
pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
4217
return _gradient_pattern_supported (pattern);
4219
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
4220
return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
4225
static cairo_int_status_t
4226
_cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
4227
cairo_operator_t op,
4228
cairo_pattern_t *pattern)
4230
if (surface->force_fallbacks && surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
4231
return CAIRO_INT_STATUS_UNSUPPORTED;
4233
if (! _pattern_supported (pattern))
4234
return CAIRO_INT_STATUS_UNSUPPORTED;
4236
if (op == CAIRO_OPERATOR_OVER) {
4237
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
4238
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
4239
if ( _cairo_surface_is_meta (surface_pattern->surface))
4240
return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
4242
return CAIRO_STATUS_SUCCESS;
4245
/* The SOURCE operator is only supported for the fallback images. */
4246
if (op == CAIRO_OPERATOR_SOURCE &&
4247
surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER)
4248
return CAIRO_STATUS_SUCCESS;
4250
return CAIRO_INT_STATUS_UNSUPPORTED;
4254
_cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
4255
cairo_operator_t op,
4256
cairo_pattern_t *pattern)
4258
if (_cairo_pdf_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
4264
static cairo_int_status_t
4265
_cairo_pdf_surface_set_operator (cairo_pdf_surface_t *surface,
4266
cairo_operator_t op)
4268
cairo_status_t status;
4270
if (op == CAIRO_OPERATOR_OVER)
4271
return CAIRO_STATUS_SUCCESS;
4273
if (op == CAIRO_OPERATOR_SOURCE) {
4274
surface->current_group = &surface->knockout_group;
4275
status = _cairo_pdf_surface_stop_content_stream (surface);
4279
status = _cairo_pdf_surface_start_content_stream (surface);
4283
return CAIRO_STATUS_SUCCESS;
4286
return CAIRO_INT_STATUS_UNSUPPORTED;
4289
static cairo_int_status_t
4290
_cairo_pdf_surface_paint (void *abstract_surface,
4291
cairo_operator_t op,
4292
cairo_pattern_t *source)
4294
cairo_pdf_surface_t *surface = abstract_surface;
4295
cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
4296
cairo_status_t status;
4298
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
4299
return _cairo_pdf_surface_analyze_operation (surface, op, source);
4301
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
4303
status = _cairo_pdf_surface_emit_pattern (surface, source);
4307
status = _cairo_pdf_surface_set_operator (surface, op);
4311
if (surface->emitted_pattern.smask.id != 0) {
4312
_cairo_pdf_surface_pause_content_stream (surface);
4313
status = _cairo_pdf_surface_open_group (surface);
4317
_cairo_output_stream_printf (surface->output, "q ");
4320
status = _cairo_pdf_surface_select_pattern (surface, FALSE);
4324
_cairo_output_stream_printf (surface->output,
4325
"0 0 %f %f re f\r\n",
4326
surface->width, surface->height);
4328
if (surface->emitted_pattern.smask.id != 0) {
4329
status = _cairo_pdf_surface_close_group (surface, &smask_group);
4333
_cairo_pdf_surface_resume_content_stream (surface);
4334
_cairo_output_stream_printf (surface->output,
4335
"q /s%d gs /x%d Do Q\r\n",
4336
surface->emitted_pattern.smask,
4338
status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
4341
status = _cairo_pdf_surface_add_xobject (surface, smask_group);
4345
_cairo_output_stream_printf (surface->output, "Q\r\n");
4348
status = _cairo_output_stream_get_status (surface->output);
4352
return _cairo_pdf_surface_check_content_stream_size (surface);
4355
static cairo_int_status_t
4356
_cairo_pdf_surface_mask (void *abstract_surface,
4357
cairo_operator_t op,
4358
cairo_pattern_t *source,
4359
cairo_pattern_t *mask)
4361
cairo_pdf_surface_t *surface = abstract_surface;
4362
cairo_pdf_resource_t mask_group;
4363
cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
4364
cairo_pdf_resource_t source_group;
4365
cairo_pdf_resource_t smask;
4366
cairo_pdf_resource_t gstate;
4367
cairo_status_t status, status2;
4369
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
4370
status = _cairo_pdf_surface_analyze_operation (surface, op, source);
4371
if (status != CAIRO_STATUS_SUCCESS &&
4372
status != CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
4375
status2 = _cairo_pdf_surface_analyze_operation (surface, op, mask);
4376
if (status2 != CAIRO_STATUS_SUCCESS)
4382
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
4383
assert (_cairo_pdf_surface_operation_supported (surface, op, mask));
4385
status = _cairo_pdf_surface_set_operator (surface, op);
4389
/* Create mask group */
4390
status = _cairo_pdf_surface_emit_pattern (surface, mask);
4394
_cairo_pdf_surface_pause_content_stream (surface);
4396
status = _cairo_pdf_surface_open_group (surface);
4400
status = _cairo_pdf_surface_select_pattern (surface, FALSE);
4404
_cairo_output_stream_printf (surface->output,
4405
"0 0 %f %f re f\r\n",
4406
surface->width, surface->height);
4407
status = _cairo_pdf_surface_close_group (surface, &mask_group);
4411
if (surface->emitted_pattern.smask.id != 0) {
4413
status = _cairo_pdf_surface_open_group (surface);
4417
_cairo_output_stream_printf (surface->output,
4418
"/s%d gs /x%d Do\r\n",
4419
surface->emitted_pattern.smask,
4421
status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
4424
status = _cairo_pdf_surface_add_xobject (surface, group);
4428
status = _cairo_pdf_surface_close_group (surface, &mask_group);
4433
/* Create source group */
4434
status = _cairo_pdf_surface_emit_pattern (surface, source);
4438
_cairo_pdf_surface_pause_content_stream (surface);
4440
status = _cairo_pdf_surface_open_group (surface);
4444
status = _cairo_pdf_surface_select_pattern (surface, FALSE);
4448
_cairo_output_stream_printf (surface->output,
4449
"0 0 %f %f re f\r\n",
4450
surface->width, surface->height);
4451
status = _cairo_pdf_surface_close_group (surface, &source_group);
4455
if (surface->emitted_pattern.smask.id != 0) {
4456
group = source_group;
4457
status = _cairo_pdf_surface_open_group (surface);
4461
_cairo_output_stream_printf (surface->output,
4462
"/s%d gs /x%d Do\r\n",
4463
surface->emitted_pattern.smask,
4465
status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
4468
status = _cairo_pdf_surface_add_xobject (surface, group);
4472
status =_cairo_pdf_surface_close_group (surface, &source_group);
4477
/* Create an smask based on the alpha component of mask_group */
4478
smask = _cairo_pdf_surface_new_object (surface);
4480
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4482
_cairo_output_stream_printf (surface->output,
4484
"<< /Type /Mask\r\n"
4492
/* Create a GState that uses the smask */
4493
gstate = _cairo_pdf_surface_new_object (surface);
4495
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4497
_cairo_output_stream_printf (surface->output,
4499
"<< /Type /ExtGState\r\n"
4500
" /SMask %d 0 R\r\n"
4509
/* Select the GState then draw the source */
4510
_cairo_pdf_surface_resume_content_stream (surface);
4511
_cairo_output_stream_printf (surface->output,
4512
"q /s%d gs /x%d Do Q\r\n",
4515
status = _cairo_pdf_surface_add_smask (surface, gstate);
4518
status = _cairo_pdf_surface_add_xobject (surface, source_group);
4522
return _cairo_output_stream_get_status (surface->output);
4526
_cairo_pdf_line_cap (cairo_line_cap_t cap)
4529
case CAIRO_LINE_CAP_BUTT:
4531
case CAIRO_LINE_CAP_ROUND:
4533
case CAIRO_LINE_CAP_SQUARE:
4542
_cairo_pdf_line_join (cairo_line_join_t join)
4545
case CAIRO_LINE_JOIN_MITER:
4547
case CAIRO_LINE_JOIN_ROUND:
4549
case CAIRO_LINE_JOIN_BEVEL:
4557
static cairo_status_t
4558
_cairo_pdf_surface_emit_stroke_style (cairo_pdf_surface_t *surface,
4559
cairo_stroke_style_t *style)
4561
_cairo_output_stream_printf (surface->output,
4565
_cairo_output_stream_printf (surface->output,
4567
_cairo_pdf_line_cap (style->line_cap));
4569
_cairo_output_stream_printf (surface->output,
4571
_cairo_pdf_line_join (style->line_join));
4573
if (style->num_dashes) {
4575
_cairo_output_stream_printf (surface->output, "[");
4576
for (d = 0; d < style->num_dashes; d++)
4577
_cairo_output_stream_printf (surface->output, " %f", style->dash[d]);
4578
_cairo_output_stream_printf (surface->output, "] %f d\r\n",
4579
style->dash_offset);
4581
_cairo_output_stream_printf (surface->output, "[] 0.0 d\r\n");
4584
_cairo_output_stream_printf (surface->output,
4586
style->miter_limit);
4588
return _cairo_output_stream_get_status (surface->output);
4591
static cairo_int_status_t
4592
_cairo_pdf_surface_stroke (void *abstract_surface,
4593
cairo_operator_t op,
4594
cairo_pattern_t *source,
4595
cairo_path_fixed_t *path,
4596
cairo_stroke_style_t *style,
4597
cairo_matrix_t *ctm,
4598
cairo_matrix_t *ctm_inverse,
4600
cairo_antialias_t antialias)
4602
cairo_pdf_surface_t *surface = abstract_surface;
4603
cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
4604
pdf_path_info_t info;
4605
cairo_status_t status;
4608
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
4609
return _cairo_pdf_surface_analyze_operation (surface, op, source);
4611
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
4613
status = _cairo_pdf_surface_emit_pattern (surface, source);
4617
if (surface->emitted_pattern.smask.id != 0) {
4618
_cairo_pdf_surface_pause_content_stream (surface);
4619
status = _cairo_pdf_surface_open_group (surface);
4623
_cairo_output_stream_printf (surface->output, "q ");
4626
status = _cairo_pdf_surface_select_pattern (surface, TRUE);
4630
status = _cairo_pdf_surface_emit_stroke_style (surface,
4635
info.output = surface->output;
4636
info.cairo_to_pdf = NULL;
4637
info.ctm_inverse = ctm_inverse;
4639
cairo_matrix_multiply (&m, ctm, &surface->cairo_to_pdf);
4640
_cairo_output_stream_printf (surface->output,
4641
"q %f %f %f %f %f %f cm\r\n",
4642
m.xx, m.yx, m.xy, m.yy,
4645
status = _cairo_path_fixed_interpret (path,
4646
CAIRO_DIRECTION_FORWARD,
4647
_cairo_pdf_path_move_to,
4648
_cairo_pdf_path_line_to,
4649
_cairo_pdf_path_curve_to,
4650
_cairo_pdf_path_close_path,
4655
_cairo_output_stream_printf (surface->output, "S Q\r\n");
4657
if (surface->emitted_pattern.smask.id != 0) {
4658
status = _cairo_pdf_surface_close_group (surface, &smask_group);
4662
_cairo_pdf_surface_resume_content_stream (surface);
4663
_cairo_output_stream_printf (surface->output,
4664
"q /s%d gs /x%d Do Q\r\n",
4665
surface->emitted_pattern.smask,
4667
status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
4670
status = _cairo_pdf_surface_add_xobject (surface, smask_group);
4674
_cairo_output_stream_printf (surface->output, "Q\r\n");
4677
status = _cairo_output_stream_get_status (surface->output);
4681
return _cairo_pdf_surface_check_content_stream_size (surface);
4684
static cairo_int_status_t
4685
_cairo_pdf_surface_fill (void *abstract_surface,
4686
cairo_operator_t op,
4687
cairo_pattern_t *source,
4688
cairo_path_fixed_t *path,
4689
cairo_fill_rule_t fill_rule,
4691
cairo_antialias_t antialias)
4693
cairo_pdf_surface_t *surface = abstract_surface;
4694
cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
4695
const char *pdf_operator;
4696
cairo_status_t status;
4697
pdf_path_info_t info;
4699
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
4700
return _cairo_pdf_surface_analyze_operation (surface, op, source);
4702
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
4704
status = _cairo_pdf_surface_set_operator (surface, op);
4708
status = _cairo_pdf_surface_emit_pattern (surface, source);
4712
if (surface->emitted_pattern.smask.id != 0) {
4713
_cairo_pdf_surface_pause_content_stream (surface);
4714
status = _cairo_pdf_surface_open_group (surface);
4718
_cairo_output_stream_printf (surface->output, "q ");
4721
status = _cairo_pdf_surface_select_pattern (surface, FALSE);
4725
info.output = surface->output;
4726
info.cairo_to_pdf = &surface->cairo_to_pdf;
4727
info.ctm_inverse = NULL;
4728
status = _cairo_path_fixed_interpret (path,
4729
CAIRO_DIRECTION_FORWARD,
4730
_cairo_pdf_path_move_to,
4731
_cairo_pdf_path_line_to,
4732
_cairo_pdf_path_curve_to,
4733
_cairo_pdf_path_close_path,
4738
switch (fill_rule) {
4739
case CAIRO_FILL_RULE_WINDING:
4742
case CAIRO_FILL_RULE_EVEN_ODD:
4743
pdf_operator = "f*";
4749
_cairo_output_stream_printf (surface->output,
4753
if (surface->emitted_pattern.smask.id != 0) {
4754
status = _cairo_pdf_surface_close_group (surface, &smask_group);
4758
_cairo_pdf_surface_resume_content_stream (surface);
4759
_cairo_output_stream_printf (surface->output,
4760
"q /s%d gs /x%d Do Q\r\n",
4761
surface->emitted_pattern.smask,
4763
status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
4766
status = _cairo_pdf_surface_add_xobject (surface, smask_group);
4770
_cairo_output_stream_printf (surface->output, "Q\r\n");
4773
status = _cairo_output_stream_get_status (surface->output);
4777
return _cairo_pdf_surface_check_content_stream_size (surface);
4780
#define GLYPH_POSITION_TOLERANCE 0.001
4782
static cairo_int_status_t
4783
_cairo_pdf_surface_show_glyphs (void *abstract_surface,
4784
cairo_operator_t op,
4785
cairo_pattern_t *source,
4786
cairo_glyph_t *glyphs,
4788
cairo_scaled_font_t *scaled_font)
4790
cairo_pdf_surface_t *surface = abstract_surface;
4791
cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */
4792
unsigned int current_subset_id = (unsigned int)-1;
4793
cairo_scaled_font_subsets_glyph_t subset_glyph;
4794
cairo_bool_t diagonal, in_TJ;
4795
cairo_status_t status;
4796
double Tlm_x = 0, Tlm_y = 0;
4800
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
4801
return _cairo_pdf_surface_analyze_operation (surface, op, source);
4803
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
4805
status = _cairo_pdf_surface_emit_pattern (surface, source);
4809
if (surface->emitted_pattern.smask.id != 0) {
4810
_cairo_pdf_surface_pause_content_stream (surface);
4811
status = _cairo_pdf_surface_open_group (surface);
4815
_cairo_output_stream_printf (surface->output, "q ");
4818
status = _cairo_pdf_surface_select_pattern (surface, FALSE);
4822
_cairo_output_stream_printf (surface->output,
4825
if (scaled_font->scale.xy == 0.0 &&
4826
scaled_font->scale.yx == 0.0)
4832
for (i = 0; i < num_glyphs; i++) {
4833
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
4834
scaled_font, glyphs[i].index,
4839
if (subset_glyph.is_composite)
4844
if (subset_glyph.is_scaled == FALSE) {
4846
cairo_matrix_transform_distance (&scaled_font->scale,
4847
&subset_glyph.x_advance,
4851
if (subset_glyph.subset_id != current_subset_id) {
4853
_cairo_output_stream_printf (surface->output, ">] TJ\r\n");
4856
_cairo_output_stream_printf (surface->output,
4857
"/f-%d-%d 1 Tf\r\n",
4858
subset_glyph.font_id,
4859
subset_glyph.subset_id);
4860
status = _cairo_pdf_surface_add_font (surface,
4861
subset_glyph.font_id,
4862
subset_glyph.subset_id);
4867
if (subset_glyph.subset_id != current_subset_id || !diagonal) {
4868
_cairo_output_stream_printf (surface->output,
4869
"%f %f %f %f %f %f Tm\r\n",
4870
scaled_font->scale.xx,
4871
-scaled_font->scale.yx,
4872
-scaled_font->scale.xy,
4873
scaled_font->scale.yy,
4875
surface->height - glyphs[i].y);
4876
current_subset_id = subset_glyph.subset_id;
4877
Tlm_x = glyphs[i].x;
4878
Tlm_y = glyphs[i].y;
4883
if (i < num_glyphs - 1 &&
4884
fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE &&
4885
fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10)
4889
_cairo_output_stream_printf (surface->output,
4891
(glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
4892
-(glyphs[i].y - Tlm_y)/scaled_font->scale.yy);
4894
Tlm_x = glyphs[i].x;
4895
Tlm_y = glyphs[i].y;
4898
_cairo_output_stream_printf (surface->output,
4901
subset_glyph.subset_glyph_index);
4902
Tm_x += subset_glyph.x_advance;
4905
if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
4906
double delta = glyphs[i].x - Tm_x;
4908
_cairo_output_stream_printf (surface->output,
4910
-1000.0*delta/scaled_font->scale.xx);
4913
_cairo_output_stream_printf (surface->output,
4916
subset_glyph.subset_glyph_index);
4917
Tm_x += subset_glyph.x_advance;
4923
if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
4924
double delta = glyphs[i].x - Tm_x;
4926
_cairo_output_stream_printf (surface->output,
4928
-1000.0*delta/scaled_font->scale.xx);
4931
_cairo_output_stream_printf (surface->output,
4934
subset_glyph.subset_glyph_index);
4935
Tm_x += subset_glyph.x_advance;
4939
_cairo_output_stream_printf (surface->output,
4941
(glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
4942
(glyphs[i].y - Tlm_y)/-scaled_font->scale.yy);
4943
Tlm_x = glyphs[i].x;
4944
Tlm_y = glyphs[i].y;
4947
_cairo_output_stream_printf (surface->output,
4950
subset_glyph.subset_glyph_index);
4951
Tm_x += subset_glyph.x_advance;
4955
_cairo_output_stream_printf (surface->output,
4958
subset_glyph.subset_glyph_index);
4962
_cairo_output_stream_printf (surface->output,
4965
if (surface->emitted_pattern.smask.id != 0) {
4966
status = _cairo_pdf_surface_close_group (surface, &smask_group);
4970
_cairo_pdf_surface_resume_content_stream (surface);
4972
_cairo_output_stream_printf (surface->output,
4973
"q /s%d gs /x%d Do Q\r\n",
4974
surface->emitted_pattern.smask,
4976
status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
4979
status = _cairo_pdf_surface_add_xobject (surface, smask_group);
4983
_cairo_output_stream_printf (surface->output, "Q\r\n");
4986
status = _cairo_output_stream_get_status (surface->output);
4990
return _cairo_pdf_surface_check_content_stream_size (surface);
4994
_cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
4995
cairo_paginated_mode_t paginated_mode)
4997
cairo_pdf_surface_t *surface = abstract_surface;
4999
surface->paginated_mode = paginated_mode;
5002
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
5003
CAIRO_SURFACE_TYPE_PDF,
5004
_cairo_pdf_surface_create_similar,
5005
_cairo_pdf_surface_finish,
5006
NULL, /* acquire_source_image */
5007
NULL, /* release_source_image */
5008
NULL, /* acquire_dest_image */
5009
NULL, /* release_dest_image */
5010
NULL, /* clone_similar */
5011
NULL, /* composite */
5012
NULL, /* fill_rectangles */
5013
NULL, /* composite_trapezoids */
5014
_cairo_pdf_surface_copy_page,
5015
_cairo_pdf_surface_show_page,
5016
NULL, /* set_clip_region */
5017
_cairo_pdf_surface_intersect_clip_path,
5018
_cairo_pdf_surface_get_extents,
5019
NULL, /* old_show_glyphs */
5020
_cairo_pdf_surface_get_font_options,
5022
NULL, /* mark_dirty_rectangle */
5023
NULL, /* scaled_font_fini */
5024
NULL, /* scaled_glyph_fini */
5026
/* Here are the drawing functions */
5028
_cairo_pdf_surface_paint,
5029
_cairo_pdf_surface_mask,
5030
_cairo_pdf_surface_stroke,
5031
_cairo_pdf_surface_fill,
5032
_cairo_pdf_surface_show_glyphs,
5033
NULL, /* snapshot */
5035
NULL, /* is_compatible */
5039
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
5040
_cairo_pdf_surface_start_page,
5041
_cairo_pdf_surface_set_paginated_mode