1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
3  *
4  * Copyright © 2004 Red Hat, Inc
5  * Copyright © 2006 Red Hat, Inc
6  * Copyright © 2007, 2008 Adrian Johnson
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it either under the terms of the GNU Lesser General Public
10  * License version 2.1 as published by the Free Software Foundation
11  * (the "LGPL") or, at your option, under the terms of the Mozilla
12  * Public License Version 1.1 (the "MPL"). If you do not alter this
13  * notice, a recipient may use your version of this file under either
14  * the MPL or the LGPL.
15  *
16  * You should have received a copy of the LGPL along with this library
17  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19  * You should have received a copy of the MPL along with this library
20  * in the file COPYING-MPL-1.1
21  *
22  * The contents of this file are subject to the Mozilla Public License
23  * Version 1.1 (the "License"); you may not use this file except in
24  * compliance with the License. You may obtain a copy of the License at
25  * http://www.mozilla.org/MPL/
26  *
27  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29  * the specific language governing rights and limitations.
30  *
31  * The Original Code is the cairo graphics library.
32  *
33  * The Initial Developer of the Original Code is University of Southern
34  * California.
35  *
36  * Contributor(s):
37  *	Kristian Høgsberg <krh@redhat.com>
38  *	Carl Worth <cworth@cworth.org>
39  *	Adrian Johnson <ajohnson@redneon.com>
40  */
41 
42 #define _BSD_SOURCE /* for snprintf() */
43 #include "cairoint.h"
44 #include "cairo-pdf.h"
45 #include "cairo-pdf-surface-private.h"
46 #include "cairo-pdf-operators-private.h"
47 #include "cairo-analysis-surface-private.h"
48 #include "cairo-composite-rectangles-private.h"
49 #include "cairo-error-private.h"
50 #include "cairo-image-info-private.h"
51 #include "cairo-recording-surface-private.h"
52 #include "cairo-output-stream-private.h"
53 #include "cairo-paginated-private.h"
54 #include "cairo-scaled-font-subsets-private.h"
55 #include "cairo-surface-clipper-private.h"
56 #include "cairo-surface-subsurface-private.h"
57 #include "cairo-type3-glyph-surface-private.h"
58 
59 #include <time.h>
60 #include <zlib.h>
61 
62 /* Issues:
63  *
64  * - We embed an image in the stream each time it's composited.  We
65  *   could add generation counters to surfaces and remember the stream
66  *   ID for a particular generation for a particular surface.
67  *
68  * - Backend specific meta data.
69  */
70 
71 /*
72  * Page Structure of the Generated PDF:
73  *
74  * Each page requiring fallbacks images contains a knockout group at
75  * the top level. The first operation of the knockout group paints a
76  * group containing all the supported drawing operations. Fallback
77  * images (if any) are painted in the knockout group. This ensures
78  * that fallback images do not composite with any content under the
79  * fallback images.
80  *
81  * Streams:
82  *
83  * This PDF surface has three types of streams:
84  *  - PDF Stream
85  *  - Content Stream
86  *  - Group Stream
87  *
88  * Calling _cairo_output_stream_printf (surface->output, ...) will
89  * write to the currently open stream.
90  *
91  * PDF Stream:
92  *   A PDF Stream may be opened and closed with the following functions:
93  *     _cairo_pdf_surface_open stream ()
94  *     _cairo_pdf_surface_close_stream ()
95  *
96  *   PDF Streams are written directly to the PDF file. They are used for
97  *   fonts, images and patterns.
98  *
99  * Content Stream:
100  *   The Content Stream is opened and closed with the following functions:
101  *     _cairo_pdf_surface_open_content_stream ()
102  *     _cairo_pdf_surface_close_content_stream ()
103  *
104  *   The Content Stream contains the text and graphics operators.
105  *
106  * Group Stream:
107  *   A Group Stream may be opened and closed with the following functions:
108  *     _cairo_pdf_surface_open_group ()
109  *     _cairo_pdf_surface_close_group ()
110  *
111  *   A Group Stream is a Form XObject. It is used for short sequences
112  *   of operators. As the content is very short the group is stored in
113  *   memory until it is closed. This allows some optimization such as
114  *   including the Resource dictionary and stream length inside the
115  *   XObject instead of using an indirect object.
116  */
117 
118 /**
119  * SECTION:cairo-pdf
120  * @Title: PDF Surfaces
121  * @Short_Description: Rendering PDF documents
122  * @See_Also: #cairo_surface_t
123  *
124  * The PDF surface is used to render cairo graphics to Adobe
125  * PDF files and is a multi-page vector surface backend.
126  */
127 
128 /**
129  * CAIRO_HAS_PDF_SURFACE:
130  *
131  * Defined if the PDF surface backend is available.
132  * This macro can be used to conditionally compile backend-specific code.
133  */
134 
135 static const cairo_pdf_version_t _cairo_pdf_versions[] =
136 {
137     CAIRO_PDF_VERSION_1_4,
138     CAIRO_PDF_VERSION_1_5
139 };
140 
141 #define CAIRO_PDF_VERSION_LAST ARRAY_LENGTH (_cairo_pdf_versions)
142 
143 static const char * _cairo_pdf_version_strings[CAIRO_PDF_VERSION_LAST] =
144 {
145     "PDF 1.4",
146     "PDF 1.5"
147 };
148 
149 typedef struct _cairo_pdf_object {
150     long offset;
151 } cairo_pdf_object_t;
152 
153 typedef struct _cairo_pdf_font {
154     unsigned int font_id;
155     unsigned int subset_id;
156     cairo_pdf_resource_t subset_resource;
157 } cairo_pdf_font_t;
158 
159 typedef struct _cairo_pdf_rgb_linear_function {
160     cairo_pdf_resource_t resource;
161     double               color1[3];
162     double               color2[3];
163 } cairo_pdf_rgb_linear_function_t;
164 
165 typedef struct _cairo_pdf_alpha_linear_function {
166     cairo_pdf_resource_t resource;
167     double               alpha1;
168     double               alpha2;
169 } cairo_pdf_alpha_linear_function_t;
170 
171 static cairo_pdf_resource_t
172 _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
173 
174 static void
175 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
176 
177 static void
178 _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
179 
180 static cairo_status_t
181 _cairo_pdf_surface_add_font (unsigned int        font_id,
182 			     unsigned int        subset_id,
183 			     void		*closure);
184 
185 static void
186 _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
187 
188 static cairo_status_t
189 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
190 				cairo_pdf_resource_t    *resource,
191                                 cairo_bool_t             compressed,
192 				const char		*fmt,
193 				...) CAIRO_PRINTF_FORMAT(4, 5);
194 static cairo_status_t
195 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t	*surface);
196 
197 static cairo_status_t
198 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
199 
200 static void
201 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
202 
203 static cairo_pdf_resource_t
204 _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface);
205 
206 static cairo_pdf_resource_t
207 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface);
208 
209 static long
210 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
211 
212 static cairo_status_t
213 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
214 
215 static cairo_status_t
216 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
217 
218 static cairo_bool_t
219 _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b);
220 
221 static const cairo_surface_backend_t cairo_pdf_surface_backend;
222 static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend;
223 
224 static cairo_pdf_resource_t
_cairo_pdf_surface_new_object(cairo_pdf_surface_t * surface)225 _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
226 {
227     cairo_pdf_resource_t resource;
228     cairo_status_t status;
229     cairo_pdf_object_t object;
230 
231     object.offset = _cairo_output_stream_get_position (surface->output);
232 
233     status = _cairo_array_append (&surface->objects, &object);
234     if (unlikely (status)) {
235 	resource.id = 0;
236 	return resource;
237     }
238 
239     resource = surface->next_available_resource;
240     surface->next_available_resource.id++;
241 
242     return resource;
243 }
244 
245 static void
_cairo_pdf_surface_update_object(cairo_pdf_surface_t * surface,cairo_pdf_resource_t resource)246 _cairo_pdf_surface_update_object (cairo_pdf_surface_t	*surface,
247 				  cairo_pdf_resource_t	 resource)
248 {
249     cairo_pdf_object_t *object;
250 
251     object = _cairo_array_index (&surface->objects, resource.id - 1);
252     object->offset = _cairo_output_stream_get_position (surface->output);
253 }
254 
255 static void
_cairo_pdf_surface_set_size_internal(cairo_pdf_surface_t * surface,double width,double height)256 _cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
257 				      double		  width,
258 				      double		  height)
259 {
260     surface->width = width;
261     surface->height = height;
262     cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
263     _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
264 						  &surface->cairo_to_pdf);
265 }
266 
267 static cairo_bool_t
_path_covers_bbox(cairo_pdf_surface_t * surface,cairo_path_fixed_t * path)268 _path_covers_bbox (cairo_pdf_surface_t *surface,
269 		   cairo_path_fixed_t *path)
270 {
271     cairo_box_t box;
272 
273     return _cairo_path_fixed_is_box (path, &box) &&
274 	   box.p1.x <= 0 &&
275 	   box.p1.y <= 0 &&
276 	   box.p2.x >= _cairo_fixed_from_double (surface->width) &&
277 	   box.p2.y >= _cairo_fixed_from_double (surface->height);
278 }
279 
280 static cairo_status_t
_cairo_pdf_surface_clipper_intersect_clip_path(cairo_surface_clipper_t * clipper,cairo_path_fixed_t * path,cairo_fill_rule_t fill_rule,double tolerance,cairo_antialias_t antialias)281 _cairo_pdf_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
282 						cairo_path_fixed_t	*path,
283 						cairo_fill_rule_t	fill_rule,
284 						double			tolerance,
285 						cairo_antialias_t	antialias)
286 {
287     cairo_pdf_surface_t *surface = cairo_container_of (clipper,
288 						       cairo_pdf_surface_t,
289 						       clipper);
290     cairo_int_status_t status;
291 
292     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
293     if (unlikely (status))
294 	return status;
295 
296     if (path == NULL) {
297 	_cairo_output_stream_printf (surface->output, "Q q\n");
298 
299 	surface->current_pattern_is_solid_color = FALSE;
300 	_cairo_pdf_operators_reset (&surface->pdf_operators);
301 
302 	return CAIRO_STATUS_SUCCESS;
303     }
304 
305     if (_path_covers_bbox (surface, path))
306 	return CAIRO_STATUS_SUCCESS;
307 
308     return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
309 }
310 
311 static cairo_surface_t *
_cairo_pdf_surface_create_for_stream_internal(cairo_output_stream_t * output,double width,double height)312 _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
313 					       double			 width,
314 					       double			 height)
315 {
316     cairo_pdf_surface_t *surface;
317     cairo_status_t status, status_ignored;
318 
319     surface = malloc (sizeof (cairo_pdf_surface_t));
320     if (unlikely (surface == NULL)) {
321 	/* destroy stream on behalf of caller */
322 	status = _cairo_output_stream_destroy (output);
323 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
324     }
325 
326     _cairo_surface_init (&surface->base,
327 			 &cairo_pdf_surface_backend,
328 			 NULL, /* device */
329 			 CAIRO_CONTENT_COLOR_ALPHA);
330 
331     surface->output = output;
332     surface->width = width;
333     surface->height = height;
334     cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
335 
336     _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
337     _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
338     _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t));
339     _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t));
340     _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t));
341     _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *));
342     _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t));
343 
344     _cairo_array_init (&surface->page_patterns, sizeof (cairo_pdf_pattern_t));
345     _cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t));
346     surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal);
347     if (unlikely (surface->all_surfaces == NULL)) {
348 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
349 	goto BAIL0;
350     }
351 
352     _cairo_pdf_group_resources_init (&surface->resources);
353 
354     surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
355     if (! surface->font_subsets) {
356 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
357 	goto BAIL1;
358     }
359 
360     surface->next_available_resource.id = 1;
361     surface->pages_resource = _cairo_pdf_surface_new_object (surface);
362     if (surface->pages_resource.id == 0) {
363 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
364         goto BAIL2;
365     }
366 
367     surface->pdf_version = CAIRO_PDF_VERSION_1_5;
368     surface->compress_content = TRUE;
369     surface->pdf_stream.active = FALSE;
370     surface->pdf_stream.old_output = NULL;
371     surface->group_stream.active = FALSE;
372     surface->group_stream.stream = NULL;
373     surface->group_stream.mem_stream = NULL;
374 
375     surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
376 
377     surface->force_fallbacks = FALSE;
378     surface->select_pattern_gstate_saved = FALSE;
379     surface->current_pattern_is_solid_color = FALSE;
380     surface->current_operator = CAIRO_OPERATOR_OVER;
381     surface->header_emitted = FALSE;
382 
383     _cairo_surface_clipper_init (&surface->clipper,
384 				 _cairo_pdf_surface_clipper_intersect_clip_path);
385 
386     _cairo_pdf_operators_init (&surface->pdf_operators,
387 			       surface->output,
388 			       &surface->cairo_to_pdf,
389 			       surface->font_subsets);
390     _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
391 						    _cairo_pdf_surface_add_font,
392 						    surface);
393     _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators, TRUE);
394 
395     surface->paginated_surface =  _cairo_paginated_surface_create (
396 	                                  &surface->base,
397 					  CAIRO_CONTENT_COLOR_ALPHA,
398 					  &cairo_pdf_surface_paginated_backend);
399 
400     status = surface->paginated_surface->status;
401     if (status == CAIRO_STATUS_SUCCESS) {
402 	/* paginated keeps the only reference to surface now, drop ours */
403 	cairo_surface_destroy (&surface->base);
404 	return surface->paginated_surface;
405     }
406 
407 BAIL2:
408     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
409 BAIL1:
410     _cairo_hash_table_destroy (surface->all_surfaces);
411 BAIL0:
412     _cairo_array_fini (&surface->objects);
413     free (surface);
414 
415     /* destroy stream on behalf of caller */
416     status_ignored = _cairo_output_stream_destroy (output);
417 
418     return _cairo_surface_create_in_error (status);
419 }
420 
421 /**
422  * cairo_pdf_surface_create_for_stream:
423  * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
424  *              to indicate a no-op @write_func. With a no-op @write_func,
425  *              the surface may be queried or used as a source without
426  *              generating any temporary files.
427  * @closure: the closure argument for @write_func
428  * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
429  * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
430  *
431  * Creates a PDF surface of the specified size in points to be written
432  * incrementally to the stream represented by @write_func and @closure.
433  *
434  * Return value: a pointer to the newly created surface. The caller
435  * owns the surface and should call cairo_surface_destroy() when done
436  * with it.
437  *
438  * This function always returns a valid pointer, but it will return a
439  * pointer to a "nil" surface if an error such as out of memory
440  * occurs. You can use cairo_surface_status() to check for this.
441  *
442  * Since: 1.2
443  */
444 cairo_surface_t *
cairo_pdf_surface_create_for_stream(cairo_write_func_t write_func,void * closure,double width_in_points,double height_in_points)445 cairo_pdf_surface_create_for_stream (cairo_write_func_t		 write_func,
446 				     void			*closure,
447 				     double			 width_in_points,
448 				     double			 height_in_points)
449 {
450     cairo_output_stream_t *output;
451 
452     output = _cairo_output_stream_create (write_func, NULL, closure);
453     if (_cairo_output_stream_get_status (output))
454 	return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
455 
456     return _cairo_pdf_surface_create_for_stream_internal (output,
457 							  width_in_points,
458 							  height_in_points);
459 }
460 
461 /**
462  * cairo_pdf_surface_create:
463  * @filename: a filename for the PDF output (must be writable), %NULL may be
464  *            used to specify no output. This will generate a PDF surface that
465  *            may be queried and used as a source, without generating a
466  *            temporary file.
467  * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
468  * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
469  *
470  * Creates a PDF surface of the specified size in points to be written
471  * to @filename.
472  *
473  * Return value: a pointer to the newly created surface. The caller
474  * owns the surface and should call cairo_surface_destroy() when done
475  * with it.
476  *
477  * This function always returns a valid pointer, but it will return a
478  * pointer to a "nil" surface if an error such as out of memory
479  * occurs. You can use cairo_surface_status() to check for this.
480  *
481  * Since: 1.2
482  **/
483 cairo_surface_t *
cairo_pdf_surface_create(const char * filename,double width_in_points,double height_in_points)484 cairo_pdf_surface_create (const char		*filename,
485 			  double		 width_in_points,
486 			  double		 height_in_points)
487 {
488     cairo_output_stream_t *output;
489 
490     output = _cairo_output_stream_create_for_filename (filename);
491     if (_cairo_output_stream_get_status (output))
492 	return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output));
493 
494     return _cairo_pdf_surface_create_for_stream_internal (output,
495 							  width_in_points,
496 							  height_in_points);
497 }
498 
499 static cairo_bool_t
_cairo_surface_is_pdf(cairo_surface_t * surface)500 _cairo_surface_is_pdf (cairo_surface_t *surface)
501 {
502     return surface->backend == &cairo_pdf_surface_backend;
503 }
504 
505 /* If the abstract_surface is a paginated surface, and that paginated
506  * surface's target is a pdf_surface, then set pdf_surface to that
507  * target. Otherwise return FALSE.
508  */
509 static cairo_bool_t
_extract_pdf_surface(cairo_surface_t * surface,cairo_pdf_surface_t ** pdf_surface)510 _extract_pdf_surface (cairo_surface_t		 *surface,
511 		      cairo_pdf_surface_t	**pdf_surface)
512 {
513     cairo_surface_t *target;
514     cairo_status_t status_ignored;
515 
516     if (surface->status)
517 	return FALSE;
518     if (surface->finished) {
519 	status_ignored = _cairo_surface_set_error (surface,
520 						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
521         return FALSE;
522     }
523 
524     if (! _cairo_surface_is_paginated (surface)) {
525 	status_ignored = _cairo_surface_set_error (surface,
526 						   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
527 	return FALSE;
528     }
529 
530     target = _cairo_paginated_surface_get_target (surface);
531     if (target->status) {
532 	status_ignored = _cairo_surface_set_error (surface,
533 						   target->status);
534 	return FALSE;
535     }
536     if (target->finished) {
537 	status_ignored = _cairo_surface_set_error (surface,
538 						   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
539 	return FALSE;
540     }
541 
542     if (! _cairo_surface_is_pdf (target)) {
543 	status_ignored = _cairo_surface_set_error (surface,
544 						   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
545 	return FALSE;
546     }
547 
548     *pdf_surface = (cairo_pdf_surface_t *) target;
549     return TRUE;
550 }
551 
552 /**
553  * cairo_pdf_surface_restrict_to_version:
554  * @surface: a PDF #cairo_surface_t
555  * @version: PDF version
556  *
557  * Restricts the generated PDF file to @version. See cairo_pdf_get_versions()
558  * for a list of available version values that can be used here.
559  *
560  * This function should only be called before any drawing operations
561  * have been performed on the given surface. The simplest way to do
562  * this is to call this function immediately after creating the
563  * surface.
564  *
565  * Since: 1.10
566  **/
567 void
cairo_pdf_surface_restrict_to_version(cairo_surface_t * abstract_surface,cairo_pdf_version_t version)568 cairo_pdf_surface_restrict_to_version (cairo_surface_t 		*abstract_surface,
569 				       cairo_pdf_version_t  	 version)
570 {
571     cairo_pdf_surface_t *surface = NULL; /* hide compiler warning */
572 
573     if (! _extract_pdf_surface (abstract_surface, &surface))
574 	return;
575 
576     if (version < CAIRO_PDF_VERSION_LAST)
577 	surface->pdf_version = version;
578 
579     _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators,
580 					    version >= CAIRO_PDF_VERSION_1_5);
581 }
582 
583 /**
584  * cairo_pdf_get_versions:
585  * @versions: supported version list
586  * @num_versions: list length
587  *
588  * Used to retrieve the list of supported versions. See
589  * cairo_pdf_surface_restrict_to_version().
590  *
591  * Since: 1.10
592  **/
593 void
cairo_pdf_get_versions(cairo_pdf_version_t const ** versions,int * num_versions)594 cairo_pdf_get_versions (cairo_pdf_version_t const	**versions,
595                         int                     	 *num_versions)
596 {
597     if (versions != NULL)
598 	*versions = _cairo_pdf_versions;
599 
600     if (num_versions != NULL)
601 	*num_versions = CAIRO_PDF_VERSION_LAST;
602 }
603 
604 /**
605  * cairo_pdf_version_to_string:
606  * @version: a version id
607  *
608  * Get the string representation of the given @version id. This function
609  * will return %NULL if @version isn't valid. See cairo_pdf_get_versions()
610  * for a way to get the list of valid version ids.
611  *
612  * Return value: the string associated to given version.
613  *
614  * Since: 1.10
615  **/
616 const char *
cairo_pdf_version_to_string(cairo_pdf_version_t version)617 cairo_pdf_version_to_string (cairo_pdf_version_t version)
618 {
619     if (version >= CAIRO_PDF_VERSION_LAST)
620 	return NULL;
621 
622     return _cairo_pdf_version_strings[version];
623 }
624 
625 /**
626  * cairo_pdf_surface_set_size:
627  * @surface: a PDF #cairo_surface_t
628  * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
629  * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
630  *
631  * Changes the size of a PDF surface for the current (and
632  * subsequent) pages.
633  *
634  * This function should only be called before any drawing operations
635  * have been performed on the current page. The simplest way to do
636  * this is to call this function immediately after creating the
637  * surface or immediately after completing a page with either
638  * cairo_show_page() or cairo_copy_page().
639  *
640  * Since: 1.2
641  **/
642 void
cairo_pdf_surface_set_size(cairo_surface_t * surface,double width_in_points,double height_in_points)643 cairo_pdf_surface_set_size (cairo_surface_t	*surface,
644 			    double		 width_in_points,
645 			    double		 height_in_points)
646 {
647     cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */
648     cairo_status_t status;
649 
650     if (! _extract_pdf_surface (surface, &pdf_surface))
651 	return;
652 
653     _cairo_pdf_surface_set_size_internal (pdf_surface,
654 					  width_in_points,
655 					  height_in_points);
656     status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
657 						width_in_points,
658 						height_in_points);
659     if (status)
660 	status = _cairo_surface_set_error (surface, status);
661 }
662 
663 static void
_cairo_pdf_surface_clear(cairo_pdf_surface_t * surface)664 _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
665 {
666     int i, size;
667     cairo_pdf_pattern_t *pattern;
668     cairo_pdf_source_surface_t *src_surface;
669     cairo_pdf_smask_group_t *group;
670 
671     size = _cairo_array_num_elements (&surface->page_patterns);
672     for (i = 0; i < size; i++) {
673 	pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->page_patterns, i);
674 	cairo_pattern_destroy (pattern->pattern);
675     }
676     _cairo_array_truncate (&surface->page_patterns, 0);
677 
678     size = _cairo_array_num_elements (&surface->page_surfaces);
679     for (i = 0; i < size; i++) {
680 	src_surface = (cairo_pdf_source_surface_t *) _cairo_array_index (&surface->page_surfaces, i);
681 	cairo_surface_destroy (src_surface->surface);
682     }
683     _cairo_array_truncate (&surface->page_surfaces, 0);
684 
685     size = _cairo_array_num_elements (&surface->smask_groups);
686     for (i = 0; i < size; i++) {
687 	_cairo_array_copy_element (&surface->smask_groups, i, &group);
688 	_cairo_pdf_smask_group_destroy (group);
689     }
690     _cairo_array_truncate (&surface->smask_groups, 0);
691     _cairo_array_truncate (&surface->knockout_group, 0);
692 }
693 
694 static void
_cairo_pdf_group_resources_init(cairo_pdf_group_resources_t * res)695 _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res)
696 {
697     int i;
698 
699     for (i = 0; i < CAIRO_NUM_OPERATORS; i++)
700 	res->operators[i] = FALSE;
701 
702     _cairo_array_init (&res->alphas, sizeof (double));
703     _cairo_array_init (&res->smasks, sizeof (cairo_pdf_resource_t));
704     _cairo_array_init (&res->patterns, sizeof (cairo_pdf_resource_t));
705     _cairo_array_init (&res->xobjects, sizeof (cairo_pdf_resource_t));
706     _cairo_array_init (&res->fonts, sizeof (cairo_pdf_font_t));
707 }
708 
709 static void
_cairo_pdf_group_resources_fini(cairo_pdf_group_resources_t * res)710 _cairo_pdf_group_resources_fini (cairo_pdf_group_resources_t *res)
711 {
712     _cairo_array_fini (&res->alphas);
713     _cairo_array_fini (&res->smasks);
714     _cairo_array_fini (&res->patterns);
715     _cairo_array_fini (&res->xobjects);
716     _cairo_array_fini (&res->fonts);
717 }
718 
719 static void
_cairo_pdf_group_resources_clear(cairo_pdf_group_resources_t * res)720 _cairo_pdf_group_resources_clear (cairo_pdf_group_resources_t *res)
721 {
722     int i;
723 
724     for (i = 0; i < CAIRO_NUM_OPERATORS; i++)
725 	res->operators[i] = FALSE;
726 
727     _cairo_array_truncate (&res->alphas, 0);
728     _cairo_array_truncate (&res->smasks, 0);
729     _cairo_array_truncate (&res->patterns, 0);
730     _cairo_array_truncate (&res->xobjects, 0);
731     _cairo_array_truncate (&res->fonts, 0);
732 }
733 
734 static void
_cairo_pdf_surface_add_operator(cairo_pdf_surface_t * surface,cairo_operator_t op)735 _cairo_pdf_surface_add_operator (cairo_pdf_surface_t *surface,
736 				 cairo_operator_t     op)
737 {
738     cairo_pdf_group_resources_t *res = &surface->resources;
739 
740     res->operators[op] = TRUE;
741 }
742 
743 static cairo_status_t
_cairo_pdf_surface_add_alpha(cairo_pdf_surface_t * surface,double alpha,int * index)744 _cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
745 			      double               alpha,
746 			      int                 *index)
747 {
748     int num_alphas, i;
749     double other;
750     cairo_status_t status;
751     cairo_pdf_group_resources_t *res = &surface->resources;
752 
753     num_alphas = _cairo_array_num_elements (&res->alphas);
754     for (i = 0; i < num_alphas; i++) {
755 	_cairo_array_copy_element (&res->alphas, i, &other);
756 	if (alpha == other) {
757 	    *index = i;
758 	    return CAIRO_STATUS_SUCCESS;
759 	}
760     }
761 
762     status = _cairo_array_append (&res->alphas, &alpha);
763     if (unlikely (status))
764 	return status;
765 
766     *index = _cairo_array_num_elements (&res->alphas) - 1;
767 
768     return CAIRO_STATUS_SUCCESS;
769 }
770 
771 static cairo_status_t
_cairo_pdf_surface_add_smask(cairo_pdf_surface_t * surface,cairo_pdf_resource_t smask)772 _cairo_pdf_surface_add_smask (cairo_pdf_surface_t  *surface,
773 			      cairo_pdf_resource_t  smask)
774 {
775     return _cairo_array_append (&(surface->resources.smasks), &smask);
776 }
777 
778 static cairo_status_t
_cairo_pdf_surface_add_pattern(cairo_pdf_surface_t * surface,cairo_pdf_resource_t pattern)779 _cairo_pdf_surface_add_pattern (cairo_pdf_surface_t  *surface,
780 				cairo_pdf_resource_t  pattern)
781 {
782     return _cairo_array_append (&(surface->resources.patterns), &pattern);
783 }
784 
785 static cairo_status_t
_cairo_pdf_surface_add_xobject(cairo_pdf_surface_t * surface,cairo_pdf_resource_t xobject)786 _cairo_pdf_surface_add_xobject (cairo_pdf_surface_t  *surface,
787 				cairo_pdf_resource_t  xobject)
788 {
789     return _cairo_array_append (&(surface->resources.xobjects), &xobject);
790 }
791 
792 static cairo_status_t
_cairo_pdf_surface_add_font(unsigned int font_id,unsigned int subset_id,void * closure)793 _cairo_pdf_surface_add_font (unsigned int        font_id,
794 			     unsigned int        subset_id,
795 			     void		*closure)
796 {
797     cairo_pdf_surface_t *surface = closure;
798     cairo_pdf_font_t font;
799     int num_fonts, i;
800     cairo_status_t status;
801     cairo_pdf_group_resources_t *res = &surface->resources;
802 
803     num_fonts = _cairo_array_num_elements (&res->fonts);
804     for (i = 0; i < num_fonts; i++) {
805 	_cairo_array_copy_element (&res->fonts, i, &font);
806 	if (font.font_id == font_id &&
807 	    font.subset_id == subset_id)
808 	    return CAIRO_STATUS_SUCCESS;
809     }
810 
811     num_fonts = _cairo_array_num_elements (&surface->fonts);
812     for (i = 0; i < num_fonts; i++) {
813 	_cairo_array_copy_element (&surface->fonts, i, &font);
814 	if (font.font_id == font_id &&
815 	    font.subset_id == subset_id)
816 	    return _cairo_array_append (&res->fonts, &font);
817     }
818 
819     font.font_id = font_id;
820     font.subset_id = subset_id;
821     font.subset_resource = _cairo_pdf_surface_new_object (surface);
822     if (font.subset_resource.id == 0)
823 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
824 
825     status = _cairo_array_append (&surface->fonts, &font);
826     if (unlikely (status))
827 	return status;
828 
829     return _cairo_array_append (&res->fonts, &font);
830 }
831 
832 static cairo_pdf_resource_t
_cairo_pdf_surface_get_font_resource(cairo_pdf_surface_t * surface,unsigned int font_id,unsigned int subset_id)833 _cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface,
834 				      unsigned int         font_id,
835 				      unsigned int         subset_id)
836 {
837     cairo_pdf_font_t font;
838     int num_fonts, i;
839 
840     num_fonts = _cairo_array_num_elements (&surface->fonts);
841     for (i = 0; i < num_fonts; i++) {
842 	_cairo_array_copy_element (&surface->fonts, i, &font);
843 	if (font.font_id == font_id && font.subset_id == subset_id)
844 	    return font.subset_resource;
845     }
846 
847     font.subset_resource.id = 0;
848     return font.subset_resource;
849 }
850 
851 static const char *
_cairo_operator_to_pdf_blend_mode(cairo_operator_t op)852 _cairo_operator_to_pdf_blend_mode (cairo_operator_t op)
853 {
854     switch (op) {
855     /* The extend blend mode operators */
856     case CAIRO_OPERATOR_MULTIPLY:       return "Multiply";
857     case CAIRO_OPERATOR_SCREEN:         return "Screen";
858     case CAIRO_OPERATOR_OVERLAY:        return "Overlay";
859     case CAIRO_OPERATOR_DARKEN:         return "Darken";
860     case CAIRO_OPERATOR_LIGHTEN:        return "Lighten";
861     case CAIRO_OPERATOR_COLOR_DODGE:    return "ColorDodge";
862     case CAIRO_OPERATOR_COLOR_BURN:     return "ColorBurn";
863     case CAIRO_OPERATOR_HARD_LIGHT:     return "HardLight";
864     case CAIRO_OPERATOR_SOFT_LIGHT:     return "SoftLight";
865     case CAIRO_OPERATOR_DIFFERENCE:     return "Difference";
866     case CAIRO_OPERATOR_EXCLUSION:      return "Exclusion";
867     case CAIRO_OPERATOR_HSL_HUE:        return "Hue";
868     case CAIRO_OPERATOR_HSL_SATURATION: return "Saturation";
869     case CAIRO_OPERATOR_HSL_COLOR:      return "Color";
870     case CAIRO_OPERATOR_HSL_LUMINOSITY: return "Luminosity";
871 
872     default:
873     /* The original Porter-Duff set */
874     case CAIRO_OPERATOR_CLEAR:
875     case CAIRO_OPERATOR_SOURCE:
876     case CAIRO_OPERATOR_OVER:
877     case CAIRO_OPERATOR_IN:
878     case CAIRO_OPERATOR_OUT:
879     case CAIRO_OPERATOR_ATOP:
880     case CAIRO_OPERATOR_DEST:
881     case CAIRO_OPERATOR_DEST_OVER:
882     case CAIRO_OPERATOR_DEST_IN:
883     case CAIRO_OPERATOR_DEST_OUT:
884     case CAIRO_OPERATOR_DEST_ATOP:
885     case CAIRO_OPERATOR_XOR:
886     case CAIRO_OPERATOR_ADD:
887     case CAIRO_OPERATOR_SATURATE:
888 	return "Normal";
889     }
890 }
891 
892 static void
_cairo_pdf_surface_emit_group_resources(cairo_pdf_surface_t * surface,cairo_pdf_group_resources_t * res)893 _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t         *surface,
894 					 cairo_pdf_group_resources_t *res)
895 {
896     int num_alphas, num_smasks, num_resources, i;
897     double alpha;
898     cairo_pdf_resource_t *smask, *pattern, *xobject;
899     cairo_pdf_font_t *font;
900 
901     _cairo_output_stream_printf (surface->output, "<<\n");
902 
903     num_alphas = _cairo_array_num_elements (&res->alphas);
904     num_smasks = _cairo_array_num_elements (&res->smasks);
905     if (num_alphas > 0 || num_smasks > 0) {
906 	_cairo_output_stream_printf (surface->output,
907 				     "   /ExtGState <<\n");
908 
909 	for (i = 0; i < CAIRO_NUM_OPERATORS; i++) {
910 	    if (res->operators[i]) {
911 		_cairo_output_stream_printf (surface->output,
912 					     "      /b%d << /BM /%s >>\n",
913 					     i, _cairo_operator_to_pdf_blend_mode(i));
914 	    }
915 	}
916 
917 	for (i = 0; i < num_alphas; i++) {
918 	    _cairo_array_copy_element (&res->alphas, i, &alpha);
919 	    _cairo_output_stream_printf (surface->output,
920 					 "      /a%d << /CA %f /ca %f >>\n",
921 					 i, alpha, alpha);
922 	}
923 
924 	for (i = 0; i < num_smasks; i++) {
925 	    smask = _cairo_array_index (&res->smasks, i);
926 	    _cairo_output_stream_printf (surface->output,
927 					 "      /s%d %d 0 R\n",
928 					 smask->id, smask->id);
929 	}
930 
931 	_cairo_output_stream_printf (surface->output,
932 				     "   >>\n");
933     }
934 
935     num_resources = _cairo_array_num_elements (&res->patterns);
936     if (num_resources > 0) {
937 	_cairo_output_stream_printf (surface->output,
938 				     "   /Pattern <<");
939 	for (i = 0; i < num_resources; i++) {
940 	    pattern = _cairo_array_index (&res->patterns, i);
941 	    _cairo_output_stream_printf (surface->output,
942 					 " /p%d %d 0 R",
943 					 pattern->id, pattern->id);
944 	}
945 
946 	_cairo_output_stream_printf (surface->output,
947 				     " >>\n");
948     }
949 
950     num_resources = _cairo_array_num_elements (&res->xobjects);
951     if (num_resources > 0) {
952 	_cairo_output_stream_printf (surface->output,
953 				     "   /XObject <<");
954 
955 	for (i = 0; i < num_resources; i++) {
956 	    xobject = _cairo_array_index (&res->xobjects, i);
957 	    _cairo_output_stream_printf (surface->output,
958 					 " /x%d %d 0 R",
959 					 xobject->id, xobject->id);
960 	}
961 
962 	_cairo_output_stream_printf (surface->output,
963 				     " >>\n");
964     }
965 
966     num_resources = _cairo_array_num_elements (&res->fonts);
967     if (num_resources > 0) {
968 	_cairo_output_stream_printf (surface->output,"   /Font <<\n");
969 	for (i = 0; i < num_resources; i++) {
970 	    font = _cairo_array_index (&res->fonts, i);
971 	    _cairo_output_stream_printf (surface->output,
972 					 "      /f-%d-%d %d 0 R\n",
973 					 font->font_id,
974 					 font->subset_id,
975 					 font->subset_resource.id);
976 	}
977 	_cairo_output_stream_printf (surface->output, "   >>\n");
978     }
979 
980     _cairo_output_stream_printf (surface->output,
981 				 ">>\n");
982 }
983 
984 static cairo_pdf_smask_group_t *
_cairo_pdf_surface_create_smask_group(cairo_pdf_surface_t * surface)985 _cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t	*surface)
986 {
987     cairo_pdf_smask_group_t	*group;
988 
989     group = calloc (1, sizeof (cairo_pdf_smask_group_t));
990     if (unlikely (group == NULL)) {
991 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
992 	return NULL;
993     }
994 
995     group->group_res = _cairo_pdf_surface_new_object (surface);
996     if (group->group_res.id == 0) {
997 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
998 	free (group);
999 	return NULL;
1000     }
1001     group->width = surface->width;
1002     group->height = surface->height;
1003 
1004     return group;
1005 }
1006 
1007 static void
_cairo_pdf_smask_group_destroy(cairo_pdf_smask_group_t * group)1008 _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
1009 {
1010     if (group->operation == PDF_FILL ||	group->operation == PDF_STROKE)
1011 	_cairo_path_fixed_fini (&group->path);
1012     if (group->source)
1013 	cairo_pattern_destroy (group->source);
1014     if (group->mask)
1015 	cairo_pattern_destroy (group->mask);
1016     if (group->utf8)
1017 	free (group->utf8);
1018     if (group->glyphs)
1019 	free (group->glyphs);
1020     if (group->clusters)
1021 	free (group->clusters);
1022     if (group->scaled_font)
1023 	cairo_scaled_font_destroy (group->scaled_font);
1024     free (group);
1025 }
1026 
1027 static cairo_status_t
_cairo_pdf_surface_add_smask_group(cairo_pdf_surface_t * surface,cairo_pdf_smask_group_t * group)1028 _cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t     *surface,
1029 				    cairo_pdf_smask_group_t *group)
1030 {
1031     return _cairo_array_append (&surface->smask_groups, &group);
1032 }
1033 
1034 static cairo_bool_t
_cairo_pdf_source_surface_equal(const void * key_a,const void * key_b)1035 _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b)
1036 {
1037     const cairo_pdf_source_surface_entry_t *a = key_a;
1038     const cairo_pdf_source_surface_entry_t *b = key_b;
1039 
1040     return (a->id == b->id) && (a->interpolate == b->interpolate);
1041 }
1042 
1043 static void
_cairo_pdf_source_surface_init_key(cairo_pdf_source_surface_entry_t * key)1044 _cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key)
1045 {
1046     key->base.hash = key->id;
1047 }
1048 
1049 static cairo_int_status_t
_get_jpx_image_info(cairo_surface_t * source,cairo_image_info_t * info,const unsigned char ** mime_data,unsigned long * mime_data_length)1050 _get_jpx_image_info (cairo_surface_t		 *source,
1051 		     cairo_image_info_t		*info,
1052 		     const unsigned char	**mime_data,
1053 		     unsigned long		 *mime_data_length)
1054 {
1055     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
1056 				 mime_data, mime_data_length);
1057     if (*mime_data == NULL)
1058 	return CAIRO_INT_STATUS_UNSUPPORTED;
1059 
1060     return _cairo_image_info_get_jpx_info (info, *mime_data, *mime_data_length);
1061 }
1062 
1063 static cairo_int_status_t
_get_jpeg_image_info(cairo_surface_t * source,cairo_image_info_t * info,const unsigned char ** mime_data,unsigned long * mime_data_length)1064 _get_jpeg_image_info (cairo_surface_t		 *source,
1065 		      cairo_image_info_t	 *info,
1066 		      const unsigned char	**mime_data,
1067 		      unsigned long		 *mime_data_length)
1068 {
1069     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
1070 				 mime_data, mime_data_length);
1071     if (*mime_data == NULL)
1072 	return CAIRO_INT_STATUS_UNSUPPORTED;
1073 
1074     return _cairo_image_info_get_jpeg_info (info, *mime_data, *mime_data_length);
1075 }
1076 
1077 static cairo_status_t
_get_source_surface_size(cairo_surface_t * source,int * width,int * height)1078 _get_source_surface_size (cairo_surface_t         *source,
1079 			  int                     *width,
1080 			  int                     *height)
1081 {
1082     cairo_status_t status;
1083     cairo_rectangle_int_t extents;
1084     cairo_image_info_t info;
1085     const unsigned char *mime_data;
1086     unsigned long mime_data_length;
1087 
1088     if (source->type == CAIRO_SURFACE_TYPE_RECORDING) {
1089 	if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1090 	     cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
1091 
1092 	    *width  = sub->extents.width;
1093 	    *height = sub->extents.height;
1094 
1095 	} else {
1096 	    cairo_recording_surface_t *recording_surface = (cairo_recording_surface_t *) source;
1097 	    cairo_box_t bbox;
1098 
1099 	    status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL);
1100 	    if (unlikely (status))
1101 		return status;
1102 
1103 	    _cairo_box_round_to_rectangle (&bbox, &extents);
1104 
1105 	    *width = extents.width;
1106 	    *height = extents.height;
1107 	}
1108 	return CAIRO_STATUS_SUCCESS;
1109     }
1110 
1111     status = _get_jpx_image_info (source, &info, &mime_data, &mime_data_length);
1112     if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
1113 	*width = info.width;
1114 	*height = info.height;
1115 	return status;
1116     }
1117 
1118     status = _get_jpeg_image_info (source, &info, &mime_data, &mime_data_length);
1119     if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
1120 	*width = info.width;
1121 	*height = info.height;
1122 	return status;
1123     }
1124 
1125     if (! _cairo_surface_get_extents (source, &extents))
1126 	return CAIRO_INT_STATUS_UNSUPPORTED;
1127 
1128     *width = extents.width;
1129     *height = extents.height;
1130 
1131     return CAIRO_STATUS_SUCCESS;
1132 }
1133 
1134 static cairo_status_t
_cairo_pdf_surface_add_source_surface(cairo_pdf_surface_t * surface,cairo_surface_t * source,cairo_filter_t filter,cairo_pdf_resource_t * surface_res,int * width,int * height)1135 _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t	*surface,
1136 				       cairo_surface_t		*source,
1137 				       cairo_filter_t		 filter,
1138 				       cairo_pdf_resource_t	*surface_res,
1139 				       int                      *width,
1140 				       int                      *height)
1141 {
1142     cairo_pdf_source_surface_t src_surface;
1143     cairo_pdf_source_surface_entry_t surface_key;
1144     cairo_pdf_source_surface_entry_t *surface_entry;
1145     cairo_status_t status;
1146     cairo_bool_t interpolate;
1147 
1148     switch (filter) {
1149     default:
1150     case CAIRO_FILTER_GOOD:
1151     case CAIRO_FILTER_BEST:
1152     case CAIRO_FILTER_BILINEAR:
1153 	interpolate = TRUE;
1154 	break;
1155     case CAIRO_FILTER_FAST:
1156     case CAIRO_FILTER_NEAREST:
1157     case CAIRO_FILTER_GAUSSIAN:
1158 	interpolate = FALSE;
1159 	break;
1160     }
1161 
1162     surface_key.id  = source->unique_id;
1163     surface_key.interpolate = interpolate;
1164     _cairo_pdf_source_surface_init_key (&surface_key);
1165     surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base);
1166     if (surface_entry) {
1167 	*surface_res = surface_entry->surface_res;
1168 	*width = surface_entry->width;
1169 	*height = surface_entry->height;
1170 
1171 	return CAIRO_STATUS_SUCCESS;
1172     }
1173 
1174     surface_entry = malloc (sizeof (cairo_pdf_source_surface_entry_t));
1175     if (surface_entry == NULL)
1176 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1177 
1178     surface_entry->id = surface_key.id;
1179     surface_entry->interpolate = interpolate;
1180     _cairo_pdf_source_surface_init_key (surface_entry);
1181 
1182     src_surface.hash_entry = surface_entry;
1183     src_surface.surface = cairo_surface_reference (source);
1184     surface_entry->surface_res = _cairo_pdf_surface_new_object (surface);
1185     if (surface_entry->surface_res.id == 0) {
1186 	cairo_surface_destroy (source);
1187 	free (surface_entry);
1188 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1189     }
1190 
1191     status = _get_source_surface_size (source, &surface_entry->width,
1192 				       &surface_entry->height);
1193 
1194     status = _cairo_array_append (&surface->page_surfaces, &src_surface);
1195     if (unlikely (status)) {
1196 	cairo_surface_destroy (source);
1197 	free (surface_entry);
1198 	return status;
1199     }
1200 
1201     status = _cairo_hash_table_insert (surface->all_surfaces,
1202 				       &surface_entry->base);
1203 
1204     *surface_res = surface_entry->surface_res;
1205     *width = surface_entry->width;
1206     *height = surface_entry->height;
1207 
1208     return status;
1209 }
1210 
1211 static cairo_bool_t
_gradient_stops_are_opaque(const cairo_gradient_pattern_t * gradient)1212 _gradient_stops_are_opaque (const cairo_gradient_pattern_t *gradient)
1213 {
1214     unsigned int i;
1215 
1216     for (i = 0; i < gradient->n_stops; i++)
1217 	if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
1218 	    return FALSE;
1219 
1220     return TRUE;
1221 }
1222 
1223 static cairo_status_t
_cairo_pdf_surface_add_pdf_pattern(cairo_pdf_surface_t * surface,const cairo_pattern_t * pattern,const cairo_rectangle_int_t * extents,cairo_pdf_resource_t * pattern_res,cairo_pdf_resource_t * gstate_res)1224 _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
1225 				    const cairo_pattern_t	*pattern,
1226 				    const cairo_rectangle_int_t	*extents,
1227 				    cairo_pdf_resource_t	*pattern_res,
1228 				    cairo_pdf_resource_t	*gstate_res)
1229 {
1230     cairo_pdf_pattern_t pdf_pattern;
1231     cairo_status_t status;
1232 
1233     /* Solid colors are emitted into the content stream */
1234     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
1235 	pattern_res->id = 0;
1236 	gstate_res->id = 0;
1237 	return CAIRO_STATUS_SUCCESS;
1238     }
1239 
1240     status = _cairo_pattern_create_copy (&pdf_pattern.pattern, pattern);
1241     if (unlikely (status))
1242 	return status;
1243 
1244     pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface);
1245     if (pdf_pattern.pattern_res.id == 0) {
1246 	cairo_pattern_destroy (pdf_pattern.pattern);
1247 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1248     }
1249 
1250     pdf_pattern.gstate_res.id = 0;
1251 
1252     /* gradient patterns require an smask object to implement transparency */
1253     if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
1254         pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
1255     {
1256 	cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
1257 	if (! _gradient_stops_are_opaque (gradient)) {
1258             pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface);
1259 	    if (pdf_pattern.gstate_res.id == 0) {
1260 		cairo_pattern_destroy (pdf_pattern.pattern);
1261 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1262 	    }
1263         }
1264     }
1265 
1266     pdf_pattern.width  = surface->width;
1267     pdf_pattern.height = surface->height;
1268     if (extents != NULL) {
1269 	pdf_pattern.extents = *extents;
1270     } else {
1271 	pdf_pattern.extents.x = 0;
1272 	pdf_pattern.extents.y = 0;
1273 	pdf_pattern.extents.width  = surface->width;
1274 	pdf_pattern.extents.height = surface->height;
1275     }
1276 
1277     *pattern_res = pdf_pattern.pattern_res;
1278     *gstate_res = pdf_pattern.gstate_res;
1279 
1280     status = _cairo_array_append (&surface->page_patterns, &pdf_pattern);
1281     if (unlikely (status)) {
1282 	cairo_pattern_destroy (pdf_pattern.pattern);
1283 	return status;
1284     }
1285 
1286     return CAIRO_STATUS_SUCCESS;
1287 }
1288 
1289 static cairo_status_t
_cairo_pdf_surface_open_stream(cairo_pdf_surface_t * surface,cairo_pdf_resource_t * resource,cairo_bool_t compressed,const char * fmt,...)1290 _cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
1291 				cairo_pdf_resource_t    *resource,
1292 				cairo_bool_t             compressed,
1293 				const char		*fmt,
1294 				...)
1295 {
1296     va_list ap;
1297     cairo_pdf_resource_t self, length;
1298     cairo_output_stream_t *output = NULL;
1299 
1300     if (resource) {
1301 	self = *resource;
1302 	_cairo_pdf_surface_update_object (surface, self);
1303     } else {
1304 	self = _cairo_pdf_surface_new_object (surface);
1305 	if (self.id == 0)
1306 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1307     }
1308 
1309     length = _cairo_pdf_surface_new_object (surface);
1310     if (length.id == 0)
1311 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1312 
1313     if (compressed) {
1314 	output = _cairo_deflate_stream_create (surface->output);
1315 	if (_cairo_output_stream_get_status (output))
1316 	    return _cairo_output_stream_destroy (output);
1317     }
1318 
1319     surface->pdf_stream.active = TRUE;
1320     surface->pdf_stream.self = self;
1321     surface->pdf_stream.length = length;
1322     surface->pdf_stream.compressed = compressed;
1323     surface->current_pattern_is_solid_color = FALSE;
1324     surface->current_operator = CAIRO_OPERATOR_OVER;
1325     _cairo_pdf_operators_reset (&surface->pdf_operators);
1326 
1327     _cairo_output_stream_printf (surface->output,
1328 				 "%d 0 obj\n"
1329 				 "<< /Length %d 0 R\n",
1330 				 surface->pdf_stream.self.id,
1331 				 surface->pdf_stream.length.id);
1332     if (compressed)
1333 	_cairo_output_stream_printf (surface->output,
1334 				     "   /Filter /FlateDecode\n");
1335 
1336     if (fmt != NULL) {
1337 	va_start (ap, fmt);
1338 	_cairo_output_stream_vprintf (surface->output, fmt, ap);
1339 	va_end (ap);
1340     }
1341 
1342     _cairo_output_stream_printf (surface->output,
1343 				 ">>\n"
1344 				 "stream\n");
1345 
1346     surface->pdf_stream.start_offset = _cairo_output_stream_get_position (surface->output);
1347 
1348     if (compressed) {
1349 	assert (surface->pdf_stream.old_output == NULL);
1350         surface->pdf_stream.old_output = surface->output;
1351         surface->output = output;
1352 	_cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1353     }
1354 
1355     return _cairo_output_stream_get_status (surface->output);
1356 }
1357 
1358 static cairo_status_t
_cairo_pdf_surface_close_stream(cairo_pdf_surface_t * surface)1359 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
1360 {
1361     cairo_status_t status;
1362     long length;
1363 
1364     if (! surface->pdf_stream.active)
1365 	return CAIRO_STATUS_SUCCESS;
1366 
1367     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1368 
1369     if (surface->pdf_stream.compressed) {
1370 	cairo_status_t status2;
1371 
1372 	status2 = _cairo_output_stream_destroy (surface->output);
1373 	if (likely (status == CAIRO_STATUS_SUCCESS))
1374 	    status = status2;
1375 
1376 	surface->output = surface->pdf_stream.old_output;
1377 	_cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1378 	surface->pdf_stream.old_output = NULL;
1379     }
1380 
1381     length = _cairo_output_stream_get_position (surface->output) -
1382 	surface->pdf_stream.start_offset;
1383     _cairo_output_stream_printf (surface->output,
1384 				 "\n"
1385 				 "endstream\n"
1386 				 "endobj\n");
1387 
1388     _cairo_pdf_surface_update_object (surface,
1389 				      surface->pdf_stream.length);
1390     _cairo_output_stream_printf (surface->output,
1391 				 "%d 0 obj\n"
1392 				 "   %ld\n"
1393 				 "endobj\n",
1394 				 surface->pdf_stream.length.id,
1395 				 length);
1396 
1397     surface->pdf_stream.active = FALSE;
1398 
1399     if (likely (status == CAIRO_STATUS_SUCCESS))
1400 	status = _cairo_output_stream_get_status (surface->output);
1401 
1402     return status;
1403 }
1404 
1405 static void
_cairo_pdf_surface_write_memory_stream(cairo_pdf_surface_t * surface,cairo_output_stream_t * mem_stream,cairo_pdf_resource_t resource,cairo_pdf_group_resources_t * resources,cairo_bool_t is_knockout_group)1406 _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t         *surface,
1407 					cairo_output_stream_t       *mem_stream,
1408 					cairo_pdf_resource_t         resource,
1409 					cairo_pdf_group_resources_t *resources,
1410 					cairo_bool_t                 is_knockout_group)
1411 {
1412     _cairo_pdf_surface_update_object (surface, resource);
1413 
1414     _cairo_output_stream_printf (surface->output,
1415 				 "%d 0 obj\n"
1416 				 "<< /Type /XObject\n"
1417 				 "   /Length %d\n",
1418 				 resource.id,
1419 				 _cairo_memory_stream_length (mem_stream));
1420 
1421     if (surface->compress_content) {
1422 	_cairo_output_stream_printf (surface->output,
1423 				     "   /Filter /FlateDecode\n");
1424     }
1425 
1426     _cairo_output_stream_printf (surface->output,
1427 				 "   /Subtype /Form\n"
1428 				 "   /BBox [ 0 0 %f %f ]\n"
1429 				 "   /Group <<\n"
1430 				 "      /Type /Group\n"
1431 				 "      /S /Transparency\n"
1432 				 "      /CS /DeviceRGB\n",
1433 				 surface->width,
1434 				 surface->height);
1435 
1436     if (is_knockout_group)
1437         _cairo_output_stream_printf (surface->output,
1438                                      "      /K true\n");
1439 
1440     _cairo_output_stream_printf (surface->output,
1441 				 "   >>\n"
1442 				 "   /Resources\n");
1443     _cairo_pdf_surface_emit_group_resources (surface, resources);
1444     _cairo_output_stream_printf (surface->output,
1445 				 ">>\n"
1446 				 "stream\n");
1447     _cairo_memory_stream_copy (mem_stream, surface->output);
1448     _cairo_output_stream_printf (surface->output,
1449 				 "endstream\n"
1450 				 "endobj\n");
1451 }
1452 
1453 static cairo_status_t
_cairo_pdf_surface_open_group(cairo_pdf_surface_t * surface,cairo_pdf_resource_t * resource)1454 _cairo_pdf_surface_open_group (cairo_pdf_surface_t  *surface,
1455 			       cairo_pdf_resource_t *resource)
1456 {
1457     cairo_status_t status;
1458 
1459     assert (surface->pdf_stream.active == FALSE);
1460     assert (surface->group_stream.active == FALSE);
1461 
1462     surface->group_stream.active = TRUE;
1463     surface->current_pattern_is_solid_color = FALSE;
1464     surface->current_operator = CAIRO_OPERATOR_OVER;
1465     _cairo_pdf_operators_reset (&surface->pdf_operators);
1466 
1467     surface->group_stream.mem_stream = _cairo_memory_stream_create ();
1468 
1469     if (surface->compress_content) {
1470 	surface->group_stream.stream =
1471 	    _cairo_deflate_stream_create (surface->group_stream.mem_stream);
1472     } else {
1473 	surface->group_stream.stream = surface->group_stream.mem_stream;
1474     }
1475     status = _cairo_output_stream_get_status (surface->group_stream.stream);
1476 
1477     surface->group_stream.old_output = surface->output;
1478     surface->output = surface->group_stream.stream;
1479     _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1480     _cairo_pdf_group_resources_clear (&surface->resources);
1481 
1482     if (resource) {
1483 	surface->group_stream.resource = *resource;
1484     } else {
1485 	surface->group_stream.resource = _cairo_pdf_surface_new_object (surface);
1486 	if (surface->group_stream.resource.id == 0)
1487 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1488     }
1489     surface->group_stream.is_knockout = FALSE;
1490 
1491     return status;
1492 }
1493 
1494 static cairo_status_t
_cairo_pdf_surface_open_knockout_group(cairo_pdf_surface_t * surface)1495 _cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t  *surface)
1496 {
1497     cairo_status_t status;
1498 
1499     status = _cairo_pdf_surface_open_group (surface, NULL);
1500     if (unlikely (status))
1501 	return status;
1502 
1503     surface->group_stream.is_knockout = TRUE;
1504 
1505     return CAIRO_STATUS_SUCCESS;
1506 }
1507 
1508 static cairo_status_t
_cairo_pdf_surface_close_group(cairo_pdf_surface_t * surface,cairo_pdf_resource_t * group)1509 _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
1510 				cairo_pdf_resource_t *group)
1511 {
1512     cairo_status_t status = CAIRO_STATUS_SUCCESS, status2;
1513 
1514     assert (surface->pdf_stream.active == FALSE);
1515     assert (surface->group_stream.active == TRUE);
1516 
1517     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1518     if (unlikely (status))
1519 	return status;
1520 
1521     if (surface->compress_content) {
1522 	status = _cairo_output_stream_destroy (surface->group_stream.stream);
1523 	surface->group_stream.stream = NULL;
1524 
1525 	_cairo_output_stream_printf (surface->group_stream.mem_stream,
1526 				     "\n");
1527     }
1528     surface->output = surface->group_stream.old_output;
1529     _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
1530     surface->group_stream.active = FALSE;
1531     _cairo_pdf_surface_write_memory_stream (surface,
1532 					    surface->group_stream.mem_stream,
1533 					    surface->group_stream.resource,
1534 					    &surface->resources,
1535 					    surface->group_stream.is_knockout);
1536     if (group)
1537 	*group = surface->group_stream.resource;
1538 
1539     status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
1540     if (status == CAIRO_STATUS_SUCCESS)
1541 	status = status2;
1542 
1543     surface->group_stream.mem_stream = NULL;
1544     surface->group_stream.stream = NULL;
1545 
1546     return status;
1547 }
1548 
1549 static cairo_status_t
_cairo_pdf_surface_open_content_stream(cairo_pdf_surface_t * surface,cairo_pdf_resource_t * resource,cairo_bool_t is_form)1550 _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t  *surface,
1551 					cairo_pdf_resource_t *resource,
1552 					cairo_bool_t          is_form)
1553 {
1554     cairo_status_t status;
1555 
1556     assert (surface->pdf_stream.active == FALSE);
1557     assert (surface->group_stream.active == FALSE);
1558 
1559     surface->content_resources = _cairo_pdf_surface_new_object (surface);
1560     if (surface->content_resources.id == 0)
1561 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1562 
1563     if (is_form) {
1564 	status =
1565 	    _cairo_pdf_surface_open_stream (surface,
1566 					    resource,
1567 					    surface->compress_content,
1568 					    "   /Type /XObject\n"
1569 					    "   /Subtype /Form\n"
1570 					    "   /BBox [ 0 0 %f %f ]\n"
1571 					    "   /Group <<\n"
1572 					    "      /Type /Group\n"
1573 					    "      /S /Transparency\n"
1574 					    "      /CS /DeviceRGB\n"
1575 					    "   >>\n"
1576 					    "   /Resources %d 0 R\n",
1577 					    surface->width,
1578 					    surface->height,
1579 					    surface->content_resources.id);
1580     } else {
1581 	status =
1582 	    _cairo_pdf_surface_open_stream (surface,
1583 					    resource,
1584 					    surface->compress_content,
1585 					    NULL);
1586     }
1587     if (unlikely (status))
1588 	return status;
1589 
1590     surface->content = surface->pdf_stream.self;
1591 
1592     _cairo_output_stream_printf (surface->output, "q\n");
1593 
1594     return _cairo_output_stream_get_status (surface->output);
1595 }
1596 
1597 static cairo_status_t
_cairo_pdf_surface_close_content_stream(cairo_pdf_surface_t * surface)1598 _cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
1599 {
1600     cairo_status_t status;
1601 
1602     assert (surface->pdf_stream.active == TRUE);
1603     assert (surface->group_stream.active == FALSE);
1604 
1605     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1606     if (unlikely (status))
1607 	return status;
1608 
1609     _cairo_output_stream_printf (surface->output, "Q\n");
1610     status = _cairo_pdf_surface_close_stream (surface);
1611     if (unlikely (status))
1612 	return status;
1613 
1614     _cairo_pdf_surface_update_object (surface, surface->content_resources);
1615     _cairo_output_stream_printf (surface->output,
1616 				 "%d 0 obj\n",
1617 				 surface->content_resources.id);
1618     _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
1619     _cairo_output_stream_printf (surface->output,
1620 				 "endobj\n");
1621 
1622     return _cairo_output_stream_get_status (surface->output);
1623 }
1624 
1625 static void
_cairo_pdf_source_surface_entry_pluck(void * entry,void * closure)1626 _cairo_pdf_source_surface_entry_pluck (void *entry, void *closure)
1627 {
1628     cairo_pdf_source_surface_entry_t *surface_entry = entry;
1629     cairo_hash_table_t *patterns = closure;
1630 
1631     _cairo_hash_table_remove (patterns, &surface_entry->base);
1632     free (surface_entry);
1633 }
1634 
1635 static cairo_status_t
_cairo_pdf_surface_finish(void * abstract_surface)1636 _cairo_pdf_surface_finish (void *abstract_surface)
1637 {
1638     cairo_pdf_surface_t *surface = abstract_surface;
1639     long offset;
1640     cairo_pdf_resource_t info, catalog;
1641     cairo_status_t status, status2;
1642 
1643     status = surface->base.status;
1644     if (status == CAIRO_STATUS_SUCCESS)
1645 	status = _cairo_pdf_surface_emit_font_subsets (surface);
1646 
1647     _cairo_pdf_surface_write_pages (surface);
1648 
1649     info = _cairo_pdf_surface_write_info (surface);
1650     if (info.id == 0 && status == CAIRO_STATUS_SUCCESS)
1651 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1652 
1653     catalog = _cairo_pdf_surface_write_catalog (surface);
1654     if (catalog.id == 0 && status == CAIRO_STATUS_SUCCESS)
1655 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1656 
1657     offset = _cairo_pdf_surface_write_xref (surface);
1658 
1659     _cairo_output_stream_printf (surface->output,
1660 				 "trailer\n"
1661 				 "<< /Size %d\n"
1662 				 "   /Root %d 0 R\n"
1663 				 "   /Info %d 0 R\n"
1664 				 ">>\n",
1665 				 surface->next_available_resource.id,
1666 				 catalog.id,
1667 				 info.id);
1668 
1669     _cairo_output_stream_printf (surface->output,
1670 				 "startxref\n"
1671 				 "%ld\n"
1672 				 "%%%%EOF\n",
1673 				 offset);
1674 
1675     /* pdf_operators has already been flushed when the last stream was
1676      * closed so we should never be writing anything here - however,
1677      * the stream may itself be in an error state. */
1678     status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
1679     if (status == CAIRO_STATUS_SUCCESS)
1680 	status = status2;
1681 
1682     /* close any active streams still open due to fatal errors */
1683     status2 = _cairo_pdf_surface_close_stream (surface);
1684     if (status == CAIRO_STATUS_SUCCESS)
1685 	status = status2;
1686 
1687     if (surface->group_stream.stream != NULL) {
1688 	status2 = _cairo_output_stream_destroy (surface->group_stream.stream);
1689 	if (status == CAIRO_STATUS_SUCCESS)
1690 	    status = status2;
1691     }
1692     if (surface->group_stream.mem_stream != NULL) {
1693 	status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
1694 	if (status == CAIRO_STATUS_SUCCESS)
1695 	    status = status2;
1696     }
1697     if (surface->pdf_stream.active)
1698 	surface->output = surface->pdf_stream.old_output;
1699     if (surface->group_stream.active)
1700 	surface->output = surface->group_stream.old_output;
1701 
1702     /* and finish the pdf surface */
1703     status2 = _cairo_output_stream_destroy (surface->output);
1704     if (status == CAIRO_STATUS_SUCCESS)
1705 	status = status2;
1706 
1707     _cairo_pdf_surface_clear (surface);
1708     _cairo_pdf_group_resources_fini (&surface->resources);
1709 
1710     _cairo_array_fini (&surface->objects);
1711     _cairo_array_fini (&surface->pages);
1712     _cairo_array_fini (&surface->rgb_linear_functions);
1713     _cairo_array_fini (&surface->alpha_linear_functions);
1714     _cairo_array_fini (&surface->page_patterns);
1715     _cairo_array_fini (&surface->page_surfaces);
1716     _cairo_hash_table_foreach (surface->all_surfaces,
1717 			       _cairo_pdf_source_surface_entry_pluck,
1718 			       surface->all_surfaces);
1719     _cairo_hash_table_destroy (surface->all_surfaces);
1720     _cairo_array_fini (&surface->smask_groups);
1721     _cairo_array_fini (&surface->fonts);
1722     _cairo_array_fini (&surface->knockout_group);
1723 
1724     if (surface->font_subsets) {
1725 	_cairo_scaled_font_subsets_destroy (surface->font_subsets);
1726 	surface->font_subsets = NULL;
1727     }
1728 
1729     _cairo_surface_clipper_reset (&surface->clipper);
1730 
1731     return status;
1732 }
1733 
1734 static cairo_int_status_t
_cairo_pdf_surface_start_page(void * abstract_surface)1735 _cairo_pdf_surface_start_page (void *abstract_surface)
1736 {
1737     cairo_pdf_surface_t *surface = abstract_surface;
1738 
1739     /* Document header */
1740     if (! surface->header_emitted) {
1741 	const char *version;
1742 
1743 	switch (surface->pdf_version) {
1744 	case CAIRO_PDF_VERSION_1_4:
1745 	    version = "1.4";
1746 	    break;
1747 	default:
1748 	case CAIRO_PDF_VERSION_1_5:
1749 	    version = "1.5";
1750 	    break;
1751 	}
1752 
1753 	_cairo_output_stream_printf (surface->output,
1754 				     "%%PDF-%s\n", version);
1755 	_cairo_output_stream_printf (surface->output,
1756 				     "%%%c%c%c%c\n", 181, 237, 174, 251);
1757 	surface->header_emitted = TRUE;
1758     }
1759 
1760     _cairo_pdf_group_resources_clear (&surface->resources);
1761 
1762     return CAIRO_STATUS_SUCCESS;
1763 }
1764 
1765 static cairo_int_status_t
_cairo_pdf_surface_has_fallback_images(void * abstract_surface,cairo_bool_t has_fallbacks)1766 _cairo_pdf_surface_has_fallback_images (void		*abstract_surface,
1767 					cairo_bool_t	 has_fallbacks)
1768 {
1769     cairo_status_t status;
1770     cairo_pdf_surface_t *surface = abstract_surface;
1771 
1772     surface->has_fallback_images = has_fallbacks;
1773     status = _cairo_pdf_surface_open_content_stream (surface, NULL, has_fallbacks);
1774     if (unlikely (status))
1775 	return status;
1776 
1777     return CAIRO_STATUS_SUCCESS;
1778 }
1779 
1780 static cairo_bool_t
_cairo_pdf_surface_supports_fine_grained_fallbacks(void * abstract_surface)1781 _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
1782 {
1783     return TRUE;
1784 }
1785 
1786 /* Emit alpha channel from the image into the given data, providing
1787  * an id that can be used to reference the resulting SMask object.
1788  *
1789  * In the case that the alpha channel happens to be all opaque, then
1790  * no SMask object will be emitted and *id_ret will be set to 0.
1791  */
1792 static cairo_status_t
_cairo_pdf_surface_emit_smask(cairo_pdf_surface_t * surface,cairo_image_surface_t * image,cairo_pdf_resource_t * stream_ret)1793 _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
1794 			       cairo_image_surface_t	*image,
1795 			       cairo_pdf_resource_t	*stream_ret)
1796 {
1797     cairo_status_t status = CAIRO_STATUS_SUCCESS;
1798     char *alpha;
1799     unsigned long alpha_size;
1800     uint32_t *pixel32;
1801     uint8_t *pixel8;
1802     int i, x, y;
1803     cairo_bool_t opaque;
1804     uint8_t a;
1805 
1806     /* This is the only image format we support, which simplifies things. */
1807     assert (image->format == CAIRO_FORMAT_ARGB32 ||
1808 	    image->format == CAIRO_FORMAT_A8 ||
1809 	    image->format == CAIRO_FORMAT_A1 );
1810 
1811     stream_ret->id = 0;
1812 
1813     if (image->format == CAIRO_FORMAT_A1) {
1814 	alpha_size = (image->width + 7) / 8 * image->height;
1815 	alpha = _cairo_malloc_ab ((image->width+7) / 8, image->height);
1816     } else {
1817 	alpha_size = image->height * image->width;
1818 	alpha = _cairo_malloc_ab (image->height, image->width);
1819     }
1820 
1821     if (unlikely (alpha == NULL)) {
1822 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1823 	goto CLEANUP;
1824     }
1825 
1826     opaque = TRUE;
1827     i = 0;
1828     for (y = 0; y < image->height; y++) {
1829 	if (image->format == CAIRO_FORMAT_ARGB32) {
1830 	    pixel32 = (uint32_t *) (image->data + y * image->stride);
1831 
1832 	    for (x = 0; x < image->width; x++, pixel32++) {
1833 		a = (*pixel32 & 0xff000000) >> 24;
1834 		alpha[i++] = a;
1835 		if (a != 0xff)
1836 		    opaque = FALSE;
1837 	    }
1838 	} else if (image->format == CAIRO_FORMAT_A8){
1839 	    pixel8 = (uint8_t *) (image->data + y * image->stride);
1840 
1841 	    for (x = 0; x < image->width; x++, pixel8++) {
1842 		a = *pixel8;
1843 		alpha[i++] = a;
1844 		if (a != 0xff)
1845 		    opaque = FALSE;
1846 	    }
1847 	} else { /* image->format == CAIRO_FORMAT_A1 */
1848 	    pixel8 = (uint8_t *) (image->data + y * image->stride);
1849 
1850 	    for (x = 0; x < (image->width + 7) / 8; x++, pixel8++) {
1851 		a = *pixel8;
1852 		a = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a);
1853 		alpha[i++] = a;
1854 		if (a != 0xff)
1855 		    opaque = FALSE;
1856 	    }
1857 	}
1858     }
1859 
1860     /* Bail out without emitting smask if it's all opaque. */
1861     if (opaque)
1862 	goto CLEANUP_ALPHA;
1863 
1864     status = _cairo_pdf_surface_open_stream (surface,
1865 					     NULL,
1866 					     TRUE,
1867 					     "   /Type /XObject\n"
1868 					     "   /Subtype /Image\n"
1869 					     "   /Width %d\n"
1870 					     "   /Height %d\n"
1871 					     "   /ColorSpace /DeviceGray\n"
1872 					     "   /BitsPerComponent %d\n",
1873 					     image->width, image->height,
1874 					     image->format == CAIRO_FORMAT_A1 ? 1 : 8);
1875     if (unlikely (status))
1876 	goto CLEANUP_ALPHA;
1877 
1878     *stream_ret = surface->pdf_stream.self;
1879     _cairo_output_stream_write (surface->output, alpha, alpha_size);
1880     status = _cairo_pdf_surface_close_stream (surface);
1881 
1882  CLEANUP_ALPHA:
1883     free (alpha);
1884  CLEANUP:
1885     return status;
1886 }
1887 
1888 /* Emit image data into the given surface, providing a resource that
1889  * can be used to reference the data in image_ret. */
1890 static cairo_status_t
_cairo_pdf_surface_emit_image(cairo_pdf_surface_t * surface,cairo_image_surface_t * image,cairo_pdf_resource_t * image_res,cairo_filter_t filter)1891 _cairo_pdf_surface_emit_image (cairo_pdf_surface_t     *surface,
1892                                cairo_image_surface_t   *image,
1893                                cairo_pdf_resource_t    *image_res,
1894 			       cairo_filter_t           filter)
1895 {
1896     cairo_status_t status = CAIRO_STATUS_SUCCESS;
1897     char *rgb;
1898     unsigned long rgb_size;
1899     uint32_t *pixel;
1900     int i, x, y;
1901     cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
1902     cairo_bool_t need_smask;
1903     const char *interpolate = "true";
1904 
1905     /* These are the only image formats we currently support, (which
1906      * makes things a lot simpler here). This is enforced through
1907      * _cairo_pdf_surface_analyze_operation which only accept source surfaces of
1908      * CONTENT_COLOR or CONTENT_COLOR_ALPHA.
1909      */
1910     assert (image->format == CAIRO_FORMAT_RGB24 ||
1911 	    image->format == CAIRO_FORMAT_ARGB32 ||
1912 	    image->format == CAIRO_FORMAT_A8 ||
1913 	    image->format == CAIRO_FORMAT_A1);
1914 
1915     rgb_size = image->height * image->width * 3;
1916     rgb = _cairo_malloc_abc (image->width, image->height, 3);
1917     if (unlikely (rgb == NULL)) {
1918 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1919 	goto CLEANUP;
1920     }
1921 
1922     i = 0;
1923     for (y = 0; y < image->height; y++) {
1924 	pixel = (uint32_t *) (image->data + y * image->stride);
1925 
1926 	for (x = 0; x < image->width; x++, pixel++) {
1927 	    /* XXX: We're un-premultiplying alpha here. My reading of the PDF
1928 	     * specification suggests that we should be able to avoid having
1929 	     * to do this by filling in the SMask's Matte dictionary
1930 	     * appropriately, but my attempts to do that so far have
1931 	     * failed. */
1932 	    if (image->format == CAIRO_FORMAT_ARGB32) {
1933 		uint8_t a;
1934 		a = (*pixel & 0xff000000) >> 24;
1935 		if (a == 0) {
1936 		    rgb[i++] = 0;
1937 		    rgb[i++] = 0;
1938 		    rgb[i++] = 0;
1939 		} else {
1940 		    rgb[i++] = (((*pixel & 0xff0000) >> 16) * 255 + a / 2) / a;
1941 		    rgb[i++] = (((*pixel & 0x00ff00) >>  8) * 255 + a / 2) / a;
1942 		    rgb[i++] = (((*pixel & 0x0000ff) >>  0) * 255 + a / 2) / a;
1943 		}
1944 	    } else if (image->format == CAIRO_FORMAT_RGB24) {
1945 		rgb[i++] = (*pixel & 0x00ff0000) >> 16;
1946 		rgb[i++] = (*pixel & 0x0000ff00) >>  8;
1947 		rgb[i++] = (*pixel & 0x000000ff) >>  0;
1948 	    } else {
1949 		rgb[i++] = 0;
1950 		rgb[i++] = 0;
1951 		rgb[i++] = 0;
1952 	    }
1953 	}
1954     }
1955 
1956     need_smask = FALSE;
1957     if (image->format == CAIRO_FORMAT_ARGB32 ||
1958 	image->format == CAIRO_FORMAT_A8 ||
1959 	image->format == CAIRO_FORMAT_A1) {
1960 	status = _cairo_pdf_surface_emit_smask (surface, image, &smask);
1961 	if (unlikely (status))
1962 	    goto CLEANUP_RGB;
1963 
1964 	if (smask.id)
1965 	    need_smask = TRUE;
1966     }
1967 
1968     switch (filter) {
1969     case CAIRO_FILTER_GOOD:
1970     case CAIRO_FILTER_BEST:
1971     case CAIRO_FILTER_BILINEAR:
1972 	interpolate = "true";
1973 	break;
1974     case CAIRO_FILTER_FAST:
1975     case CAIRO_FILTER_NEAREST:
1976     case CAIRO_FILTER_GAUSSIAN:
1977 	interpolate = "false";
1978 	break;
1979     }
1980 
1981 #define IMAGE_DICTIONARY	"   /Type /XObject\n"		\
1982 				"   /Subtype /Image\n"	\
1983 				"   /Width %d\n"		\
1984 				"   /Height %d\n"		\
1985 				"   /ColorSpace /DeviceRGB\n"	\
1986 	                        "   /Interpolate %s\n" \
1987 				"   /BitsPerComponent 8\n"
1988 
1989     if (need_smask)
1990 	status = _cairo_pdf_surface_open_stream (surface,
1991 						 image_res,
1992 						 TRUE,
1993 						 IMAGE_DICTIONARY
1994 						 "   /SMask %d 0 R\n",
1995 						 image->width, image->height,
1996 						 interpolate,
1997 						 smask.id);
1998     else
1999 	status = _cairo_pdf_surface_open_stream (surface,
2000 						 image_res,
2001 						 TRUE,
2002 						 IMAGE_DICTIONARY,
2003 						 image->width, image->height,
2004 						 interpolate);
2005     if (unlikely (status))
2006 	goto CLEANUP_RGB;
2007 
2008 #undef IMAGE_DICTIONARY
2009 
2010     _cairo_output_stream_write (surface->output, rgb, rgb_size);
2011     status = _cairo_pdf_surface_close_stream (surface);
2012 
2013 CLEANUP_RGB:
2014     free (rgb);
2015 CLEANUP:
2016     return status;
2017 }
2018 
2019 static cairo_int_status_t
_cairo_pdf_surface_emit_jpx_image(cairo_pdf_surface_t * surface,cairo_surface_t * source,cairo_pdf_resource_t res)2020 _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t   *surface,
2021 				   cairo_surface_t	 *source,
2022 				   cairo_pdf_resource_t   res)
2023 {
2024     cairo_status_t status;
2025     const unsigned char *mime_data;
2026     unsigned long mime_data_length;
2027     cairo_image_info_t info;
2028 
2029     if (surface->pdf_version < CAIRO_PDF_VERSION_1_5)
2030 	return CAIRO_INT_STATUS_UNSUPPORTED;
2031 
2032     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
2033 				 &mime_data, &mime_data_length);
2034     if (mime_data == NULL)
2035 	return CAIRO_INT_STATUS_UNSUPPORTED;
2036 
2037     status = _cairo_image_info_get_jpx_info (&info, mime_data, mime_data_length);
2038     if (status)
2039 	return status;
2040 
2041     status = _cairo_pdf_surface_open_stream (surface,
2042 					     &res,
2043 					     FALSE,
2044 					     "   /Type /XObject\n"
2045 					     "   /Subtype /Image\n"
2046 					     "   /Width %d\n"
2047 					     "   /Height %d\n"
2048 					     "   /Filter /JPXDecode\n",
2049 					     info.width,
2050 					     info.height);
2051     if (status)
2052 	return status;
2053 
2054     _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
2055     status = _cairo_pdf_surface_close_stream (surface);
2056 
2057     return status;
2058 }
2059 
2060 static cairo_int_status_t
_cairo_pdf_surface_emit_jpeg_image(cairo_pdf_surface_t * surface,cairo_surface_t * source,cairo_pdf_resource_t res)2061 _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t   *surface,
2062 				    cairo_surface_t	  *source,
2063 				    cairo_pdf_resource_t   res)
2064 {
2065     cairo_status_t status;
2066     const unsigned char *mime_data;
2067     unsigned long mime_data_length;
2068     cairo_image_info_t info;
2069 
2070     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
2071 				 &mime_data, &mime_data_length);
2072     if (unlikely (source->status))
2073 	return source->status;
2074     if (mime_data == NULL)
2075 	return CAIRO_INT_STATUS_UNSUPPORTED;
2076 
2077     status = _cairo_image_info_get_jpeg_info (&info, mime_data, mime_data_length);
2078     if (unlikely (status))
2079 	return status;
2080 
2081     if (info.num_components != 1 && info.num_components != 3)
2082 	return CAIRO_INT_STATUS_UNSUPPORTED;
2083 
2084     status = _cairo_pdf_surface_open_stream (surface,
2085 					     &res,
2086 					     FALSE,
2087 					     "   /Type /XObject\n"
2088 					     "   /Subtype /Image\n"
2089 					     "   /Width %d\n"
2090 					     "   /Height %d\n"
2091 					     "   /ColorSpace %s\n"
2092 					     "   /BitsPerComponent %d\n"
2093 					     "   /Filter /DCTDecode\n",
2094 					     info.width,
2095 					     info.height,
2096 					     info.num_components == 1 ? "/DeviceGray" : "/DeviceRGB",
2097 					     info.bits_per_component);
2098     if (unlikely (status))
2099 	return status;
2100 
2101     _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
2102     status = _cairo_pdf_surface_close_stream (surface);
2103 
2104     return status;
2105 }
2106 
2107 static cairo_status_t
_cairo_pdf_surface_emit_image_surface(cairo_pdf_surface_t * surface,cairo_surface_t * source,cairo_pdf_resource_t resource,cairo_bool_t interpolate)2108 _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
2109 				       cairo_surface_t         *source,
2110 				       cairo_pdf_resource_t     resource,
2111 				       cairo_bool_t 		interpolate)
2112 {
2113     cairo_image_surface_t *image;
2114     void *image_extra;
2115     cairo_status_t status;
2116 
2117     status = _cairo_pdf_surface_emit_jpx_image (surface, source, resource);
2118     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2119 	return status;
2120 
2121     status = _cairo_pdf_surface_emit_jpeg_image (surface, source, resource);
2122     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2123 	return status;
2124 
2125     status = _cairo_surface_acquire_source_image (source, &image, &image_extra);
2126     if (unlikely (status))
2127 	return status;
2128 
2129     status = _cairo_pdf_surface_emit_image (surface, image,
2130 					    &resource, interpolate);
2131     if (unlikely (status))
2132 	goto BAIL;
2133 
2134 BAIL:
2135     _cairo_surface_release_source_image (source, image, image_extra);
2136 
2137     return status;
2138 }
2139 
2140 static cairo_status_t
_cairo_pdf_surface_emit_padded_image_surface(cairo_pdf_surface_t * surface,cairo_pdf_pattern_t * pdf_pattern,cairo_pdf_resource_t * resource,int * width,int * height,int * origin_x,int * origin_y)2141 _cairo_pdf_surface_emit_padded_image_surface (cairo_pdf_surface_t     *surface,
2142 					      cairo_pdf_pattern_t     *pdf_pattern,
2143 					      cairo_pdf_resource_t    *resource,
2144 					      int                     *width,
2145 					      int                     *height,
2146 					      int                     *origin_x,
2147 					      int                     *origin_y)
2148 {
2149     cairo_image_surface_t *image;
2150     cairo_surface_t *pad_image;
2151     void *image_extra;
2152     cairo_status_t status;
2153     cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
2154     int x = 0;
2155     int y = 0;
2156     cairo_bool_t interpolate;
2157 
2158     status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
2159     if (unlikely (status))
2160         return status;
2161 
2162     pad_image = &image->base;
2163     if (pattern->base.extend == CAIRO_EXTEND_PAD) {
2164         cairo_box_t box;
2165         cairo_rectangle_int_t rect;
2166         cairo_surface_pattern_t pad_pattern;
2167 
2168         /* get the operation extents in pattern space */
2169         _cairo_box_from_rectangle (&box, &pdf_pattern->extents);
2170         _cairo_matrix_transform_bounding_box_fixed (&pattern->base.matrix, &box, NULL);
2171         _cairo_box_round_to_rectangle (&box, &rect);
2172         x = -rect.x;
2173         y = -rect.y;
2174 
2175         pad_image = _cairo_image_surface_create_with_content (pattern->surface->content,
2176                                                               rect.width,
2177                                                               rect.height);
2178         if (pad_image->status) {
2179             status = pad_image->status;
2180             goto BAIL;
2181         }
2182 
2183         _cairo_pattern_init_for_surface (&pad_pattern, &image->base);
2184         cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
2185         pad_pattern.base.extend = CAIRO_EXTEND_PAD;
2186         status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
2187                                            &pad_pattern.base,
2188                                            NULL,
2189                                            pad_image,
2190                                            0, 0,
2191                                            0, 0,
2192                                            0, 0,
2193                                            rect.width,
2194                                            rect.height,
2195 					   NULL);
2196         _cairo_pattern_fini (&pad_pattern.base);
2197         if (unlikely (status))
2198             goto BAIL;
2199     }
2200 
2201     switch (pdf_pattern->pattern->filter) {
2202     case CAIRO_FILTER_GOOD:
2203     case CAIRO_FILTER_BEST:
2204     case CAIRO_FILTER_BILINEAR:
2205 	interpolate = TRUE;
2206 	break;
2207     case CAIRO_FILTER_FAST:
2208     case CAIRO_FILTER_NEAREST:
2209     case CAIRO_FILTER_GAUSSIAN:
2210 	interpolate = FALSE;
2211 	break;
2212     }
2213 
2214     *resource = _cairo_pdf_surface_new_object (surface);
2215     if (resource->id == 0) {
2216 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2217 	goto BAIL;
2218     }
2219 
2220     status = _cairo_pdf_surface_emit_image (surface, (cairo_image_surface_t *)pad_image,
2221                                             resource, interpolate);
2222     if (unlikely (status))
2223         goto BAIL;
2224 
2225     *width = ((cairo_image_surface_t *)pad_image)->width;
2226     *height = ((cairo_image_surface_t *)pad_image)->height;
2227     *origin_x = x;
2228     *origin_y = y;
2229 
2230 BAIL:
2231     if (pad_image != &image->base)
2232         cairo_surface_destroy (pad_image);
2233 
2234     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
2235 
2236     return status;
2237 }
2238 
2239 
2240 static cairo_status_t
_cairo_pdf_surface_emit_recording_surface(cairo_pdf_surface_t * surface,cairo_surface_t * recording_surface,cairo_pdf_resource_t resource)2241 _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t  *surface,
2242 					   cairo_surface_t      *recording_surface,
2243 					   cairo_pdf_resource_t  resource)
2244 {
2245     double old_width, old_height;
2246     cairo_paginated_mode_t old_paginated_mode;
2247     cairo_rectangle_int_t recording_extents;
2248     cairo_bool_t is_bounded;
2249     cairo_status_t status;
2250     int alpha = 0;
2251 
2252     is_bounded = _cairo_surface_get_extents (recording_surface, &recording_extents);
2253     assert (is_bounded);
2254 
2255     old_width = surface->width;
2256     old_height = surface->height;
2257     old_paginated_mode = surface->paginated_mode;
2258 
2259     _cairo_pdf_surface_set_size_internal (surface,
2260 					  recording_extents.width,
2261 					  recording_extents.height);
2262     /* Patterns are emitted after fallback images. The paginated mode
2263      * needs to be set to _RENDER while the recording surface is replayed
2264      * back to this surface.
2265      */
2266     surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
2267     _cairo_pdf_group_resources_clear (&surface->resources);
2268     status = _cairo_pdf_surface_open_content_stream (surface, &resource, TRUE);
2269     if (unlikely (status))
2270 	return status;
2271 
2272     if (cairo_surface_get_content (recording_surface) == CAIRO_CONTENT_COLOR) {
2273 	status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
2274 	if (unlikely (status))
2275 	    return status;
2276 
2277 	_cairo_output_stream_printf (surface->output,
2278 				     "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
2279 				     alpha,
2280 				     surface->width,
2281 				     surface->height);
2282     }
2283 
2284     status = _cairo_recording_surface_replay_region (recording_surface,
2285 						     NULL,
2286 						     &surface->base,
2287 						     CAIRO_RECORDING_REGION_NATIVE);
2288     assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
2289     if (unlikely (status))
2290 	return status;
2291 
2292     status = _cairo_pdf_surface_close_content_stream (surface);
2293 
2294     _cairo_pdf_surface_set_size_internal (surface,
2295 					  old_width,
2296 					  old_height);
2297     surface->paginated_mode = old_paginated_mode;
2298 
2299     return status;
2300 }
2301 
2302 static cairo_status_t
_cairo_pdf_surface_emit_recording_subsurface(cairo_pdf_surface_t * surface,cairo_surface_t * recording_surface,const cairo_rectangle_int_t * extents,cairo_pdf_resource_t resource)2303 _cairo_pdf_surface_emit_recording_subsurface (cairo_pdf_surface_t  *surface,
2304 					      cairo_surface_t      *recording_surface,
2305 					      const cairo_rectangle_int_t *extents,
2306 					      cairo_pdf_resource_t  resource)
2307 {
2308     double old_width, old_height;
2309     cairo_paginated_mode_t old_paginated_mode;
2310     cairo_status_t status;
2311     int alpha = 0;
2312 
2313     old_width = surface->width;
2314     old_height = surface->height;
2315     old_paginated_mode = surface->paginated_mode;
2316 
2317     _cairo_pdf_surface_set_size_internal (surface,
2318 					  extents->width,
2319 					  extents->height);
2320     /* Patterns are emitted after fallback images. The paginated mode
2321      * needs to be set to _RENDER while the recording surface is replayed
2322      * back to this surface.
2323      */
2324     surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
2325     _cairo_pdf_group_resources_clear (&surface->resources);
2326     status = _cairo_pdf_surface_open_content_stream (surface, &resource, TRUE);
2327     if (unlikely (status))
2328 	return status;
2329 
2330     if (cairo_surface_get_content (recording_surface) == CAIRO_CONTENT_COLOR) {
2331 	status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
2332 	if (unlikely (status))
2333 	    return status;
2334 
2335 	_cairo_output_stream_printf (surface->output,
2336 				     "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
2337 				     alpha,
2338 				     surface->width,
2339 				     surface->height);
2340     }
2341 
2342     status = _cairo_recording_surface_replay_region (recording_surface,
2343 						     extents,
2344 						     &surface->base,
2345 						     CAIRO_RECORDING_REGION_NATIVE);
2346     assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
2347     if (unlikely (status))
2348 	return status;
2349 
2350     status = _cairo_pdf_surface_close_content_stream (surface);
2351 
2352     _cairo_pdf_surface_set_size_internal (surface,
2353 					  old_width,
2354 					  old_height);
2355     surface->paginated_mode = old_paginated_mode;
2356 
2357     return status;
2358 }
2359 
2360 static cairo_status_t
_cairo_pdf_surface_emit_surface(cairo_pdf_surface_t * surface,cairo_pdf_source_surface_t * src_surface)2361 _cairo_pdf_surface_emit_surface (cairo_pdf_surface_t        *surface,
2362 				 cairo_pdf_source_surface_t *src_surface)
2363 {
2364     if (src_surface->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
2365 	if (src_surface->surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
2366 	    cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) src_surface->surface;
2367 	    return _cairo_pdf_surface_emit_recording_subsurface (surface,
2368 								 sub->target,
2369 								 &sub->extents,
2370 								 src_surface->hash_entry->surface_res);
2371 	} else {
2372 	    return _cairo_pdf_surface_emit_recording_surface (surface,
2373 							      src_surface->surface,
2374 							      src_surface->hash_entry->surface_res);
2375 	}
2376     } else {
2377 	return _cairo_pdf_surface_emit_image_surface (surface,
2378 						      src_surface->surface,
2379 						      src_surface->hash_entry->surface_res,
2380 						      src_surface->hash_entry->interpolate);
2381     }
2382 }
2383 
2384 static cairo_status_t
_cairo_pdf_surface_emit_surface_pattern(cairo_pdf_surface_t * surface,cairo_pdf_pattern_t * pdf_pattern)2385 _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t	*surface,
2386 					 cairo_pdf_pattern_t	*pdf_pattern)
2387 {
2388     cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
2389     cairo_status_t status;
2390     cairo_pdf_resource_t pattern_resource = {0};
2391     cairo_matrix_t cairo_p2d, pdf_p2d;
2392     cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
2393     double xstep, ystep;
2394     int pattern_width = 0; /* squelch bogus compiler warning */
2395     int pattern_height = 0; /* squelch bogus compiler warning */
2396     int origin_x = 0; /* squelch bogus compiler warning */
2397     int origin_y = 0; /* squelch bogus compiler warning */
2398     int bbox_x, bbox_y;
2399     char draw_surface[200];
2400 
2401     if (pattern->base.extend == CAIRO_EXTEND_PAD &&
2402 	pattern->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
2403     {
2404 	status = _cairo_pdf_surface_emit_padded_image_surface (surface,
2405 							       pdf_pattern,
2406 							       &pattern_resource,
2407 							       &pattern_width,
2408 							       &pattern_height,
2409 							       &origin_x,
2410 							       &origin_y);
2411     }
2412     else
2413     {
2414 	status = _cairo_pdf_surface_add_source_surface (surface,
2415 							pattern->surface,
2416 							pdf_pattern->pattern->filter,
2417 							&pattern_resource,
2418 							&pattern_width,
2419 							&pattern_height);
2420     }
2421     if (unlikely (status))
2422 	return status;
2423 
2424     bbox_x = pattern_width;
2425     bbox_y = pattern_height;
2426     switch (extend) {
2427     case CAIRO_EXTEND_PAD:
2428     case CAIRO_EXTEND_NONE:
2429     {
2430 	/* In PS/PDF, (as far as I can tell), all patterns are
2431 	 * repeating. So we support cairo's EXTEND_NONE semantics
2432 	 * by setting the repeat step size to a size large enough
2433 	 * to guarantee that no more than a single occurrence will
2434 	 * be visible.
2435 	 *
2436 	 * First, map the surface extents into pattern space (since
2437 	 * xstep and ystep are in pattern space).  Then use an upper
2438 	 * bound on the length of the diagonal of the pattern image
2439 	 * and the surface as repeat size.  This guarantees to never
2440 	 * repeat visibly.
2441 	 */
2442 	double x1 = 0.0, y1 = 0.0;
2443 	double x2 = surface->width, y2 = surface->height;
2444 	_cairo_matrix_transform_bounding_box (&pattern->base.matrix,
2445 					      &x1, &y1, &x2, &y2,
2446 					      NULL);
2447 
2448 	/* Rather than computing precise bounds of the union, just
2449 	 * add the surface extents unconditionally. We only
2450 	 * required an answer that's large enough, we don't really
2451 	 * care if it's not as tight as possible.*/
2452 	xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
2453 			      pattern_width + pattern_height);
2454     }
2455     break;
2456     case CAIRO_EXTEND_REPEAT:
2457 	xstep = pattern_width;
2458 	ystep = pattern_height;
2459 	break;
2460     case CAIRO_EXTEND_REFLECT:
2461 	bbox_x = pattern_width*2;
2462 	bbox_y = pattern_height*2;
2463 	xstep = bbox_x;
2464 	ystep = bbox_y;
2465 	break;
2466 	/* All the rest (if any) should have been analyzed away, so this
2467 	 * case should be unreachable. */
2468     default:
2469 	ASSERT_NOT_REACHED;
2470 	xstep = 0;
2471 	ystep = 0;
2472     }
2473 
2474     /* At this point, (that is, within the surface backend interface),
2475      * the pattern's matrix maps from cairo's device space to cairo's
2476      * pattern space, (both with their origin at the upper-left, and
2477      * cairo's pattern space of size width,height).
2478      *
2479      * Then, we must emit a PDF pattern object that maps from its own
2480      * pattern space, (which has a size that we establish in the BBox
2481      * dictionary entry), to the PDF page's *initial* space, (which
2482      * does not benefit from the Y-axis flipping matrix that we emit
2483      * on each page). So the PDF patterns matrix maps from a
2484      * (width,height) pattern space to a device space with the origin
2485      * in the lower-left corner.
2486      *
2487      * So to handle all of that, we start with an identity matrix for
2488      * the PDF pattern to device matrix. We translate it up by the
2489      * image height then flip it in the Y direction, (moving us from
2490      * the PDF origin to cairo's origin). We then multiply in the
2491      * inverse of the cairo pattern matrix, (since it maps from device
2492      * to pattern, while we're setting up pattern to device). Finally,
2493      * we translate back down by the image height and flip again to
2494      * end up at the lower-left origin that PDF expects.
2495      *
2496      * Additionally, within the stream that paints the pattern itself,
2497      * we are using a PDF image object that has a size of (1,1) so we
2498      * have to scale it up by the image width and height to fill our
2499      * pattern cell.
2500      */
2501     cairo_p2d = pattern->base.matrix;
2502     status = cairo_matrix_invert (&cairo_p2d);
2503     /* cairo_pattern_set_matrix ensures the matrix is invertible */
2504     assert (status == CAIRO_STATUS_SUCCESS);
2505 
2506     cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &surface->cairo_to_pdf);
2507     cairo_matrix_translate (&pdf_p2d, -origin_x, -origin_y);
2508     cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
2509     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
2510 
2511     _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
2512     status = _cairo_pdf_surface_open_stream (surface,
2513 				             &pdf_pattern->pattern_res,
2514 					     FALSE,
2515 					     "   /PatternType 1\n"
2516 					     "   /BBox [0 0 %d %d]\n"
2517 					     "   /XStep %f\n"
2518 					     "   /YStep %f\n"
2519 					     "   /TilingType 1\n"
2520 					     "   /PaintType 1\n"
2521 					     "   /Matrix [ %f %f %f %f %f %f ]\n"
2522 					     "   /Resources << /XObject << /x%d %d 0 R >> >>\n",
2523 					     bbox_x, bbox_y,
2524 					     xstep, ystep,
2525 					     pdf_p2d.xx, pdf_p2d.yx,
2526 					     pdf_p2d.xy, pdf_p2d.yy,
2527 					     pdf_p2d.x0, pdf_p2d.y0,
2528 					     pattern_resource.id,
2529 					     pattern_resource.id);
2530     if (unlikely (status))
2531 	return status;
2532 
2533     if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
2534 	snprintf(draw_surface,
2535 		 sizeof (draw_surface),
2536 		 "/x%d Do\n",
2537 		 pattern_resource.id);
2538     } else {
2539 	snprintf(draw_surface,
2540 		 sizeof (draw_surface),
2541 		 "q %d 0 0 %d 0 0 cm /x%d Do Q",
2542 		 pattern_width,
2543 		 pattern_height,
2544 		 pattern_resource.id);
2545     }
2546 
2547     if (extend == CAIRO_EXTEND_REFLECT) {
2548 	_cairo_output_stream_printf (surface->output,
2549 				     "q 0 0 %d %d re W n %s Q\n"
2550 				     "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n %s Q\n"
2551 				     "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n %s Q\n"
2552 				     "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n %s Q\n",
2553 				     pattern_width, pattern_height,
2554 				     draw_surface,
2555 				     pattern_width*2, pattern_width, pattern_height,
2556 				     draw_surface,
2557 				     pattern_height*2, pattern_width, pattern_height,
2558 				     draw_surface,
2559 				     pattern_width*2, pattern_height*2, pattern_width, pattern_height,
2560 				     draw_surface);
2561     } else {
2562 	_cairo_output_stream_printf (surface->output,
2563 				     " %s \n",
2564 				     draw_surface);
2565     }
2566 
2567     status = _cairo_pdf_surface_close_stream (surface);
2568     if (unlikely (status))
2569 	return status;
2570 
2571     return _cairo_output_stream_get_status (surface->output);
2572 }
2573 
2574 typedef struct _cairo_pdf_color_stop {
2575     double offset;
2576     double color[4];
2577     cairo_pdf_resource_t resource;
2578 } cairo_pdf_color_stop_t;
2579 
2580 static cairo_status_t
cairo_pdf_surface_emit_rgb_linear_function(cairo_pdf_surface_t * surface,cairo_pdf_color_stop_t * stop1,cairo_pdf_color_stop_t * stop2,cairo_pdf_resource_t * function)2581 cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t    *surface,
2582                                             cairo_pdf_color_stop_t *stop1,
2583                                             cairo_pdf_color_stop_t *stop2,
2584                                             cairo_pdf_resource_t   *function)
2585 {
2586     int num_elems, i;
2587     cairo_pdf_rgb_linear_function_t elem;
2588     cairo_pdf_resource_t res;
2589     cairo_status_t status;
2590 
2591     num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions);
2592     for (i = 0; i < num_elems; i++) {
2593 	_cairo_array_copy_element (&surface->rgb_linear_functions, i, &elem);
2594         if (memcmp (&elem.color1[0], &stop1->color[0], sizeof (double)*3) != 0)
2595             continue;
2596         if (memcmp (&elem.color2[0], &stop2->color[0], sizeof (double)*3) != 0)
2597             continue;
2598         *function =  elem.resource;
2599         return CAIRO_STATUS_SUCCESS;
2600     }
2601 
2602     res = _cairo_pdf_surface_new_object (surface);
2603     if (res.id == 0)
2604 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2605 
2606     _cairo_output_stream_printf (surface->output,
2607 				 "%d 0 obj\n"
2608 				 "<< /FunctionType 2\n"
2609 				 "   /Domain [ 0 1 ]\n"
2610 				 "   /C0 [ %f %f %f ]\n"
2611 				 "   /C1 [ %f %f %f ]\n"
2612 				 "   /N 1\n"
2613 				 ">>\n"
2614 				 "endobj\n",
2615 				 res.id,
2616                                  stop1->color[0],
2617                                  stop1->color[1],
2618                                  stop1->color[2],
2619                                  stop2->color[0],
2620                                  stop2->color[1],
2621                                  stop2->color[2]);
2622 
2623     elem.resource = res;
2624     memcpy (&elem.color1[0], &stop1->color[0], sizeof (double)*3);
2625     memcpy (&elem.color2[0], &stop2->color[0], sizeof (double)*3);
2626 
2627     status = _cairo_array_append (&surface->rgb_linear_functions, &elem);
2628     *function = res;
2629 
2630     return status;
2631 }
2632 
2633 static cairo_status_t
cairo_pdf_surface_emit_alpha_linear_function(cairo_pdf_surface_t * surface,cairo_pdf_color_stop_t * stop1,cairo_pdf_color_stop_t * stop2,cairo_pdf_resource_t * function)2634 cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t    *surface,
2635                                               cairo_pdf_color_stop_t *stop1,
2636                                               cairo_pdf_color_stop_t *stop2,
2637                                               cairo_pdf_resource_t   *function)
2638 {
2639     int num_elems, i;
2640     cairo_pdf_alpha_linear_function_t elem;
2641     cairo_pdf_resource_t res;
2642     cairo_status_t status;
2643 
2644     num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions);
2645     for (i = 0; i < num_elems; i++) {
2646 	_cairo_array_copy_element (&surface->alpha_linear_functions, i, &elem);
2647         if (elem.alpha1 != stop1->color[3])
2648             continue;
2649         if (elem.alpha2 != stop2->color[3])
2650             continue;
2651         *function =  elem.resource;
2652         return CAIRO_STATUS_SUCCESS;
2653     }
2654 
2655     res = _cairo_pdf_surface_new_object (surface);
2656     if (res.id == 0)
2657 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2658 
2659     _cairo_output_stream_printf (surface->output,
2660 				 "%d 0 obj\n"
2661 				 "<< /FunctionType 2\n"
2662 				 "   /Domain [ 0 1 ]\n"
2663 				 "   /C0 [ %f ]\n"
2664 				 "   /C1 [ %f ]\n"
2665 				 "   /N 1\n"
2666 				 ">>\n"
2667 				 "endobj\n",
2668 				 res.id,
2669                                  stop1->color[3],
2670                                  stop2->color[3]);
2671 
2672     elem.resource = res;
2673     elem.alpha1 = stop1->color[3];
2674     elem.alpha2 = stop2->color[3];
2675 
2676     status = _cairo_array_append (&surface->alpha_linear_functions, &elem);
2677     *function = res;
2678 
2679     return status;
2680 }
2681 
2682 static cairo_status_t
_cairo_pdf_surface_emit_stitched_colorgradient(cairo_pdf_surface_t * surface,unsigned int n_stops,cairo_pdf_color_stop_t * stops,cairo_bool_t is_alpha,cairo_pdf_resource_t * function)2683 _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t    *surface,
2684                                                 unsigned int	        n_stops,
2685                                                 cairo_pdf_color_stop_t *stops,
2686                                                 cairo_bool_t	        is_alpha,
2687                                                 cairo_pdf_resource_t   *function)
2688 {
2689     cairo_pdf_resource_t res;
2690     unsigned int i;
2691     cairo_status_t status;
2692 
2693     /* emit linear gradients between pairs of subsequent stops... */
2694     for (i = 0; i < n_stops-1; i++) {
2695         if (is_alpha) {
2696             status = cairo_pdf_surface_emit_alpha_linear_function (surface,
2697                                                                    &stops[i],
2698                                                                    &stops[i+1],
2699                                                                    &stops[i].resource);
2700             if (unlikely (status))
2701                 return status;
2702         } else {
2703             status = cairo_pdf_surface_emit_rgb_linear_function (surface,
2704                                                                  &stops[i],
2705                                                                  &stops[i+1],
2706                                                                  &stops[i].resource);
2707             if (unlikely (status))
2708                 return status;
2709         }
2710     }
2711 
2712     /* ... and stitch them together */
2713     res = _cairo_pdf_surface_new_object (surface);
2714     if (res.id == 0)
2715 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2716 
2717     _cairo_output_stream_printf (surface->output,
2718 				 "%d 0 obj\n"
2719 				 "<< /FunctionType 3\n"
2720 				 "   /Domain [ %f %f ]\n",
2721 				 res.id,
2722                                  stops[0].offset,
2723                                  stops[n_stops - 1].offset);
2724 
2725     _cairo_output_stream_printf (surface->output,
2726 				 "   /Functions [ ");
2727     for (i = 0; i < n_stops-1; i++)
2728         _cairo_output_stream_printf (surface->output,
2729                                      "%d 0 R ", stops[i].resource.id);
2730     _cairo_output_stream_printf (surface->output,
2731 				 "]\n");
2732 
2733     _cairo_output_stream_printf (surface->output,
2734 				 "   /Bounds [ ");
2735     for (i = 1; i < n_stops-1; i++)
2736         _cairo_output_stream_printf (surface->output,
2737 				     "%f ", stops[i].offset);
2738     _cairo_output_stream_printf (surface->output,
2739 				 "]\n");
2740 
2741     _cairo_output_stream_printf (surface->output,
2742 				 "   /Encode [ ");
2743     for (i = 1; i < n_stops; i++)
2744         _cairo_output_stream_printf (surface->output,
2745 				     "0 1 ");
2746     _cairo_output_stream_printf (surface->output,
2747 				 "]\n");
2748 
2749     _cairo_output_stream_printf (surface->output,
2750 				 ">>\n"
2751 				 "endobj\n");
2752 
2753     *function = res;
2754 
2755     return _cairo_output_stream_get_status (surface->output);
2756 }
2757 
2758 
2759 static void
calc_gradient_color(cairo_pdf_color_stop_t * new_stop,cairo_pdf_color_stop_t * stop1,cairo_pdf_color_stop_t * stop2)2760 calc_gradient_color (cairo_pdf_color_stop_t *new_stop,
2761 		     cairo_pdf_color_stop_t *stop1,
2762 		     cairo_pdf_color_stop_t *stop2)
2763 {
2764     int i;
2765     double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
2766 
2767     for (i = 0; i < 4; i++)
2768 	new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
2769 }
2770 
2771 #define COLOR_STOP_EPSILON 1e-6
2772 
2773 static cairo_status_t
_cairo_pdf_surface_emit_pattern_stops(cairo_pdf_surface_t * surface,cairo_gradient_pattern_t * pattern,cairo_pdf_resource_t * color_function,cairo_pdf_resource_t * alpha_function)2774 _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t      *surface,
2775                                        cairo_gradient_pattern_t *pattern,
2776                                        cairo_pdf_resource_t     *color_function,
2777                                        cairo_pdf_resource_t     *alpha_function)
2778 {
2779     cairo_pdf_color_stop_t *allstops, *stops;
2780     unsigned int n_stops;
2781     unsigned int i;
2782     cairo_bool_t emit_alpha = FALSE;
2783     cairo_status_t status;
2784 
2785     color_function->id = 0;
2786     alpha_function->id = 0;
2787 
2788     allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t));
2789     if (unlikely (allstops == NULL))
2790 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2791 
2792     stops = &allstops[1];
2793     n_stops = pattern->n_stops;
2794 
2795     for (i = 0; i < n_stops; i++) {
2796 	stops[i].color[0] = pattern->stops[i].color.red;
2797 	stops[i].color[1] = pattern->stops[i].color.green;
2798 	stops[i].color[2] = pattern->stops[i].color.blue;
2799 	stops[i].color[3] = pattern->stops[i].color.alpha;
2800         if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
2801             emit_alpha = TRUE;
2802 	stops[i].offset = pattern->stops[i].offset;
2803     }
2804 
2805     if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
2806 	pattern->base.extend == CAIRO_EXTEND_REFLECT) {
2807 	if (stops[0].offset > COLOR_STOP_EPSILON) {
2808 	    if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
2809 		memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
2810 	    else
2811 		calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
2812 	    stops = allstops;
2813 	    n_stops++;
2814 	}
2815 	stops[0].offset = 0.0;
2816 
2817 	if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
2818 	    if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
2819 		memcpy (&stops[n_stops],
2820 			&stops[n_stops - 1],
2821 			sizeof (cairo_pdf_color_stop_t));
2822 	    } else {
2823 		calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
2824 	    }
2825 	    n_stops++;
2826 	}
2827 	stops[n_stops-1].offset = 1.0;
2828     }
2829 
2830     if (n_stops <= 2) {
2831         /* no need for stitched function */
2832         status = cairo_pdf_surface_emit_rgb_linear_function (surface,
2833                                                              &stops[0],
2834                                                              &stops[n_stops - 1],
2835                                                              color_function);
2836         if (unlikely (status))
2837             goto BAIL;
2838 
2839         if (emit_alpha) {
2840             status = cairo_pdf_surface_emit_alpha_linear_function (surface,
2841                                                                    &stops[0],
2842                                                                    &stops[n_stops - 1],
2843                                                                    alpha_function);
2844             if (unlikely (status))
2845                 goto BAIL;
2846         }
2847     } else {
2848         /* multiple stops: stitch. XXX possible optimization: regularly spaced
2849          * stops do not require stitching. XXX */
2850         status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
2851                                                                  n_stops,
2852                                                                  stops,
2853                                                                  FALSE,
2854                                                                  color_function);
2855         if (unlikely (status))
2856             goto BAIL;
2857 
2858         if (emit_alpha) {
2859             status = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
2860                                                                      n_stops,
2861                                                                      stops,
2862                                                                      TRUE,
2863                                                                      alpha_function);
2864             if (unlikely (status))
2865                 goto BAIL;
2866         }
2867     }
2868 
2869 BAIL:
2870     free (allstops);
2871     return status;
2872 }
2873 
2874 static cairo_status_t
_cairo_pdf_surface_emit_repeating_function(cairo_pdf_surface_t * surface,cairo_gradient_pattern_t * pattern,cairo_pdf_resource_t * function,int begin,int end)2875 _cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t      *surface,
2876 					    cairo_gradient_pattern_t *pattern,
2877 					    cairo_pdf_resource_t     *function,
2878 					    int                       begin,
2879 					    int                       end)
2880 {
2881     cairo_pdf_resource_t res;
2882     int i;
2883 
2884     res = _cairo_pdf_surface_new_object (surface);
2885     if (res.id == 0)
2886 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2887 
2888     _cairo_output_stream_printf (surface->output,
2889 				 "%d 0 obj\n"
2890 				 "<< /FunctionType 3\n"
2891 				 "   /Domain [ %d %d ]\n",
2892 				 res.id,
2893                                  begin,
2894                                  end);
2895 
2896     _cairo_output_stream_printf (surface->output,
2897 				 "   /Functions [ ");
2898     for (i = begin; i < end; i++)
2899         _cairo_output_stream_printf (surface->output,
2900                                      "%d 0 R ", function->id);
2901     _cairo_output_stream_printf (surface->output,
2902 				 "]\n");
2903 
2904     _cairo_output_stream_printf (surface->output,
2905 				 "   /Bounds [ ");
2906     for (i = begin + 1; i < end; i++)
2907         _cairo_output_stream_printf (surface->output,
2908 				     "%d ", i);
2909     _cairo_output_stream_printf (surface->output,
2910 				 "]\n");
2911 
2912     _cairo_output_stream_printf (surface->output,
2913 				 "   /Encode [ ");
2914     for (i = begin; i < end; i++) {
2915 	if ((i % 2) && pattern->base.extend == CAIRO_EXTEND_REFLECT) {
2916 	    _cairo_output_stream_printf (surface->output,
2917 					 "1 0 ");
2918 	} else {
2919 	    _cairo_output_stream_printf (surface->output,
2920 					 "0 1 ");
2921 	}
2922     }
2923     _cairo_output_stream_printf (surface->output,
2924 				 "]\n");
2925 
2926     _cairo_output_stream_printf (surface->output,
2927 				 ">>\n"
2928 				 "endobj\n");
2929 
2930     *function = res;
2931 
2932     return _cairo_output_stream_get_status (surface->output);
2933 }
2934 
2935 static cairo_status_t
cairo_pdf_surface_emit_transparency_group(cairo_pdf_surface_t * surface,cairo_pdf_resource_t gstate_resource,cairo_pdf_resource_t gradient_mask)2936 cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t  *surface,
2937 					   cairo_pdf_resource_t  gstate_resource,
2938 					   cairo_pdf_resource_t  gradient_mask)
2939 {
2940     cairo_pdf_resource_t smask_resource;
2941     cairo_status_t status;
2942 
2943     status = _cairo_pdf_surface_open_stream (surface,
2944 					     NULL,
2945 					     surface->compress_content,
2946 					     "   /Type /XObject\n"
2947 					     "   /Subtype /Form\n"
2948 					     "   /FormType 1\n"
2949 					     "   /BBox [ 0 0 %f %f ]\n"
2950 					     "   /Resources\n"
2951 					     "      << /ExtGState\n"
2952 					     "            << /a0 << /ca 1 /CA 1 >>"
2953 					     "      >>\n"
2954 					     "         /Pattern\n"
2955 					     "            << /p%d %d 0 R >>\n"
2956 					     "      >>\n"
2957 					     "   /Group\n"
2958 					     "      << /Type /Group\n"
2959 					     "         /S /Transparency\n"
2960 					     "         /CS /DeviceGray\n"
2961 					     "      >>\n",
2962 					     surface->width,
2963 					     surface->height,
2964 					     gradient_mask.id,
2965 					     gradient_mask.id);
2966     if (unlikely (status))
2967 	return status;
2968 
2969     _cairo_output_stream_printf (surface->output,
2970                                  "q\n"
2971                                  "/a0 gs\n"
2972                                  "/Pattern cs /p%d scn\n"
2973                                  "0 0 %f %f re\n"
2974                                  "f\n"
2975                                  "Q\n",
2976                                  gradient_mask.id,
2977                                  surface->width,
2978                                  surface->height);
2979 
2980      status = _cairo_pdf_surface_close_stream (surface);
2981      if (unlikely (status))
2982 	return status;
2983 
2984     smask_resource = _cairo_pdf_surface_new_object (surface);
2985     if (smask_resource.id == 0)
2986 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2987 
2988     _cairo_output_stream_printf (surface->output,
2989                                  "%d 0 obj\n"
2990                                  "<< /Type /Mask\n"
2991                                  "   /S /Luminosity\n"
2992                                  "   /G %d 0 R\n"
2993                                  ">>\n"
2994                                  "endobj\n",
2995                                  smask_resource.id,
2996                                  surface->pdf_stream.self.id);
2997 
2998     /* Create GState which uses the transparency group as an SMask. */
2999     _cairo_pdf_surface_update_object (surface, gstate_resource);
3000 
3001     _cairo_output_stream_printf (surface->output,
3002                                  "%d 0 obj\n"
3003                                  "<< /Type /ExtGState\n"
3004                                  "   /SMask %d 0 R\n"
3005                                  "   /ca 1\n"
3006                                  "   /CA 1\n"
3007                                  "   /AIS false\n"
3008                                  ">>\n"
3009                                  "endobj\n",
3010                                  gstate_resource.id,
3011                                  smask_resource.id);
3012 
3013     return _cairo_output_stream_get_status (surface->output);
3014 }
3015 
3016 static cairo_status_t
_cairo_pdf_surface_emit_linear_pattern(cairo_pdf_surface_t * surface,cairo_pdf_pattern_t * pdf_pattern)3017 _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t    *surface,
3018 					cairo_pdf_pattern_t    *pdf_pattern)
3019 {
3020     cairo_linear_pattern_t *pattern = (cairo_linear_pattern_t *) pdf_pattern->pattern;
3021     cairo_pdf_resource_t color_function, alpha_function;
3022     double x1, y1, x2, y2;
3023     double _x1, _y1, _x2, _y2;
3024     cairo_matrix_t pat_to_pdf;
3025     cairo_extend_t extend;
3026     cairo_status_t status;
3027     cairo_gradient_pattern_t *gradient = &pattern->base;
3028     double first_stop, last_stop;
3029     int repeat_begin = 0, repeat_end = 1;
3030 
3031     assert (pattern->base.n_stops != 0);
3032 
3033     extend = cairo_pattern_get_extend (pdf_pattern->pattern);
3034 
3035     pat_to_pdf = pattern->base.base.matrix;
3036     status = cairo_matrix_invert (&pat_to_pdf);
3037     /* cairo_pattern_set_matrix ensures the matrix is invertible */
3038     assert (status == CAIRO_STATUS_SUCCESS);
3039 
3040     cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
3041     first_stop = gradient->stops[0].offset;
3042     last_stop = gradient->stops[gradient->n_stops - 1].offset;
3043 
3044     if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
3045 	pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
3046 	double dx, dy;
3047 	int x_rep = 0, y_rep = 0;
3048 
3049 	x1 = _cairo_fixed_to_double (pattern->p1.x);
3050 	y1 = _cairo_fixed_to_double (pattern->p1.y);
3051 	cairo_matrix_transform_point (&pat_to_pdf, &x1, &y1);
3052 
3053 	x2 = _cairo_fixed_to_double (pattern->p2.x);
3054 	y2 = _cairo_fixed_to_double (pattern->p2.y);
3055 	cairo_matrix_transform_point (&pat_to_pdf, &x2, &y2);
3056 
3057 	dx = fabs (x2 - x1);
3058 	dy = fabs (y2 - y1);
3059 	if (dx > 1e-6)
3060 	    x_rep = ceil (surface->width/dx);
3061 	if (dy > 1e-6)
3062 	    y_rep = ceil (surface->height/dy);
3063 
3064 	repeat_end = MAX (x_rep, y_rep);
3065 	repeat_begin = -repeat_end;
3066 	first_stop = repeat_begin;
3067 	last_stop = repeat_end;
3068     }
3069 
3070     /* PDF requires the first and last stop to be the same as the line
3071      * coordinates. For repeating patterns this moves the line
3072      * coordinates out to the begin/end of the repeating function. For
3073      * non repeating patterns this may move the line coordinates in if
3074      * there are not stops at offset 0 and 1. */
3075     x1 = _cairo_fixed_to_double (pattern->p1.x);
3076     y1 = _cairo_fixed_to_double (pattern->p1.y);
3077     x2 = _cairo_fixed_to_double (pattern->p2.x);
3078     y2 = _cairo_fixed_to_double (pattern->p2.y);
3079 
3080     _x1 = x1 + (x2 - x1)*first_stop;
3081     _y1 = y1 + (y2 - y1)*first_stop;
3082     _x2 = x1 + (x2 - x1)*last_stop;
3083     _y2 = y1 + (y2 - y1)*last_stop;
3084 
3085     x1 = _x1;
3086     x2 = _x2;
3087     y1 = _y1;
3088     y2 = _y2;
3089 
3090     /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
3091      * Type 2 function is used by itself without a stitching
3092      * function. Type 2 functions always have the domain [0 1] */
3093     if ((pattern->base.base.extend == CAIRO_EXTEND_NONE ||
3094 	 pattern->base.base.extend == CAIRO_EXTEND_PAD) &&
3095 	gradient->n_stops == 2) {
3096 	first_stop = 0.0;
3097 	last_stop = 1.0;
3098     }
3099 
3100     status = _cairo_pdf_surface_emit_pattern_stops (surface,
3101                                                     &pattern->base,
3102                                                     &color_function,
3103                                                     &alpha_function);
3104     if (unlikely (status))
3105 	return status;
3106 
3107     if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
3108 	pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
3109 	status = _cairo_pdf_surface_emit_repeating_function (surface,
3110 							     &pattern->base,
3111 							     &color_function,
3112 							     repeat_begin,
3113 							     repeat_end);
3114 	if (unlikely (status))
3115 	    return status;
3116 
3117 	if (alpha_function.id != 0) {
3118 	    status = _cairo_pdf_surface_emit_repeating_function (surface,
3119 								 &pattern->base,
3120 								 &alpha_function,
3121 								 repeat_begin,
3122 								 repeat_end);
3123 	    if (unlikely (status))
3124 		return status;
3125 	}
3126     }
3127 
3128     _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
3129     _cairo_output_stream_printf (surface->output,
3130                                  "%d 0 obj\n"
3131                                  "<< /Type /Pattern\n"
3132                                  "   /PatternType 2\n"
3133                                  "   /Matrix [ %f %f %f %f %f %f ]\n"
3134                                  "   /Shading\n"
3135                                  "      << /ShadingType 2\n"
3136                                  "         /ColorSpace /DeviceRGB\n"
3137                                  "         /Coords [ %f %f %f %f ]\n"
3138                                  "         /Domain [ %f %f ]\n"
3139                                  "         /Function %d 0 R\n",
3140 				 pdf_pattern->pattern_res.id,
3141                                  pat_to_pdf.xx, pat_to_pdf.yx,
3142                                  pat_to_pdf.xy, pat_to_pdf.yy,
3143                                  pat_to_pdf.x0, pat_to_pdf.y0,
3144                                  x1, y1, x2, y2,
3145                                  first_stop, last_stop,
3146                                  color_function.id);
3147 
3148     if (extend == CAIRO_EXTEND_PAD) {
3149         _cairo_output_stream_printf (surface->output,
3150                                      "         /Extend [ true true ]\n");
3151     } else {
3152         _cairo_output_stream_printf (surface->output,
3153                                      "         /Extend [ false false ]\n");
3154     }
3155 
3156     _cairo_output_stream_printf (surface->output,
3157                                  "      >>\n"
3158                                  ">>\n"
3159                                  "endobj\n");
3160 
3161     if (alpha_function.id != 0) {
3162 	cairo_pdf_resource_t mask_resource;
3163 
3164 	assert (pdf_pattern->gstate_res.id != 0);
3165 
3166         /* Create pattern for SMask. */
3167         mask_resource = _cairo_pdf_surface_new_object (surface);
3168 	if (mask_resource.id == 0)
3169 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3170 
3171         _cairo_output_stream_printf (surface->output,
3172                                      "%d 0 obj\n"
3173                                      "<< /Type /Pattern\n"
3174                                      "   /PatternType 2\n"
3175                                      "   /Matrix [ %f %f %f %f %f %f ]\n"
3176                                      "   /Shading\n"
3177                                      "      << /ShadingType 2\n"
3178                                      "         /ColorSpace /DeviceGray\n"
3179                                      "         /Coords [ %f %f %f %f ]\n"
3180 				     "         /Domain [ %f %f ]\n"
3181                                      "         /Function %d 0 R\n",
3182                                      mask_resource.id,
3183                                      pat_to_pdf.xx, pat_to_pdf.yx,
3184                                      pat_to_pdf.xy, pat_to_pdf.yy,
3185                                      pat_to_pdf.x0, pat_to_pdf.y0,
3186                                      x1, y1, x2, y2,
3187 				     first_stop, last_stop,
3188                                      alpha_function.id);
3189 
3190         if (extend == CAIRO_EXTEND_PAD) {
3191             _cairo_output_stream_printf (surface->output,
3192                                          "         /Extend [ true true ]\n");
3193         } else {
3194             _cairo_output_stream_printf (surface->output,
3195                                          "         /Extend [ false false ]\n");
3196         }
3197 
3198         _cairo_output_stream_printf (surface->output,
3199                                      "      >>\n"
3200                                      ">>\n"
3201                                      "endobj\n");
3202         status = _cairo_pdf_surface_add_pattern (surface, mask_resource);
3203         if (unlikely (status))
3204             return status;
3205 
3206 	status = cairo_pdf_surface_emit_transparency_group (surface,
3207 						            pdf_pattern->gstate_res,
3208 							    mask_resource);
3209 	if (unlikely (status))
3210 	    return status;
3211     }
3212 
3213     return _cairo_output_stream_get_status (surface->output);
3214 }
3215 
3216 static cairo_status_t
_cairo_pdf_surface_emit_radial_pattern(cairo_pdf_surface_t * surface,cairo_pdf_pattern_t * pdf_pattern)3217 _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t    *surface,
3218 					cairo_pdf_pattern_t    *pdf_pattern)
3219 {
3220     cairo_pdf_resource_t color_function, alpha_function;
3221     double x1, y1, x2, y2, r1, r2;
3222     cairo_matrix_t pat_to_pdf;
3223     cairo_extend_t extend;
3224     cairo_status_t status;
3225     cairo_radial_pattern_t *pattern = (cairo_radial_pattern_t *) pdf_pattern->pattern;
3226 
3227     assert (pattern->base.n_stops != 0);
3228 
3229     extend = cairo_pattern_get_extend (pdf_pattern->pattern);
3230 
3231     status = _cairo_pdf_surface_emit_pattern_stops (surface,
3232                                                     &pattern->base,
3233                                                     &color_function,
3234                                                     &alpha_function);
3235     if (unlikely (status))
3236 	return status;
3237 
3238     pat_to_pdf = pattern->base.base.matrix;
3239     status = cairo_matrix_invert (&pat_to_pdf);
3240     /* cairo_pattern_set_matrix ensures the matrix is invertible */
3241     assert (status == CAIRO_STATUS_SUCCESS);
3242 
3243     cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
3244     x1 = _cairo_fixed_to_double (pattern->c1.x);
3245     y1 = _cairo_fixed_to_double (pattern->c1.y);
3246     r1 = _cairo_fixed_to_double (pattern->r1);
3247     x2 = _cairo_fixed_to_double (pattern->c2.x);
3248     y2 = _cairo_fixed_to_double (pattern->c2.y);
3249     r2 = _cairo_fixed_to_double (pattern->r2);
3250 
3251     _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
3252 
3253     _cairo_output_stream_printf (surface->output,
3254                                  "%d 0 obj\n"
3255                                  "<< /Type /Pattern\n"
3256                                  "   /PatternType 2\n"
3257                                  "   /Matrix [ %f %f %f %f %f %f ]\n"
3258                                  "   /Shading\n"
3259                                  "      << /ShadingType 3\n"
3260                                  "         /ColorSpace /DeviceRGB\n"
3261                                  "         /Coords [ %f %f %f %f %f %f ]\n"
3262                                  "         /Function %d 0 R\n",
3263 				 pdf_pattern->pattern_res.id,
3264                                  pat_to_pdf.xx, pat_to_pdf.yx,
3265                                  pat_to_pdf.xy, pat_to_pdf.yy,
3266                                  pat_to_pdf.x0, pat_to_pdf.y0,
3267                                  x1, y1, r1, x2, y2, r2,
3268                                  color_function.id);
3269 
3270     if (extend == CAIRO_EXTEND_PAD) {
3271         _cairo_output_stream_printf (surface->output,
3272                                      "         /Extend [ true true ]\n");
3273     } else {
3274         _cairo_output_stream_printf (surface->output,
3275                                      "         /Extend [ false false ]\n");
3276     }
3277 
3278     _cairo_output_stream_printf (surface->output,
3279                                  "      >>\n"
3280                                  ">>\n"
3281                                  "endobj\n");
3282 
3283     if (alpha_function.id != 0) {
3284 	cairo_pdf_resource_t mask_resource;
3285 
3286 	assert (pdf_pattern->gstate_res.id != 0);
3287 
3288 	/* Create pattern for SMask. */
3289         mask_resource = _cairo_pdf_surface_new_object (surface);
3290 	if (mask_resource.id == 0)
3291 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3292 
3293         _cairo_output_stream_printf (surface->output,
3294                                      "%d 0 obj\n"
3295                                      "<< /Type /Pattern\n"
3296                                      "   /PatternType 2\n"
3297                                      "   /Matrix [ %f %f %f %f %f %f ]\n"
3298                                      "   /Shading\n"
3299                                      "      << /ShadingType 3\n"
3300                                      "         /ColorSpace /DeviceGray\n"
3301                                      "         /Coords [ %f %f %f %f %f %f ]\n"
3302                                      "         /Function %d 0 R\n",
3303                                      mask_resource.id,
3304                                      pat_to_pdf.xx, pat_to_pdf.yx,
3305                                      pat_to_pdf.xy, pat_to_pdf.yy,
3306                                      pat_to_pdf.x0, pat_to_pdf.y0,
3307                                      x1, y1, r1, x2, y2, r2,
3308                                      alpha_function.id);
3309 
3310         if (extend == CAIRO_EXTEND_PAD) {
3311             _cairo_output_stream_printf (surface->output,
3312                                          "         /Extend [ true true ]\n");
3313         } else {
3314             _cairo_output_stream_printf (surface->output,
3315                                          "         /Extend [ false false ]\n");
3316         }
3317 
3318         _cairo_output_stream_printf (surface->output,
3319                                      "      >>\n"
3320                                      ">>\n"
3321                                      "endobj\n");
3322 
3323 	status = cairo_pdf_surface_emit_transparency_group (surface,
3324 						            pdf_pattern->gstate_res,
3325 							    mask_resource);
3326 	if (unlikely (status))
3327 	    return status;
3328     }
3329 
3330     return _cairo_output_stream_get_status (surface->output);
3331 }
3332 
3333 static cairo_status_t
_cairo_pdf_surface_emit_pattern(cairo_pdf_surface_t * surface,cairo_pdf_pattern_t * pdf_pattern)3334 _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
3335 {
3336     double old_width, old_height;
3337     cairo_status_t status;
3338 
3339     old_width = surface->width;
3340     old_height = surface->height;
3341     _cairo_pdf_surface_set_size_internal (surface,
3342 					  pdf_pattern->width,
3343 					  pdf_pattern->height);
3344 
3345     switch (pdf_pattern->pattern->type) {
3346     case CAIRO_PATTERN_TYPE_SOLID:
3347 	ASSERT_NOT_REACHED;
3348 	status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3349 	break;
3350 
3351     case CAIRO_PATTERN_TYPE_SURFACE:
3352 	status = _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
3353 	break;
3354 
3355     case CAIRO_PATTERN_TYPE_LINEAR:
3356 	status = _cairo_pdf_surface_emit_linear_pattern (surface, pdf_pattern);
3357 	break;
3358 
3359     case CAIRO_PATTERN_TYPE_RADIAL:
3360 	status = _cairo_pdf_surface_emit_radial_pattern (surface, pdf_pattern);
3361 	break;
3362 
3363     default:
3364 	ASSERT_NOT_REACHED;
3365 	status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3366 	break;
3367     }
3368 
3369     _cairo_pdf_surface_set_size_internal (surface,
3370 					  old_width,
3371 					  old_height);
3372 
3373     return status;
3374 }
3375 
3376 static cairo_status_t
_cairo_pdf_surface_paint_surface_pattern(cairo_pdf_surface_t * surface,cairo_surface_pattern_t * source)3377 _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t     *surface,
3378 					  cairo_surface_pattern_t *source)
3379 {
3380     cairo_pdf_resource_t surface_res;
3381     int width, height;
3382     cairo_matrix_t cairo_p2d, pdf_p2d;
3383     cairo_status_t status;
3384     int alpha;
3385 
3386     status = _cairo_pdf_surface_add_source_surface (surface,
3387 						    source->surface,
3388 						    source->base.filter,
3389 						    &surface_res,
3390 						    &width,
3391 						    &height);
3392     if (unlikely (status))
3393 	return status;
3394 
3395     cairo_p2d = source->base.matrix;
3396     status = cairo_matrix_invert (&cairo_p2d);
3397     /* cairo_pattern_set_matrix ensures the matrix is invertible */
3398     assert (status == CAIRO_STATUS_SUCCESS);
3399 
3400     pdf_p2d = surface->cairo_to_pdf;
3401     cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
3402     cairo_matrix_translate (&pdf_p2d, 0.0, height);
3403     cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
3404     if (source->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
3405 	cairo_matrix_scale (&pdf_p2d, width, height);
3406 
3407     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3408     if (unlikely (status))
3409 	return status;
3410 
3411     if (! _cairo_matrix_is_identity (&pdf_p2d)) {
3412 	_cairo_output_stream_printf (surface->output,
3413 				     "%f %f %f %f %f %f cm\n",
3414 				     pdf_p2d.xx, pdf_p2d.yx,
3415 				     pdf_p2d.xy, pdf_p2d.yy,
3416 				     pdf_p2d.x0, pdf_p2d.y0);
3417     }
3418 
3419     status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
3420     if (unlikely (status))
3421 	return status;
3422 
3423     _cairo_output_stream_printf (surface->output,
3424 				 "/a%d gs /x%d Do\n",
3425 				 alpha,
3426 				 surface_res.id);
3427 
3428     return _cairo_pdf_surface_add_xobject (surface, surface_res);
3429 }
3430 
3431 static cairo_status_t
_cairo_pdf_surface_select_operator(cairo_pdf_surface_t * surface,cairo_operator_t op)3432 _cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface,
3433 				    cairo_operator_t     op)
3434 {
3435     cairo_status_t status;
3436 
3437     if (op == surface->current_operator)
3438 	return CAIRO_STATUS_SUCCESS;
3439 
3440     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3441     if (unlikely (status))
3442 	return status;
3443 
3444     _cairo_output_stream_printf (surface->output,
3445 				 "/b%d gs\n", op);
3446     surface->current_operator = op;
3447     _cairo_pdf_surface_add_operator (surface, op);
3448 
3449     return CAIRO_STATUS_SUCCESS;
3450 }
3451 
3452 static cairo_status_t
_cairo_pdf_surface_select_pattern(cairo_pdf_surface_t * surface,const cairo_pattern_t * pattern,cairo_pdf_resource_t pattern_res,cairo_bool_t is_stroke)3453 _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
3454 				   const cairo_pattern_t     *pattern,
3455 				   cairo_pdf_resource_t pattern_res,
3456 				   cairo_bool_t         is_stroke)
3457 {
3458     cairo_status_t status;
3459     int alpha;
3460     const cairo_color_t *solid_color = NULL;
3461 
3462     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
3463 	const cairo_solid_pattern_t *solid = (const cairo_solid_pattern_t *) pattern;
3464 
3465 	solid_color = &solid->color;
3466     }
3467 
3468     if (solid_color != NULL) {
3469 	if (surface->current_pattern_is_solid_color == FALSE ||
3470 	    surface->current_color_red != solid_color->red ||
3471 	    surface->current_color_green != solid_color->green ||
3472 	    surface->current_color_blue != solid_color->blue ||
3473 	    surface->current_color_is_stroke != is_stroke)
3474 	{
3475 	    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3476 	    if (unlikely (status))
3477 		return status;
3478 
3479 	    _cairo_output_stream_printf (surface->output,
3480 					 "%f %f %f ",
3481 					 solid_color->red,
3482 					 solid_color->green,
3483 					 solid_color->blue);
3484 
3485 	    if (is_stroke)
3486 		_cairo_output_stream_printf (surface->output, "RG ");
3487 	    else
3488 		_cairo_output_stream_printf (surface->output, "rg ");
3489 
3490 	    surface->current_color_red = solid_color->red;
3491 	    surface->current_color_green = solid_color->green;
3492 	    surface->current_color_blue = solid_color->blue;
3493 	    surface->current_color_is_stroke = is_stroke;
3494 	}
3495 
3496 	if (surface->current_pattern_is_solid_color == FALSE ||
3497 	    surface->current_color_alpha != solid_color->alpha)
3498 	{
3499 	    status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha);
3500 	    if (unlikely (status))
3501 		return status;
3502 
3503 	    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3504 	    if (unlikely (status))
3505 		return status;
3506 
3507 	    _cairo_output_stream_printf (surface->output,
3508 					 "/a%d gs\n",
3509 					 alpha);
3510 	    surface->current_color_alpha = solid_color->alpha;
3511 	}
3512 
3513 	surface->current_pattern_is_solid_color = TRUE;
3514     } else {
3515 	status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
3516 	if (unlikely (status))
3517 	    return status;
3518 
3519 	status = _cairo_pdf_surface_add_pattern (surface, pattern_res);
3520 	if (unlikely (status))
3521 	    return status;
3522 
3523 	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3524 	if (unlikely (status))
3525 	    return status;
3526 
3527 	/* fill-stroke calls select_pattern twice. Don't save if the
3528 	 * gstate is already saved. */
3529 	if (!surface->select_pattern_gstate_saved)
3530 	    _cairo_output_stream_printf (surface->output, "q ");
3531 
3532 	if (is_stroke) {
3533 	    _cairo_output_stream_printf (surface->output,
3534 					 "/Pattern CS /p%d SCN ",
3535 					 pattern_res.id);
3536 	} else {
3537 	    _cairo_output_stream_printf (surface->output,
3538 					 "/Pattern cs /p%d scn ",
3539 					 pattern_res.id);
3540 	}
3541 	_cairo_output_stream_printf (surface->output,
3542 				     "/a%d gs\n",
3543 				     alpha);
3544 	surface->select_pattern_gstate_saved = TRUE;
3545 	surface->current_pattern_is_solid_color = FALSE;
3546     }
3547 
3548     return _cairo_output_stream_get_status (surface->output);
3549 }
3550 
3551 static cairo_int_status_t
_cairo_pdf_surface_unselect_pattern(cairo_pdf_surface_t * surface)3552 _cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
3553 {
3554     cairo_int_status_t status;
3555 
3556     if (surface->select_pattern_gstate_saved) {
3557 	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3558 	if (unlikely (status))
3559 	    return status;
3560 
3561 	_cairo_output_stream_printf (surface->output, "Q\n");
3562 	_cairo_pdf_operators_reset (&surface->pdf_operators);
3563 	surface->current_pattern_is_solid_color = FALSE;
3564     }
3565     surface->select_pattern_gstate_saved = FALSE;
3566 
3567     return CAIRO_STATUS_SUCCESS;
3568 }
3569 
3570 static cairo_int_status_t
_cairo_pdf_surface_show_page(void * abstract_surface)3571 _cairo_pdf_surface_show_page (void *abstract_surface)
3572 {
3573     cairo_pdf_surface_t *surface = abstract_surface;
3574     cairo_int_status_t status;
3575 
3576     status = _cairo_pdf_surface_close_content_stream (surface);
3577     if (unlikely (status))
3578 	return status;
3579 
3580     _cairo_surface_clipper_reset (&surface->clipper);
3581 
3582     status = _cairo_pdf_surface_write_page (surface);
3583     if (unlikely (status))
3584 	return status;
3585 
3586     _cairo_pdf_surface_clear (surface);
3587 
3588     return CAIRO_STATUS_SUCCESS;
3589 }
3590 
3591 static cairo_bool_t
_cairo_pdf_surface_get_extents(void * abstract_surface,cairo_rectangle_int_t * rectangle)3592 _cairo_pdf_surface_get_extents (void		        *abstract_surface,
3593 				cairo_rectangle_int_t   *rectangle)
3594 {
3595     cairo_pdf_surface_t *surface = abstract_surface;
3596 
3597     rectangle->x = 0;
3598     rectangle->y = 0;
3599 
3600     /* XXX: The conversion to integers here is pretty bogus, (not to
3601      * mention the arbitrary limitation of width to a short(!). We
3602      * may need to come up with a better interface for get_size.
3603      */
3604     rectangle->width  = ceil (surface->width);
3605     rectangle->height = ceil (surface->height);
3606 
3607     return TRUE;
3608 }
3609 
3610 static void
_cairo_pdf_surface_get_font_options(void * abstract_surface,cairo_font_options_t * options)3611 _cairo_pdf_surface_get_font_options (void                  *abstract_surface,
3612 				     cairo_font_options_t  *options)
3613 {
3614     _cairo_font_options_init_default (options);
3615 
3616     cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
3617     cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
3618     cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
3619 }
3620 
3621 static cairo_pdf_resource_t
_cairo_pdf_surface_write_info(cairo_pdf_surface_t * surface)3622 _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface)
3623 {
3624     cairo_pdf_resource_t info;
3625 
3626     info = _cairo_pdf_surface_new_object (surface);
3627     if (info.id == 0)
3628 	return info;
3629 
3630     _cairo_output_stream_printf (surface->output,
3631 				 "%d 0 obj\n"
3632 				 "<< /Creator (cairo %s (http://cairographics.org))\n"
3633 				 "   /Producer (cairo %s (http://cairographics.org))\n"
3634 				 ">>\n"
3635 				 "endobj\n",
3636 				 info.id,
3637                                  cairo_version_string (),
3638                                  cairo_version_string ());
3639 
3640     return info;
3641 }
3642 
3643 static void
_cairo_pdf_surface_write_pages(cairo_pdf_surface_t * surface)3644 _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
3645 {
3646     cairo_pdf_resource_t page;
3647     int num_pages, i;
3648 
3649     _cairo_pdf_surface_update_object (surface, surface->pages_resource);
3650     _cairo_output_stream_printf (surface->output,
3651 				 "%d 0 obj\n"
3652 				 "<< /Type /Pages\n"
3653 				 "   /Kids [ ",
3654 				 surface->pages_resource.id);
3655 
3656     num_pages = _cairo_array_num_elements (&surface->pages);
3657     for (i = 0; i < num_pages; i++) {
3658 	_cairo_array_copy_element (&surface->pages, i, &page);
3659 	_cairo_output_stream_printf (surface->output, "%d 0 R ", page.id);
3660     }
3661 
3662     _cairo_output_stream_printf (surface->output, "]\n");
3663     _cairo_output_stream_printf (surface->output, "   /Count %d\n", num_pages);
3664 
3665 
3666     /* TODO: Figure out which other defaults to be inherited by /Page
3667      * objects. */
3668     _cairo_output_stream_printf (surface->output,
3669 				 ">>\n"
3670 				 "endobj\n");
3671 }
3672 
3673 static cairo_status_t
_cairo_pdf_surface_emit_unicode_for_glyph(cairo_pdf_surface_t * surface,const char * utf8)3674 _cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t	*surface,
3675 					   const char 		*utf8)
3676 {
3677     uint16_t *utf16 = NULL;
3678     int utf16_len = 0;
3679     cairo_status_t status;
3680     int i;
3681 
3682     if (utf8 && *utf8) {
3683 	status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
3684 	if (unlikely (status))
3685 	    return status;
3686     }
3687 
3688     _cairo_output_stream_printf (surface->output, "<");
3689     if (utf16 == NULL || utf16_len == 0) {
3690 	/* According to the "ToUnicode Mapping File Tutorial"
3691 	 * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
3692 	 *
3693 	 * Glyphs that do not map to a Unicode code point must be
3694 	 * mapped to 0xfffd "REPLACEMENT CHARACTER".
3695 	 */
3696 	_cairo_output_stream_printf (surface->output,
3697 				     "fffd");
3698     } else {
3699 	for (i = 0; i < utf16_len; i++)
3700 	    _cairo_output_stream_printf (surface->output,
3701 					 "%04x", (int) (utf16[i]));
3702     }
3703     _cairo_output_stream_printf (surface->output, ">");
3704 
3705     if (utf16)
3706 	free (utf16);
3707 
3708     return CAIRO_STATUS_SUCCESS;
3709 }
3710 
3711 /* Bob Jenkins hash
3712  *
3713  * Public domain code from:
3714  *   http://burtleburtle.net/bob/hash/doobs.html
3715  */
3716 
3717 #define HASH_MIX(a,b,c) 		\
3718 { 					\
3719     a -= b; a -= c; a ^= (c>>13);	\
3720     b -= c; b -= a; b ^= (a<<8);	\
3721     c -= a; c -= b; c ^= (b>>13);	\
3722     a -= b; a -= c; a ^= (c>>12);	\
3723     b -= c; b -= a; b ^= (a<<16);	\
3724     c -= a; c -= b; c ^= (b>>5);	\
3725     a -= b; a -= c; a ^= (c>>3);	\
3726     b -= c; b -= a; b ^= (a<<10);	\
3727     c -= a; c -= b; c ^= (b>>15);	\
3728 }
3729 
3730 static uint32_t
_hash_data(const unsigned char * data,int length,uint32_t initval)3731 _hash_data (const unsigned char *data, int length, uint32_t initval)
3732 {
3733     uint32_t a, b, c, len;
3734 
3735     len = length;
3736     a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
3737     c = initval;         /* the previous hash value */
3738 
3739     while (len >= 12) {
3740 	a += (data[0] + ((uint32_t)data[1]<<8) + ((uint32_t)data[2]<<16) + ((uint32_t)data[3]<<24));
3741 	b += (data[4] + ((uint32_t)data[5]<<8) + ((uint32_t)data[6]<<16) + ((uint32_t)data[7]<<24));
3742 	c += (data[8] + ((uint32_t)data[9]<<8) + ((uint32_t)data[10]<<16)+ ((uint32_t)data[11]<<24));
3743 	HASH_MIX (a,b,c);
3744 	data += 12;
3745 	len -= 12;
3746     }
3747 
3748     c += length;
3749     switch(len) {
3750     case 11: c+= ((uint32_t) data[10] << 24);
3751     case 10: c+= ((uint32_t) data[9] << 16);
3752     case 9 : c+= ((uint32_t) data[8] << 8);
3753     case 8 : b+= ((uint32_t) data[7] << 24);
3754     case 7 : b+= ((uint32_t) data[6] << 16);
3755     case 6 : b+= ((uint32_t) data[5] << 8);
3756     case 5 : b+= data[4];
3757     case 4 : a+= ((uint32_t) data[3] << 24);
3758     case 3 : a+= ((uint32_t) data[2] << 16);
3759     case 2 : a+= ((uint32_t) data[1] << 8);
3760     case 1 : a+= data[0];
3761     }
3762     HASH_MIX (a,b,c);
3763 
3764     return c;
3765 }
3766 
3767 static void
_create_font_subset_tag(cairo_scaled_font_subset_t * font_subset,const char * font_name,char * tag)3768 _create_font_subset_tag (cairo_scaled_font_subset_t	*font_subset,
3769 			 const char 			*font_name,
3770 			 char				*tag)
3771 {
3772     uint32_t hash;
3773     int i;
3774     long numerator;
3775     ldiv_t d;
3776 
3777     hash = _hash_data ((unsigned char *) font_name, strlen(font_name), 0);
3778     hash = _hash_data ((unsigned char *) (font_subset->glyphs),
3779 		       font_subset->num_glyphs * sizeof(unsigned long), hash);
3780 
3781     numerator = abs (hash);
3782     for (i = 0; i < 6; i++) {
3783 	d = ldiv (numerator, 26);
3784 	numerator = d.quot;
3785         tag[i] = 'A' + d.rem;
3786     }
3787     tag[i] = 0;
3788 }
3789 
3790 static cairo_int_status_t
_cairo_pdf_surface_emit_to_unicode_stream(cairo_pdf_surface_t * surface,cairo_scaled_font_subset_t * font_subset,cairo_bool_t is_composite,cairo_pdf_resource_t * stream)3791 _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t		*surface,
3792 					   cairo_scaled_font_subset_t	*font_subset,
3793                                            cairo_bool_t                  is_composite,
3794 					   cairo_pdf_resource_t         *stream)
3795 {
3796     unsigned int i, num_bfchar;
3797     cairo_int_status_t status;
3798 
3799     stream->id = 0;
3800 
3801     status = _cairo_pdf_surface_open_stream (surface,
3802 					      NULL,
3803 					      surface->compress_content,
3804 					      NULL);
3805     if (unlikely (status))
3806 	return status;
3807 
3808     _cairo_output_stream_printf (surface->output,
3809                                  "/CIDInit /ProcSet findresource begin\n"
3810                                  "12 dict begin\n"
3811                                  "begincmap\n"
3812                                  "/CIDSystemInfo\n"
3813                                  "<< /Registry (Adobe)\n"
3814                                  "   /Ordering (UCS)\n"
3815                                  "   /Supplement 0\n"
3816                                  ">> def\n"
3817                                  "/CMapName /Adobe-Identity-UCS def\n"
3818                                  "/CMapType 2 def\n"
3819                                  "1 begincodespacerange\n");
3820 
3821     if (is_composite) {
3822         _cairo_output_stream_printf (surface->output,
3823                                      "<0000> <ffff>\n");
3824     } else {
3825         _cairo_output_stream_printf (surface->output,
3826                                      "<00> <ff>\n");
3827     }
3828 
3829     _cairo_output_stream_printf (surface->output,
3830                                   "endcodespacerange\n");
3831 
3832     if (font_subset->is_scaled) {
3833 	/* Type 3 fonts include glyph 0 in the subset */
3834 	num_bfchar = font_subset->num_glyphs;
3835 
3836 	/* The CMap specification has a limit of 100 characters per beginbfchar operator */
3837 	_cairo_output_stream_printf (surface->output,
3838 				     "%d beginbfchar\n",
3839 				     num_bfchar > 100 ? 100 : num_bfchar);
3840 
3841 	for (i = 0; i < num_bfchar; i++) {
3842 	    if (i != 0 && i % 100 == 0) {
3843 		_cairo_output_stream_printf (surface->output,
3844 					     "endbfchar\n"
3845 					     "%d beginbfchar\n",
3846 					     num_bfchar - i > 100 ? 100 : num_bfchar - i);
3847 	    }
3848 	    _cairo_output_stream_printf (surface->output, "<%02x> ", i);
3849 	    status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
3850 								font_subset->utf8[i]);
3851 	    if (unlikely (status))
3852 		return status;
3853 
3854 	    _cairo_output_stream_printf (surface->output,
3855 					 "\n");
3856 	}
3857     } else {
3858 	/* Other fonts reserve glyph 0 for .notdef. Omit glyph 0 from the /ToUnicode map */
3859 	num_bfchar = font_subset->num_glyphs - 1;
3860 
3861 	/* The CMap specification has a limit of 100 characters per beginbfchar operator */
3862 	_cairo_output_stream_printf (surface->output,
3863 				     "%d beginbfchar\n",
3864 				     num_bfchar > 100 ? 100 : num_bfchar);
3865 
3866 	for (i = 0; i < num_bfchar; i++) {
3867 	    if (i != 0 && i % 100 == 0) {
3868 		_cairo_output_stream_printf (surface->output,
3869 					     "endbfchar\n"
3870 					     "%d beginbfchar\n",
3871 					     num_bfchar - i > 100 ? 100 : num_bfchar - i);
3872 	    }
3873 	    if (is_composite)
3874 		_cairo_output_stream_printf (surface->output, "<%04x> ", i + 1);
3875 	    else
3876 		_cairo_output_stream_printf (surface->output, "<%02x> ", i + 1);
3877 
3878 	    status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
3879 								font_subset->utf8[i + 1]);
3880 	    if (unlikely (status))
3881 		return status;
3882 
3883 	    _cairo_output_stream_printf (surface->output,
3884 					 "\n");
3885 	}
3886     }
3887 
3888     _cairo_output_stream_printf (surface->output,
3889                                  "endbfchar\n");
3890 
3891     _cairo_output_stream_printf (surface->output,
3892                                  "endcmap\n"
3893                                  "CMapName currentdict /CMap defineresource pop\n"
3894                                  "end\n"
3895                                  "end\n");
3896 
3897     *stream = surface->pdf_stream.self;
3898     return _cairo_pdf_surface_close_stream (surface);
3899 }
3900 
3901 #define PDF_UNITS_PER_EM 1000
3902 
3903 static cairo_status_t
_cairo_pdf_surface_emit_cff_font(cairo_pdf_surface_t * surface,cairo_scaled_font_subset_t * font_subset,cairo_cff_subset_t * subset)3904 _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t		*surface,
3905                                   cairo_scaled_font_subset_t	*font_subset,
3906                                   cairo_cff_subset_t            *subset)
3907 {
3908     cairo_pdf_resource_t stream, descriptor, cidfont_dict;
3909     cairo_pdf_resource_t subset_resource, to_unicode_stream;
3910     cairo_pdf_font_t font;
3911     unsigned int i;
3912     cairo_status_t status;
3913     char tag[10];
3914 
3915     _create_font_subset_tag (font_subset, subset->ps_name, tag);
3916 
3917     subset_resource = _cairo_pdf_surface_get_font_resource (surface,
3918 							    font_subset->font_id,
3919 							    font_subset->subset_id);
3920     if (subset_resource.id == 0)
3921 	return CAIRO_STATUS_SUCCESS;
3922 
3923     status = _cairo_pdf_surface_open_stream (surface,
3924 					     NULL,
3925 					     TRUE,
3926 					     "   /Subtype /CIDFontType0C\n");
3927     if (unlikely (status))
3928 	return status;
3929 
3930     stream = surface->pdf_stream.self;
3931     _cairo_output_stream_write (surface->output,
3932 				subset->data, subset->data_length);
3933     status = _cairo_pdf_surface_close_stream (surface);
3934     if (unlikely (status))
3935 	return status;
3936 
3937     status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
3938 	                                                font_subset, TRUE,
3939 							&to_unicode_stream);
3940     if (_cairo_status_is_error (status))
3941 	return status;
3942 
3943     descriptor = _cairo_pdf_surface_new_object (surface);
3944     if (descriptor.id == 0)
3945 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3946 
3947     _cairo_output_stream_printf (surface->output,
3948 				 "%d 0 obj\n"
3949 				 "<< /Type /FontDescriptor\n"
3950 				 "   /FontName /%s+%s\n",
3951 				 descriptor.id,
3952 				 tag,
3953 				 subset->ps_name);
3954 
3955     if (subset->font_name) {
3956 	_cairo_output_stream_printf (surface->output,
3957 				     "   /FontFamily (%s)\n",
3958 				     subset->font_name);
3959     }
3960 
3961     _cairo_output_stream_printf (surface->output,
3962 				 "   /Flags 4\n"
3963 				 "   /FontBBox [ %ld %ld %ld %ld ]\n"
3964 				 "   /ItalicAngle 0\n"
3965 				 "   /Ascent %ld\n"
3966 				 "   /Descent %ld\n"
3967 				 "   /CapHeight %ld\n"
3968 				 "   /StemV 80\n"
3969 				 "   /StemH 80\n"
3970 				 "   /FontFile3 %u 0 R\n"
3971 				 ">>\n"
3972 				 "endobj\n",
3973 				 (long)(subset->x_min*PDF_UNITS_PER_EM),
3974 				 (long)(subset->y_min*PDF_UNITS_PER_EM),
3975 				 (long)(subset->x_max*PDF_UNITS_PER_EM),
3976 				 (long)(subset->y_max*PDF_UNITS_PER_EM),
3977 				 (long)(subset->ascent*PDF_UNITS_PER_EM),
3978 				 (long)(subset->descent*PDF_UNITS_PER_EM),
3979 				 (long)(subset->y_max*PDF_UNITS_PER_EM),
3980 				 stream.id);
3981 
3982     cidfont_dict = _cairo_pdf_surface_new_object (surface);
3983     if (cidfont_dict.id == 0)
3984 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3985 
3986     _cairo_output_stream_printf (surface->output,
3987                                  "%d 0 obj\n"
3988                                  "<< /Type /Font\n"
3989                                  "   /Subtype /CIDFontType0\n"
3990                                  "   /BaseFont /%s+%s\n"
3991                                  "   /CIDSystemInfo\n"
3992                                  "   << /Registry (Adobe)\n"
3993                                  "      /Ordering (Identity)\n"
3994                                  "      /Supplement 0\n"
3995                                  "   >>\n"
3996                                  "   /FontDescriptor %d 0 R\n"
3997                                  "   /W [0 [",
3998                                  cidfont_dict.id,
3999 				 tag,
4000                                  subset->ps_name,
4001                                  descriptor.id);
4002 
4003     for (i = 0; i < font_subset->num_glyphs; i++)
4004 	_cairo_output_stream_printf (surface->output,
4005 				     " %ld",
4006                                      (long)(subset->widths[i]*PDF_UNITS_PER_EM));
4007 
4008     _cairo_output_stream_printf (surface->output,
4009                                  " ]]\n"
4010 				 ">>\n"
4011 				 "endobj\n");
4012 
4013     _cairo_pdf_surface_update_object (surface, subset_resource);
4014     _cairo_output_stream_printf (surface->output,
4015 				 "%d 0 obj\n"
4016 				 "<< /Type /Font\n"
4017 				 "   /Subtype /Type0\n"
4018 				 "   /BaseFont /%s+%s\n"
4019                                  "   /Encoding /Identity-H\n"
4020 				 "   /DescendantFonts [ %d 0 R]\n",
4021 				 subset_resource.id,
4022 				 tag,
4023 				 subset->ps_name,
4024 				 cidfont_dict.id);
4025 
4026     if (to_unicode_stream.id != 0)
4027         _cairo_output_stream_printf (surface->output,
4028                                      "   /ToUnicode %d 0 R\n",
4029                                      to_unicode_stream.id);
4030 
4031     _cairo_output_stream_printf (surface->output,
4032 				 ">>\n"
4033 				 "endobj\n");
4034 
4035     font.font_id = font_subset->font_id;
4036     font.subset_id = font_subset->subset_id;
4037     font.subset_resource = subset_resource;
4038     status = _cairo_array_append (&surface->fonts, &font);
4039 
4040     return status;
4041 }
4042 
4043 static cairo_status_t
_cairo_pdf_surface_emit_cff_font_subset(cairo_pdf_surface_t * surface,cairo_scaled_font_subset_t * font_subset)4044 _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t	     *surface,
4045                                          cairo_scaled_font_subset_t  *font_subset)
4046 {
4047     cairo_status_t status;
4048     cairo_cff_subset_t subset;
4049     char name[64];
4050 
4051     snprintf (name, sizeof name, "CairoFont-%d-%d",
4052               font_subset->font_id, font_subset->subset_id);
4053     status = _cairo_cff_subset_init (&subset, name, font_subset);
4054     if (unlikely (status))
4055         return status;
4056 
4057     status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
4058 
4059     _cairo_cff_subset_fini (&subset);
4060 
4061     return status;
4062 }
4063 
4064 static cairo_status_t
_cairo_pdf_surface_emit_cff_fallback_font(cairo_pdf_surface_t * surface,cairo_scaled_font_subset_t * font_subset)4065 _cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t	       *surface,
4066                                            cairo_scaled_font_subset_t  *font_subset)
4067 {
4068     cairo_status_t status;
4069     cairo_cff_subset_t subset;
4070     char name[64];
4071 
4072     snprintf (name, sizeof name, "CairoFont-%d-%d",
4073               font_subset->font_id, font_subset->subset_id);
4074     status = _cairo_cff_fallback_init (&subset, name, font_subset);
4075     if (unlikely (status))
4076         return status;
4077 
4078     status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
4079 
4080     _cairo_cff_fallback_fini (&subset);
4081 
4082     return status;
4083 }
4084 
4085 static cairo_status_t
_cairo_pdf_surface_emit_type1_font(cairo_pdf_surface_t * surface,cairo_scaled_font_subset_t * font_subset,cairo_type1_subset_t * subset)4086 _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
4087                                     cairo_scaled_font_subset_t	*font_subset,
4088                                     cairo_type1_subset_t        *subset)
4089 {
4090     cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
4091     cairo_pdf_font_t font;
4092     cairo_status_t status;
4093     unsigned long length;
4094     unsigned int i;
4095     char tag[10];
4096 
4097     _create_font_subset_tag (font_subset, subset->base_font, tag);
4098 
4099     subset_resource = _cairo_pdf_surface_get_font_resource (surface,
4100 							    font_subset->font_id,
4101 							    font_subset->subset_id);
4102     if (subset_resource.id == 0)
4103 	return CAIRO_STATUS_SUCCESS;
4104 
4105     length = subset->header_length + subset->data_length + subset->trailer_length;
4106     status = _cairo_pdf_surface_open_stream (surface,
4107 					     NULL,
4108 					     TRUE,
4109 					     "   /Length1 %lu\n"
4110 					     "   /Length2 %lu\n"
4111 					     "   /Length3 %lu\n",
4112 					     subset->header_length,
4113 					     subset->data_length,
4114 					     subset->trailer_length);
4115     if (unlikely (status))
4116 	return status;
4117 
4118     stream = surface->pdf_stream.self;
4119     _cairo_output_stream_write (surface->output, subset->data, length);
4120     status = _cairo_pdf_surface_close_stream (surface);
4121     if (unlikely (status))
4122 	return status;
4123 
4124     status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
4125 	                                                font_subset, FALSE,
4126 							&to_unicode_stream);
4127     if (_cairo_status_is_error (status))
4128 	return status;
4129 
4130     descriptor = _cairo_pdf_surface_new_object (surface);
4131     if (descriptor.id == 0)
4132 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4133 
4134     _cairo_output_stream_printf (surface->output,
4135 				 "%d 0 obj\n"
4136 				 "<< /Type /FontDescriptor\n"
4137 				 "   /FontName /%s+%s\n"
4138 				 "   /Flags 4\n"
4139 				 "   /FontBBox [ %ld %ld %ld %ld ]\n"
4140 				 "   /ItalicAngle 0\n"
4141 				 "   /Ascent %ld\n"
4142 				 "   /Descent %ld\n"
4143 				 "   /CapHeight %ld\n"
4144 				 "   /StemV 80\n"
4145 				 "   /StemH 80\n"
4146 				 "   /FontFile %u 0 R\n"
4147 				 ">>\n"
4148 				 "endobj\n",
4149 				 descriptor.id,
4150 				 tag,
4151 				 subset->base_font,
4152 				 (long)(subset->x_min*PDF_UNITS_PER_EM),
4153 				 (long)(subset->y_min*PDF_UNITS_PER_EM),
4154 				 (long)(subset->x_max*PDF_UNITS_PER_EM),
4155 				 (long)(subset->y_max*PDF_UNITS_PER_EM),
4156 				 (long)(subset->ascent*PDF_UNITS_PER_EM),
4157 				 (long)(subset->descent*PDF_UNITS_PER_EM),
4158 				 (long)(subset->y_max*PDF_UNITS_PER_EM),
4159 				 stream.id);
4160 
4161     _cairo_pdf_surface_update_object (surface, subset_resource);
4162     _cairo_output_stream_printf (surface->output,
4163 				 "%d 0 obj\n"
4164 				 "<< /Type /Font\n"
4165 				 "   /Subtype /Type1\n"
4166 				 "   /BaseFont /%s+%s\n"
4167 				 "   /FirstChar 0\n"
4168 				 "   /LastChar %d\n"
4169 				 "   /FontDescriptor %d 0 R\n"
4170 				 "   /Widths [",
4171 				 subset_resource.id,
4172 				 tag,
4173 				 subset->base_font,
4174 				 font_subset->num_glyphs - 1,
4175 				 descriptor.id);
4176 
4177     for (i = 0; i < font_subset->num_glyphs; i++)
4178 	_cairo_output_stream_printf (surface->output,
4179 				     " %ld",
4180                                      (long)(subset->widths[i]*PDF_UNITS_PER_EM));
4181 
4182     _cairo_output_stream_printf (surface->output,
4183 				 " ]\n");
4184 
4185     if (to_unicode_stream.id != 0)
4186         _cairo_output_stream_printf (surface->output,
4187                                      "    /ToUnicode %d 0 R\n",
4188                                      to_unicode_stream.id);
4189 
4190     _cairo_output_stream_printf (surface->output,
4191 				 ">>\n"
4192 				 "endobj\n");
4193 
4194     font.font_id = font_subset->font_id;
4195     font.subset_id = font_subset->subset_id;
4196     font.subset_resource = subset_resource;
4197     return _cairo_array_append (&surface->fonts, &font);
4198 }
4199 
4200 #if CAIRO_HAS_FT_FONT
4201 static cairo_status_t
_cairo_pdf_surface_emit_type1_font_subset(cairo_pdf_surface_t * surface,cairo_scaled_font_subset_t * font_subset)4202 _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t		*surface,
4203 					   cairo_scaled_font_subset_t	*font_subset)
4204 {
4205     cairo_status_t status;
4206     cairo_type1_subset_t subset;
4207     char name[64];
4208 
4209     snprintf (name, sizeof name, "CairoFont-%d-%d",
4210 	      font_subset->font_id, font_subset->subset_id);
4211     status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE);
4212     if (unlikely (status))
4213 	return status;
4214 
4215     status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
4216 
4217     _cairo_type1_subset_fini (&subset);
4218     return status;
4219 }
4220 #endif
4221 
4222 static cairo_status_t
_cairo_pdf_surface_emit_type1_fallback_font(cairo_pdf_surface_t * surface,cairo_scaled_font_subset_t * font_subset)4223 _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t	*surface,
4224                                              cairo_scaled_font_subset_t	*font_subset)
4225 {
4226     cairo_status_t status;
4227     cairo_type1_subset_t subset;
4228     char name[64];
4229 
4230     snprintf (name, sizeof name, "CairoFont-%d-%d",
4231 	      font_subset->font_id, font_subset->subset_id);
4232     status = _cairo_type1_fallback_init_binary (&subset, name, font_subset);
4233     if (unlikely (status))
4234 	return status;
4235 
4236     status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
4237 
4238     _cairo_type1_fallback_fini (&subset);
4239     return status;
4240 }
4241 
4242 static cairo_status_t
_cairo_pdf_surface_emit_truetype_font_subset(cairo_pdf_surface_t * surface,cairo_scaled_font_subset_t * font_subset)4243 _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
4244 					      cairo_scaled_font_subset_t	*font_subset)
4245 {
4246     cairo_pdf_resource_t stream, descriptor, cidfont_dict;
4247     cairo_pdf_resource_t subset_resource, to_unicode_stream;
4248     cairo_status_t status;
4249     cairo_pdf_font_t font;
4250     cairo_truetype_subset_t subset;
4251     unsigned int i;
4252     char tag[10];
4253 
4254     subset_resource = _cairo_pdf_surface_get_font_resource (surface,
4255 							    font_subset->font_id,
4256 							    font_subset->subset_id);
4257     if (subset_resource.id == 0)
4258 	return CAIRO_STATUS_SUCCESS;
4259 
4260     status = _cairo_truetype_subset_init (&subset, font_subset);
4261     if (unlikely (status))
4262 	return status;
4263 
4264     _create_font_subset_tag (font_subset, subset.ps_name, tag);
4265 
4266     status = _cairo_pdf_surface_open_stream (surface,
4267 					     NULL,
4268 					     TRUE,
4269 					     "   /Length1 %lu\n",
4270 					     subset.data_length);
4271     if (unlikely (status)) {
4272 	_cairo_truetype_subset_fini (&subset);
4273 	return status;
4274     }
4275 
4276     stream = surface->pdf_stream.self;
4277     _cairo_output_stream_write (surface->output,
4278 				subset.data, subset.data_length);
4279     status = _cairo_pdf_surface_close_stream (surface);
4280     if (unlikely (status)) {
4281 	_cairo_truetype_subset_fini (&subset);
4282 	return status;
4283     }
4284 
4285     status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
4286 	                                                font_subset, TRUE,
4287 							&to_unicode_stream);
4288     if (_cairo_status_is_error (status)) {
4289 	_cairo_truetype_subset_fini (&subset);
4290 	return status;
4291     }
4292 
4293     descriptor = _cairo_pdf_surface_new_object (surface);
4294     if (descriptor.id == 0) {
4295 	_cairo_truetype_subset_fini (&subset);
4296 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4297     }
4298 
4299     _cairo_output_stream_printf (surface->output,
4300 				 "%d 0 obj\n"
4301 				 "<< /Type /FontDescriptor\n"
4302 				 "   /FontName /%s+%s\n",
4303 				 descriptor.id,
4304 				 tag,
4305 				 subset.ps_name);
4306 
4307     if (subset.font_name) {
4308 	_cairo_output_stream_printf (surface->output,
4309 				     "   /FontFamily (%s)\n",
4310 				     subset.font_name);
4311     }
4312 
4313     _cairo_output_stream_printf (surface->output,
4314 				 "   /Flags 4\n"
4315 				 "   /FontBBox [ %ld %ld %ld %ld ]\n"
4316 				 "   /ItalicAngle 0\n"
4317 				 "   /Ascent %ld\n"
4318 				 "   /Descent %ld\n"
4319 				 "   /CapHeight %ld\n"
4320 				 "   /StemV 80\n"
4321 				 "   /StemH 80\n"
4322 				 "   /FontFile2 %u 0 R\n"
4323 				 ">>\n"
4324 				 "endobj\n",
4325 				 (long)(subset.x_min*PDF_UNITS_PER_EM),
4326 				 (long)(subset.y_min*PDF_UNITS_PER_EM),
4327                                  (long)(subset.x_max*PDF_UNITS_PER_EM),
4328 				 (long)(subset.y_max*PDF_UNITS_PER_EM),
4329 				 (long)(subset.ascent*PDF_UNITS_PER_EM),
4330 				 (long)(subset.descent*PDF_UNITS_PER_EM),
4331 				 (long)(subset.y_max*PDF_UNITS_PER_EM),
4332 				 stream.id);
4333 
4334     cidfont_dict = _cairo_pdf_surface_new_object (surface);
4335     if (cidfont_dict.id == 0) {
4336 	_cairo_truetype_subset_fini (&subset);
4337 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4338     }
4339 
4340     _cairo_output_stream_printf (surface->output,
4341                                  "%d 0 obj\n"
4342                                  "<< /Type /Font\n"
4343                                  "   /Subtype /CIDFontType2\n"
4344                                  "   /BaseFont /%s+%s\n"
4345                                  "   /CIDSystemInfo\n"
4346                                  "   << /Registry (Adobe)\n"
4347                                  "      /Ordering (Identity)\n"
4348                                  "      /Supplement 0\n"
4349                                  "   >>\n"
4350                                  "   /FontDescriptor %d 0 R\n"
4351                                  "   /W [0 [",
4352                                  cidfont_dict.id,
4353 				 tag,
4354                                  subset.ps_name,
4355                                  descriptor.id);
4356 
4357     for (i = 0; i < font_subset->num_glyphs; i++)
4358         _cairo_output_stream_printf (surface->output,
4359                                      " %ld",
4360                                      (long)(subset.widths[i]*PDF_UNITS_PER_EM));
4361 
4362     _cairo_output_stream_printf (surface->output,
4363                                  " ]]\n"
4364 				 ">>\n"
4365 				 "endobj\n");
4366 
4367     _cairo_pdf_surface_update_object (surface, subset_resource);
4368     _cairo_output_stream_printf (surface->output,
4369 				 "%d 0 obj\n"
4370 				 "<< /Type /Font\n"
4371 				 "   /Subtype /Type0\n"
4372 				 "   /BaseFont /%s+%s\n"
4373                                  "   /Encoding /Identity-H\n"
4374 				 "   /DescendantFonts [ %d 0 R]\n",
4375 				 subset_resource.id,
4376 				 tag,
4377 				 subset.ps_name,
4378 				 cidfont_dict.id);
4379 
4380     if (to_unicode_stream.id != 0)
4381         _cairo_output_stream_printf (surface->output,
4382                                      "   /ToUnicode %d 0 R\n",
4383                                      to_unicode_stream.id);
4384 
4385     _cairo_output_stream_printf (surface->output,
4386 				 ">>\n"
4387 				 "endobj\n");
4388 
4389     font.font_id = font_subset->font_id;
4390     font.subset_id = font_subset->subset_id;
4391     font.subset_resource = subset_resource;
4392     status = _cairo_array_append (&surface->fonts, &font);
4393 
4394     _cairo_truetype_subset_fini (&subset);
4395 
4396     return status;
4397 }
4398 
4399 static cairo_status_t
_cairo_pdf_emit_imagemask(cairo_image_surface_t * image,cairo_output_stream_t * stream)4400 _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
4401 			     cairo_output_stream_t *stream)
4402 {
4403     uint8_t *byte, output_byte;
4404     int row, col, num_cols;
4405 
4406     /* The only image type supported by Type 3 fonts are 1-bit image
4407      * masks */
4408     assert (image->format == CAIRO_FORMAT_A1);
4409 
4410     _cairo_output_stream_printf (stream,
4411 				 "BI\n"
4412 				 "/IM true\n"
4413 				 "/W %d\n"
4414 				 "/H %d\n"
4415 				 "/BPC 1\n"
4416 				 "/D [1 0]\n",
4417 				 image->width,
4418 				 image->height);
4419 
4420     _cairo_output_stream_printf (stream,
4421 				 "ID ");
4422 
4423     num_cols = (image->width + 7) / 8;
4424     for (row = 0; row < image->height; row++) {
4425 	byte = image->data + row * image->stride;
4426 	for (col = 0; col < num_cols; col++) {
4427 	    output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
4428 	    _cairo_output_stream_write (stream, &output_byte, 1);
4429 	    byte++;
4430 	}
4431     }
4432 
4433     _cairo_output_stream_printf (stream,
4434 				 "\nEI\n");
4435 
4436     return _cairo_output_stream_get_status (stream);
4437 }
4438 
4439 static cairo_status_t
_cairo_pdf_surface_analyze_user_font_subset(cairo_scaled_font_subset_t * font_subset,void * closure)4440 _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
4441 					     void		        *closure)
4442 {
4443     cairo_pdf_surface_t *surface = closure;
4444     cairo_status_t status = CAIRO_STATUS_SUCCESS;
4445     cairo_status_t status2;
4446     unsigned int i;
4447     cairo_surface_t *type3_surface;
4448     cairo_output_stream_t *null_stream;
4449 
4450     null_stream = _cairo_null_stream_create ();
4451     type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
4452 						       null_stream,
4453 						       _cairo_pdf_emit_imagemask,
4454 						       surface->font_subsets);
4455     if (unlikely (type3_surface->status)) {
4456 	status2 = _cairo_output_stream_destroy (null_stream);
4457 	return type3_surface->status;
4458     }
4459 
4460     _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
4461 							  _cairo_pdf_surface_add_font,
4462 							  surface);
4463 
4464     for (i = 0; i < font_subset->num_glyphs; i++) {
4465 	status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
4466 							   font_subset->glyphs[i]);
4467 	if (unlikely (status))
4468 	    break;
4469     }
4470 
4471     cairo_surface_destroy (type3_surface);
4472     status2 = _cairo_output_stream_destroy (null_stream);
4473     if (status == CAIRO_STATUS_SUCCESS)
4474 	status = status2;
4475 
4476     return status;
4477 }
4478 
4479 static cairo_status_t
_cairo_pdf_surface_emit_type3_font_subset(cairo_pdf_surface_t * surface,cairo_scaled_font_subset_t * font_subset)4480 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
4481 					   cairo_scaled_font_subset_t	*font_subset)
4482 {
4483     cairo_status_t status = CAIRO_STATUS_SUCCESS;
4484     cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
4485     cairo_pdf_font_t font;
4486     double *widths;
4487     unsigned int i;
4488     cairo_box_t font_bbox = {{0,0},{0,0}};
4489     cairo_box_t bbox = {{0,0},{0,0}};
4490     cairo_surface_t *type3_surface;
4491 
4492     if (font_subset->num_glyphs == 0)
4493 	return CAIRO_STATUS_SUCCESS;
4494 
4495     subset_resource = _cairo_pdf_surface_get_font_resource (surface,
4496 							    font_subset->font_id,
4497 							    font_subset->subset_id);
4498     if (subset_resource.id == 0)
4499 	return CAIRO_STATUS_SUCCESS;
4500 
4501     glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
4502     if (unlikely (glyphs == NULL))
4503 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4504 
4505     widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
4506     if (unlikely (widths == NULL)) {
4507         free (glyphs);
4508 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4509     }
4510 
4511     _cairo_pdf_group_resources_clear (&surface->resources);
4512     type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
4513 						       NULL,
4514 						       _cairo_pdf_emit_imagemask,
4515 						       surface->font_subsets);
4516     if (unlikely (type3_surface->status)) {
4517         free (glyphs);
4518         free (widths);
4519 	return type3_surface->status;
4520     }
4521 
4522     _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
4523 							  _cairo_pdf_surface_add_font,
4524 							  surface);
4525 
4526     for (i = 0; i < font_subset->num_glyphs; i++) {
4527 	status = _cairo_pdf_surface_open_stream (surface,
4528 						 NULL,
4529 						 surface->compress_content,
4530 						 NULL);
4531 	if (unlikely (status))
4532 	    break;
4533 
4534 	glyphs[i] = surface->pdf_stream.self;
4535 	status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
4536 							surface->output,
4537 							font_subset->glyphs[i],
4538 							&bbox,
4539 							&widths[i]);
4540 	if (unlikely (status))
4541 	    break;
4542 
4543 	status = _cairo_pdf_surface_close_stream (surface);
4544 	if (unlikely (status))
4545 	    break;
4546 
4547         if (i == 0) {
4548             font_bbox.p1.x = bbox.p1.x;
4549             font_bbox.p1.y = bbox.p1.y;
4550             font_bbox.p2.x = bbox.p2.x;
4551             font_bbox.p2.y = bbox.p2.y;
4552         } else {
4553             if (bbox.p1.x < font_bbox.p1.x)
4554                 font_bbox.p1.x = bbox.p1.x;
4555             if (bbox.p1.y < font_bbox.p1.y)
4556                 font_bbox.p1.y = bbox.p1.y;
4557             if (bbox.p2.x > font_bbox.p2.x)
4558                 font_bbox.p2.x = bbox.p2.x;
4559             if (bbox.p2.y > font_bbox.p2.y)
4560                 font_bbox.p2.y = bbox.p2.y;
4561         }
4562     }
4563     cairo_surface_destroy (type3_surface);
4564     if (unlikely (status)) {
4565 	free (glyphs);
4566 	free (widths);
4567 	return status;
4568     }
4569 
4570     encoding = _cairo_pdf_surface_new_object (surface);
4571     if (encoding.id == 0) {
4572 	free (glyphs);
4573 	free (widths);
4574 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4575     }
4576 
4577     _cairo_output_stream_printf (surface->output,
4578 				 "%d 0 obj\n"
4579 				 "<< /Type /Encoding\n"
4580 				 "   /Differences [0", encoding.id);
4581     for (i = 0; i < font_subset->num_glyphs; i++)
4582 	_cairo_output_stream_printf (surface->output,
4583 				     " /%d", i);
4584     _cairo_output_stream_printf (surface->output,
4585 				 "]\n"
4586 				 ">>\n"
4587 				 "endobj\n");
4588 
4589     char_procs = _cairo_pdf_surface_new_object (surface);
4590     if (char_procs.id == 0) {
4591 	free (glyphs);
4592 	free (widths);
4593 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4594     }
4595 
4596     _cairo_output_stream_printf (surface->output,
4597 				 "%d 0 obj\n"
4598 				 "<<\n", char_procs.id);
4599     for (i = 0; i < font_subset->num_glyphs; i++)
4600 	_cairo_output_stream_printf (surface->output,
4601 				     " /%d %d 0 R\n",
4602 				     i, glyphs[i].id);
4603     _cairo_output_stream_printf (surface->output,
4604 				 ">>\n"
4605 				 "endobj\n");
4606 
4607     free (glyphs);
4608 
4609     status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
4610 	                                                font_subset, FALSE,
4611 							&to_unicode_stream);
4612     if (_cairo_status_is_error (status)) {
4613 	free (widths);
4614 	return status;
4615     }
4616 
4617     _cairo_pdf_surface_update_object (surface, subset_resource);
4618     _cairo_output_stream_printf (surface->output,
4619 				 "%d 0 obj\n"
4620 				 "<< /Type /Font\n"
4621 				 "   /Subtype /Type3\n"
4622 				 "   /FontBBox [%f %f %f %f]\n"
4623 				 "   /FontMatrix [ 1 0 0 1 0 0 ]\n"
4624 				 "   /Encoding %d 0 R\n"
4625 				 "   /CharProcs %d 0 R\n"
4626 				 "   /FirstChar 0\n"
4627 				 "   /LastChar %d\n",
4628 				 subset_resource.id,
4629 				 _cairo_fixed_to_double (font_bbox.p1.x),
4630 				 - _cairo_fixed_to_double (font_bbox.p2.y),
4631 				 _cairo_fixed_to_double (font_bbox.p2.x),
4632 				 - _cairo_fixed_to_double (font_bbox.p1.y),
4633 				 encoding.id,
4634 				 char_procs.id,
4635 				 font_subset->num_glyphs - 1);
4636 
4637     _cairo_output_stream_printf (surface->output,
4638 				 "   /Widths [");
4639     for (i = 0; i < font_subset->num_glyphs; i++)
4640 	_cairo_output_stream_printf (surface->output, " %f", widths[i]);
4641     _cairo_output_stream_printf (surface->output,
4642 				 "]\n");
4643     free (widths);
4644 
4645     _cairo_output_stream_printf (surface->output,
4646 				 "   /Resources\n");
4647     _cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
4648 
4649     if (to_unicode_stream.id != 0)
4650         _cairo_output_stream_printf (surface->output,
4651                                      "    /ToUnicode %d 0 R\n",
4652                                      to_unicode_stream.id);
4653 
4654     _cairo_output_stream_printf (surface->output,
4655 				 ">>\n"
4656 				 "endobj\n");
4657 
4658     font.font_id = font_subset->font_id;
4659     font.subset_id = font_subset->subset_id;
4660     font.subset_resource = subset_resource;
4661     return _cairo_array_append (&surface->fonts, &font);
4662 }
4663 
4664 static cairo_status_t
_cairo_pdf_surface_emit_unscaled_font_subset(cairo_scaled_font_subset_t * font_subset,void * closure)4665 _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
4666                                               void			 *closure)
4667 {
4668     cairo_pdf_surface_t *surface = closure;
4669     cairo_status_t status;
4670 
4671     if (font_subset->is_composite) {
4672         status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
4673         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4674             return status;
4675 
4676         status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
4677         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4678             return status;
4679 
4680         status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
4681         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4682             return status;
4683     } else {
4684 #if CAIRO_HAS_FT_FONT
4685         status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
4686         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4687             return status;
4688 #endif
4689 
4690         status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
4691         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4692             return status;
4693 
4694     }
4695 
4696     ASSERT_NOT_REACHED;
4697     return CAIRO_STATUS_SUCCESS;
4698 }
4699 
4700 static cairo_status_t
_cairo_pdf_surface_emit_scaled_font_subset(cairo_scaled_font_subset_t * font_subset,void * closure)4701 _cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
4702                                             void		       *closure)
4703 {
4704     cairo_pdf_surface_t *surface = closure;
4705     cairo_status_t status;
4706 
4707     status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
4708     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
4709 	return status;
4710 
4711     ASSERT_NOT_REACHED;
4712     return CAIRO_STATUS_SUCCESS;
4713 }
4714 
4715 static cairo_status_t
_cairo_pdf_surface_emit_font_subsets(cairo_pdf_surface_t * surface)4716 _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
4717 {
4718     cairo_status_t status;
4719 
4720     status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
4721 						      _cairo_pdf_surface_analyze_user_font_subset,
4722 						      surface);
4723     if (unlikely (status))
4724 	goto BAIL;
4725 
4726     status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
4727                                                           _cairo_pdf_surface_emit_unscaled_font_subset,
4728                                                           surface);
4729     if (unlikely (status))
4730 	goto BAIL;
4731 
4732     status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
4733                                                         _cairo_pdf_surface_emit_scaled_font_subset,
4734                                                         surface);
4735     if (unlikely (status))
4736 	goto BAIL;
4737 
4738     status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
4739 						      _cairo_pdf_surface_emit_scaled_font_subset,
4740 						      surface);
4741 
4742 BAIL:
4743     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
4744     surface->font_subsets = NULL;
4745 
4746     return status;
4747 }
4748 
4749 static cairo_pdf_resource_t
_cairo_pdf_surface_write_catalog(cairo_pdf_surface_t * surface)4750 _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface)
4751 {
4752     cairo_pdf_resource_t catalog;
4753 
4754     catalog = _cairo_pdf_surface_new_object (surface);
4755     if (catalog.id == 0)
4756 	return catalog;
4757 
4758     _cairo_output_stream_printf (surface->output,
4759 				 "%d 0 obj\n"
4760 				 "<< /Type /Catalog\n"
4761 				 "   /Pages %d 0 R\n"
4762 				 ">>\n"
4763 				 "endobj\n",
4764 				 catalog.id,
4765 				 surface->pages_resource.id);
4766 
4767     return catalog;
4768 }
4769 
4770 static long
_cairo_pdf_surface_write_xref(cairo_pdf_surface_t * surface)4771 _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
4772 {
4773     cairo_pdf_object_t *object;
4774     int num_objects, i;
4775     long offset;
4776     char buffer[11];
4777 
4778     num_objects = _cairo_array_num_elements (&surface->objects);
4779 
4780     offset = _cairo_output_stream_get_position (surface->output);
4781     _cairo_output_stream_printf (surface->output,
4782 				 "xref\n"
4783 				 "%d %d\n",
4784 				 0, num_objects + 1);
4785 
4786     _cairo_output_stream_printf (surface->output,
4787 				 "0000000000 65535 f \n");
4788     for (i = 0; i < num_objects; i++) {
4789 	object = _cairo_array_index (&surface->objects, i);
4790 	snprintf (buffer, sizeof buffer, "%010ld", object->offset);
4791 	_cairo_output_stream_printf (surface->output,
4792 				     "%s 00000 n \n", buffer);
4793     }
4794 
4795     return offset;
4796 }
4797 
4798 static cairo_status_t
_cairo_pdf_surface_write_mask_group(cairo_pdf_surface_t * surface,cairo_pdf_smask_group_t * group)4799 _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t	*surface,
4800 				     cairo_pdf_smask_group_t	*group)
4801 {
4802     cairo_pdf_resource_t mask_group;
4803     cairo_pdf_resource_t smask;
4804     cairo_pdf_smask_group_t *smask_group;
4805     cairo_pdf_resource_t pattern_res, gstate_res;
4806     cairo_status_t status;
4807 
4808     /* Create mask group */
4809     status = _cairo_pdf_surface_open_group (surface, NULL);
4810     if (unlikely (status))
4811 	return status;
4812 
4813     pattern_res.id = 0;
4814     gstate_res.id = 0;
4815     status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, NULL,
4816 						 &pattern_res, &gstate_res);
4817     if (unlikely (status))
4818 	return status;
4819 
4820     if (gstate_res.id != 0) {
4821 	smask_group = _cairo_pdf_surface_create_smask_group (surface);
4822 	if (unlikely (smask_group == NULL))
4823 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4824 
4825 	smask_group->operation = PDF_PAINT;
4826 	smask_group->source = cairo_pattern_reference (group->mask);
4827 	smask_group->source_res = pattern_res;
4828 	status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
4829 	if (unlikely (status)) {
4830 	    _cairo_pdf_smask_group_destroy (smask_group);
4831 	    return status;
4832 	}
4833 
4834 	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
4835 	if (unlikely (status))
4836 	    return status;
4837 
4838 	status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
4839 	if (unlikely (status))
4840 	    return status;
4841 
4842 	_cairo_output_stream_printf (surface->output,
4843 				     "q /s%d gs /x%d Do Q\n",
4844 				     gstate_res.id,
4845 				     smask_group->group_res.id);
4846     } else {
4847 	status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE);
4848 	if (unlikely (status))
4849 	    return status;
4850 
4851 	_cairo_output_stream_printf (surface->output,
4852 				     "0 0 %f %f re f\n",
4853 				     surface->width, surface->height);
4854 
4855 	status = _cairo_pdf_surface_unselect_pattern (surface);
4856 	if (unlikely (status))
4857 	    return status;
4858     }
4859 
4860     status = _cairo_pdf_surface_close_group (surface, &mask_group);
4861     if (unlikely (status))
4862 	return status;
4863 
4864     /* Create source group */
4865     status = _cairo_pdf_surface_open_group (surface, &group->source_res);
4866     if (unlikely (status))
4867 	return status;
4868 
4869     pattern_res.id = 0;
4870     gstate_res.id = 0;
4871     status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, NULL,
4872 						 &pattern_res, &gstate_res);
4873     if (unlikely (status))
4874 	return status;
4875 
4876     if (gstate_res.id != 0) {
4877 	smask_group = _cairo_pdf_surface_create_smask_group (surface);
4878 	if (unlikely (smask_group == NULL))
4879 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4880 
4881 	smask_group->operation = PDF_PAINT;
4882 	smask_group->source = cairo_pattern_reference (group->source);
4883 	smask_group->source_res = pattern_res;
4884 	status = _cairo_pdf_surface_add_smask_group (surface, smask_group);
4885 	if (unlikely (status)) {
4886 	    _cairo_pdf_smask_group_destroy (smask_group);
4887 	    return status;
4888 	}
4889 
4890 	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
4891 	if (unlikely (status))
4892 	    return status;
4893 
4894 	status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res);
4895 	if (unlikely (status))
4896 	    return status;
4897 
4898 	_cairo_output_stream_printf (surface->output,
4899 				     "q /s%d gs /x%d Do Q\n",
4900 				     gstate_res.id,
4901 				     smask_group->group_res.id);
4902     } else {
4903 	status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE);
4904 	if (unlikely (status))
4905 	    return status;
4906 
4907 	_cairo_output_stream_printf (surface->output,
4908 				     "0 0 %f %f re f\n",
4909 				     surface->width, surface->height);
4910 
4911 	status = _cairo_pdf_surface_unselect_pattern (surface);
4912 	if (unlikely (status))
4913 	    return status;
4914     }
4915 
4916     status = _cairo_pdf_surface_close_group (surface, NULL);
4917     if (unlikely (status))
4918 	return status;
4919 
4920     /* Create an smask based on the alpha component of mask_group */
4921     smask = _cairo_pdf_surface_new_object (surface);
4922     if (smask.id == 0)
4923 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4924 
4925     _cairo_output_stream_printf (surface->output,
4926 				 "%d 0 obj\n"
4927 				 "<< /Type /Mask\n"
4928 				 "   /S /Alpha\n"
4929 				 "   /G %d 0 R\n"
4930 				 ">>\n"
4931 				 "endobj\n",
4932 				 smask.id,
4933 				 mask_group.id);
4934 
4935     /* Create a GState that uses the smask */
4936     _cairo_pdf_surface_update_object (surface, group->group_res);
4937     _cairo_output_stream_printf (surface->output,
4938 				 "%d 0 obj\n"
4939 				 "<< /Type /ExtGState\n"
4940 				 "   /SMask %d 0 R\n"
4941 				 "   /ca 1\n"
4942 				 "   /CA 1\n"
4943 				 "   /AIS false\n"
4944 				 ">>\n"
4945 				 "endobj\n",
4946 				 group->group_res.id,
4947 				 smask.id);
4948 
4949     return _cairo_output_stream_get_status (surface->output);
4950 }
4951 
4952 static cairo_status_t
_cairo_pdf_surface_write_smask_group(cairo_pdf_surface_t * surface,cairo_pdf_smask_group_t * group)4953 _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t     *surface,
4954 				      cairo_pdf_smask_group_t *group)
4955 {
4956     double old_width, old_height;
4957     cairo_status_t status;
4958 
4959     old_width = surface->width;
4960     old_height = surface->height;
4961     _cairo_pdf_surface_set_size_internal (surface,
4962 					  group->width,
4963 					  group->height);
4964     /* _mask is a special case that requires two groups - source
4965      * and mask as well as a smask and gstate dictionary */
4966     if (group->operation == PDF_MASK) {
4967 	status = _cairo_pdf_surface_write_mask_group (surface, group);
4968 	goto RESTORE_SIZE;
4969     }
4970 
4971     status = _cairo_pdf_surface_open_group (surface, &group->group_res);
4972     if (unlikely (status))
4973 	return status;
4974 
4975     status = _cairo_pdf_surface_select_pattern (surface,
4976 						group->source,
4977 						group->source_res,
4978 						group->operation == PDF_STROKE);
4979     if (unlikely (status))
4980 	return status;
4981 
4982     switch (group->operation) {
4983     case PDF_PAINT:
4984 	_cairo_output_stream_printf (surface->output,
4985 				     "0 0 %f %f re f\n",
4986 				     surface->width, surface->height);
4987 	break;
4988     case PDF_MASK:
4989 	ASSERT_NOT_REACHED;
4990 	break;
4991     case PDF_FILL:
4992 	status = _cairo_pdf_operators_fill (&surface->pdf_operators,
4993 					    &group->path,
4994 					    group->fill_rule);
4995 	break;
4996     case PDF_STROKE:
4997 	status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
4998 					      &group->path,
4999 					      &group->style,
5000 					      &group->ctm,
5001 					      &group->ctm_inverse);
5002 	break;
5003     case PDF_SHOW_GLYPHS:
5004 	status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
5005 							group->utf8, group->utf8_len,
5006 							group->glyphs, group->num_glyphs,
5007 							group->clusters, group->num_clusters,
5008 							group->cluster_flags,
5009 							group->scaled_font);
5010 	break;
5011     }
5012     if (unlikely (status))
5013 	return status;
5014 
5015     status = _cairo_pdf_surface_unselect_pattern (surface);
5016     if (unlikely (status))
5017 	return status;
5018 
5019     status = _cairo_pdf_surface_close_group (surface, NULL);
5020 
5021 RESTORE_SIZE:
5022     _cairo_pdf_surface_set_size_internal (surface,
5023 					  old_width,
5024 					  old_height);
5025 
5026     return status;
5027 }
5028 
5029 static cairo_status_t
_cairo_pdf_surface_write_patterns_and_smask_groups(cairo_pdf_surface_t * surface)5030 _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface)
5031 {
5032     cairo_pdf_pattern_t pattern;
5033     cairo_pdf_smask_group_t *group;
5034     cairo_pdf_source_surface_t src_surface;
5035     int pattern_index, group_index, surface_index;
5036     cairo_status_t status;
5037 
5038     /* Writing out PDF_MASK groups will cause additional smask groups
5039      * to be appended to surface->smask_groups. Additional patterns
5040      * may also be appended to surface->patterns.
5041      *
5042      * Writing recording surface patterns will cause additional patterns
5043      * and groups to be appended.
5044      */
5045     pattern_index = 0;
5046     group_index = 0;
5047     surface_index = 0;
5048     while ((pattern_index < _cairo_array_num_elements (&surface->page_patterns)) ||
5049 	   (group_index < _cairo_array_num_elements (&surface->smask_groups)) ||
5050 	   (surface_index < _cairo_array_num_elements (&surface->page_surfaces)))
5051     {
5052 	for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) {
5053 	    _cairo_array_copy_element (&surface->smask_groups, group_index, &group);
5054 	    status = _cairo_pdf_surface_write_smask_group (surface, group);
5055 	    if (unlikely (status))
5056 		return status;
5057 	}
5058 
5059 	for (; pattern_index < _cairo_array_num_elements (&surface->page_patterns); pattern_index++) {
5060 	    _cairo_array_copy_element (&surface->page_patterns, pattern_index, &pattern);
5061 	    status = _cairo_pdf_surface_emit_pattern (surface, &pattern);
5062 	    if (unlikely (status))
5063 		return status;
5064 	}
5065 
5066 	for (; surface_index < _cairo_array_num_elements (&surface->page_surfaces); surface_index++) {
5067 	    _cairo_array_copy_element (&surface->page_surfaces, surface_index, &src_surface);
5068 	    status = _cairo_pdf_surface_emit_surface (surface, &src_surface);
5069 	    if (unlikely (status))
5070 		return status;
5071 	}
5072     }
5073 
5074     return CAIRO_STATUS_SUCCESS;
5075 }
5076 
5077 static cairo_status_t
_cairo_pdf_surface_write_page(cairo_pdf_surface_t * surface)5078 _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
5079 {
5080     cairo_pdf_resource_t page, knockout, res;
5081     cairo_status_t status;
5082     int i, len;
5083 
5084     _cairo_pdf_group_resources_clear (&surface->resources);
5085     if (surface->has_fallback_images) {
5086 	status = _cairo_pdf_surface_open_knockout_group (surface);
5087 	if (unlikely (status))
5088 	    return status;
5089 
5090 	len = _cairo_array_num_elements (&surface->knockout_group);
5091 	for (i = 0; i < len; i++) {
5092 	    _cairo_array_copy_element (&surface->knockout_group, i, &res);
5093 	    _cairo_output_stream_printf (surface->output,
5094 					 "/x%d Do\n",
5095 					 res.id);
5096 	    status = _cairo_pdf_surface_add_xobject (surface, res);
5097 	    if (unlikely (status))
5098 		return status;
5099 	}
5100 	_cairo_output_stream_printf (surface->output,
5101 				     "/x%d Do\n",
5102 				     surface->content.id);
5103 	status = _cairo_pdf_surface_add_xobject (surface, surface->content);
5104 	if (unlikely (status))
5105 	    return status;
5106 
5107 	status = _cairo_pdf_surface_close_group (surface, &knockout);
5108 	if (unlikely (status))
5109 	    return status;
5110 
5111 	_cairo_pdf_group_resources_clear (&surface->resources);
5112 	status = _cairo_pdf_surface_open_content_stream (surface, NULL, FALSE);
5113 	if (unlikely (status))
5114 	    return status;
5115 
5116 	_cairo_output_stream_printf (surface->output,
5117 				     "/x%d Do\n",
5118 				     knockout.id);
5119 	status = _cairo_pdf_surface_add_xobject (surface, knockout);
5120 	if (unlikely (status))
5121 	    return status;
5122 
5123 	status = _cairo_pdf_surface_close_content_stream (surface);
5124 	if (unlikely (status))
5125 	    return status;
5126     }
5127 
5128     page = _cairo_pdf_surface_new_object (surface);
5129     if (page.id == 0)
5130 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5131 
5132     _cairo_output_stream_printf (surface->output,
5133 				 "%d 0 obj\n"
5134 				 "<< /Type /Page\n"
5135 				 "   /Parent %d 0 R\n"
5136 				 "   /MediaBox [ 0 0 %f %f ]\n"
5137 				 "   /Contents %d 0 R\n"
5138 				 "   /Group <<\n"
5139 				 "      /Type /Group\n"
5140 				 "      /S /Transparency\n"
5141 				 "      /CS /DeviceRGB\n"
5142 				 "   >>\n"
5143 				 "   /Resources %d 0 R\n"
5144 				 ">>\n"
5145 				 "endobj\n",
5146 				 page.id,
5147 				 surface->pages_resource.id,
5148 				 surface->width,
5149 				 surface->height,
5150 				 surface->content.id,
5151 				 surface->content_resources.id);
5152 
5153     status = _cairo_array_append (&surface->pages, &page);
5154     if (unlikely (status))
5155 	return status;
5156 
5157     status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface);
5158     if (unlikely (status))
5159 	return status;
5160 
5161     return CAIRO_STATUS_SUCCESS;
5162 }
5163 
5164 static cairo_int_status_t
_cairo_pdf_surface_analyze_surface_pattern_transparency(cairo_pdf_surface_t * surface,cairo_surface_pattern_t * pattern)5165 _cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t      *surface,
5166 							 cairo_surface_pattern_t *pattern)
5167 {
5168     cairo_image_surface_t  *image;
5169     void		   *image_extra;
5170     cairo_int_status_t      status;
5171     cairo_image_transparency_t transparency;
5172 
5173     status = _cairo_surface_acquire_source_image (pattern->surface,
5174 						  &image,
5175 						  &image_extra);
5176     if (unlikely (status))
5177 	return status;
5178 
5179     if (image->base.status)
5180 	return image->base.status;
5181 
5182     transparency = _cairo_image_analyze_transparency (image);
5183     if (transparency == CAIRO_IMAGE_IS_OPAQUE)
5184 	status = CAIRO_STATUS_SUCCESS;
5185     else
5186 	status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
5187 
5188     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
5189 
5190     return status;
5191 }
5192 
5193 static cairo_bool_t
_surface_pattern_supported(cairo_surface_pattern_t * pattern)5194 _surface_pattern_supported (cairo_surface_pattern_t *pattern)
5195 {
5196     cairo_extend_t extend;
5197 
5198     if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
5199 	return TRUE;
5200 
5201     if (pattern->surface->backend->acquire_source_image == NULL)
5202 	return FALSE;
5203 
5204     /* Does an ALPHA-only source surface even make sense? Maybe, but I
5205      * don't think it's worth the extra code to support it. */
5206 
5207 /* XXX: Need to write this function here...
5208     content = cairo_surface_get_content (pattern->surface);
5209     if (content == CAIRO_CONTENT_ALPHA)
5210 	return FALSE;
5211 */
5212 
5213     extend = cairo_pattern_get_extend (&pattern->base);
5214     switch (extend) {
5215     case CAIRO_EXTEND_NONE:
5216     case CAIRO_EXTEND_REPEAT:
5217     case CAIRO_EXTEND_REFLECT:
5218     /* There's no point returning FALSE for EXTEND_PAD, as the image
5219      * surface does not currently implement it either */
5220     case CAIRO_EXTEND_PAD:
5221 	return TRUE;
5222     }
5223 
5224     ASSERT_NOT_REACHED;
5225     return FALSE;
5226 }
5227 
5228 static cairo_bool_t
_gradient_pattern_supported(const cairo_pattern_t * pattern)5229 _gradient_pattern_supported (const cairo_pattern_t *pattern)
5230 {
5231     cairo_extend_t extend;
5232 
5233     extend = cairo_pattern_get_extend ((cairo_pattern_t *) pattern);
5234 
5235 
5236     /* Radial gradients are currently only supported with EXTEND_NONE
5237      * and EXTEND_PAD and when one circle is inside the other. */
5238     if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
5239         double x1, y1, x2, y2, r1, r2, d;
5240         cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
5241 
5242 	if (extend == CAIRO_EXTEND_REPEAT ||
5243 	    extend == CAIRO_EXTEND_REFLECT) {
5244 	    return FALSE;
5245 	}
5246 
5247 	x1 = _cairo_fixed_to_double (radial->c1.x);
5248         y1 = _cairo_fixed_to_double (radial->c1.y);
5249         r1 = _cairo_fixed_to_double (radial->r1);
5250         x2 = _cairo_fixed_to_double (radial->c2.x);
5251         y2 = _cairo_fixed_to_double (radial->c2.y);
5252         r2 = _cairo_fixed_to_double (radial->r2);
5253 
5254         d = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
5255         if (d > fabs(r2 - r1)) {
5256             return FALSE;
5257         }
5258     }
5259 
5260     return TRUE;
5261 }
5262 
5263 static cairo_bool_t
_pattern_supported(const cairo_pattern_t * pattern)5264 _pattern_supported (const cairo_pattern_t *pattern)
5265 {
5266     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
5267 	return TRUE;
5268 
5269     if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
5270 	pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
5271 	return _gradient_pattern_supported (pattern);
5272 
5273     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
5274 	return _surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
5275 
5276     return FALSE;
5277 }
5278 
5279 static cairo_bool_t
_pdf_operator_supported(cairo_operator_t op)5280 _pdf_operator_supported (cairo_operator_t op)
5281 {
5282     switch (op) {
5283     case CAIRO_OPERATOR_OVER:
5284     case CAIRO_OPERATOR_MULTIPLY:
5285     case CAIRO_OPERATOR_SCREEN:
5286     case CAIRO_OPERATOR_OVERLAY:
5287     case CAIRO_OPERATOR_DARKEN:
5288     case CAIRO_OPERATOR_LIGHTEN:
5289     case CAIRO_OPERATOR_COLOR_DODGE:
5290     case CAIRO_OPERATOR_COLOR_BURN:
5291     case CAIRO_OPERATOR_HARD_LIGHT:
5292     case CAIRO_OPERATOR_SOFT_LIGHT:
5293     case CAIRO_OPERATOR_DIFFERENCE:
5294     case CAIRO_OPERATOR_EXCLUSION:
5295     case CAIRO_OPERATOR_HSL_HUE:
5296     case CAIRO_OPERATOR_HSL_SATURATION:
5297     case CAIRO_OPERATOR_HSL_COLOR:
5298     case CAIRO_OPERATOR_HSL_LUMINOSITY:
5299 	return TRUE;
5300 
5301     default:
5302     case CAIRO_OPERATOR_CLEAR:
5303     case CAIRO_OPERATOR_SOURCE:
5304     case CAIRO_OPERATOR_IN:
5305     case CAIRO_OPERATOR_OUT:
5306     case CAIRO_OPERATOR_ATOP:
5307     case CAIRO_OPERATOR_DEST:
5308     case CAIRO_OPERATOR_DEST_OVER:
5309     case CAIRO_OPERATOR_DEST_IN:
5310     case CAIRO_OPERATOR_DEST_OUT:
5311     case CAIRO_OPERATOR_DEST_ATOP:
5312     case CAIRO_OPERATOR_XOR:
5313     case CAIRO_OPERATOR_ADD:
5314     case CAIRO_OPERATOR_SATURATE:
5315 	return FALSE;
5316     }
5317 }
5318 
5319 static cairo_int_status_t
_cairo_pdf_surface_analyze_operation(cairo_pdf_surface_t * surface,cairo_operator_t op,const cairo_pattern_t * pattern,const cairo_rectangle_int_t * extents)5320 _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t  *surface,
5321 				      cairo_operator_t      op,
5322 				      const cairo_pattern_t      *pattern,
5323 				      const cairo_rectangle_int_t	 *extents)
5324 {
5325     if (surface->force_fallbacks &&
5326 	surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
5327     {
5328 	return CAIRO_INT_STATUS_UNSUPPORTED;
5329     }
5330 
5331     if (! _pattern_supported (pattern))
5332 	return CAIRO_INT_STATUS_UNSUPPORTED;
5333 
5334     if (_pdf_operator_supported (op)) {
5335 	if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
5336 	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
5337 
5338 	    if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
5339 		if (pattern->extend == CAIRO_EXTEND_PAD)
5340 		    return CAIRO_INT_STATUS_UNSUPPORTED;
5341 		else
5342 		    return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
5343 	    }
5344 	}
5345 
5346 	return CAIRO_STATUS_SUCCESS;
5347     }
5348 
5349 
5350     /* The SOURCE operator is supported if the pattern is opaque or if
5351      * there is nothing painted underneath. */
5352     if (op == CAIRO_OPERATOR_SOURCE) {
5353 	if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
5354 	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
5355 
5356 	    if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
5357 		if (_cairo_pattern_is_opaque (pattern, extents)) {
5358 		    return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
5359 		} else {
5360 		    /* FIXME: The analysis surface does not yet have
5361 		     * the capability to analyze a non opaque recording
5362 		     * surface and mark it supported if there is
5363 		     * nothing underneath. For now recording surfaces of
5364 		     * type CONTENT_COLOR_ALPHA painted with
5365 		     * OPERATOR_SOURCE will result in a fallback
5366 		     * image. */
5367 
5368 		    return CAIRO_INT_STATUS_UNSUPPORTED;
5369 		}
5370 	    } else {
5371 		return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
5372 										surface_pattern);
5373 	    }
5374 	}
5375 
5376 	if (_cairo_pattern_is_opaque (pattern, extents))
5377 	    return CAIRO_STATUS_SUCCESS;
5378 	else
5379 	    return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
5380     }
5381 
5382     return CAIRO_INT_STATUS_UNSUPPORTED;
5383 }
5384 
5385 static cairo_bool_t
_cairo_pdf_surface_operation_supported(cairo_pdf_surface_t * surface,cairo_operator_t op,const cairo_pattern_t * pattern,const cairo_rectangle_int_t * extents)5386 _cairo_pdf_surface_operation_supported (cairo_pdf_surface_t  *surface,
5387 					cairo_operator_t      op,
5388 					const cairo_pattern_t      *pattern,
5389 					const cairo_rectangle_int_t *extents)
5390 {
5391     return _cairo_pdf_surface_analyze_operation (surface, op, pattern, extents) != CAIRO_INT_STATUS_UNSUPPORTED;
5392 }
5393 
5394 static cairo_int_status_t
_cairo_pdf_surface_start_fallback(cairo_pdf_surface_t * surface)5395 _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
5396 {
5397     cairo_status_t status;
5398 
5399     status = _cairo_pdf_surface_close_content_stream (surface);
5400     if (unlikely (status))
5401 	return status;
5402 
5403     status = _cairo_array_append (&surface->knockout_group, &surface->content);
5404     if (unlikely (status))
5405 	return status;
5406 
5407     _cairo_pdf_group_resources_clear (&surface->resources);
5408     return _cairo_pdf_surface_open_content_stream (surface, NULL, TRUE);
5409 }
5410 
5411 static cairo_int_status_t
_cairo_pdf_surface_paint(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_clip_t * clip)5412 _cairo_pdf_surface_paint (void			*abstract_surface,
5413 			  cairo_operator_t	 op,
5414 			  const cairo_pattern_t	*source,
5415 			  cairo_clip_t		*clip)
5416 {
5417     cairo_pdf_surface_t *surface = abstract_surface;
5418     cairo_status_t status;
5419     cairo_pdf_smask_group_t *group;
5420     cairo_pdf_resource_t pattern_res, gstate_res;
5421     cairo_composite_rectangles_t extents;
5422 
5423     status = _cairo_composite_rectangles_init_for_paint (&extents,
5424 							 surface->width, surface->height,
5425 							 op, source, clip);
5426     if (unlikely (status)) {
5427 	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
5428 	    return CAIRO_STATUS_SUCCESS;
5429 
5430 	return status;
5431     }
5432 
5433     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
5434 	return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
5435     } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
5436 	status = _cairo_pdf_surface_start_fallback (surface);
5437 	if (unlikely (status))
5438 	    return status;
5439     }
5440 
5441     assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
5442 
5443     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
5444     if (unlikely (status))
5445 	return status;
5446 
5447     status = _cairo_pdf_surface_select_operator (surface, op);
5448     if (unlikely (status))
5449 	return status;
5450 
5451     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5452     if (unlikely (status))
5453 	return status;
5454 
5455     if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
5456 	source->extend == CAIRO_EXTEND_NONE)
5457     {
5458 	_cairo_output_stream_printf (surface->output, "q\n");
5459 	status = _cairo_pdf_surface_paint_surface_pattern (surface,
5460 							   (cairo_surface_pattern_t *) source);
5461 	if (unlikely (status))
5462 	    return status;
5463 
5464 	_cairo_output_stream_printf (surface->output, "Q\n");
5465 	return _cairo_output_stream_get_status (surface->output);
5466     }
5467 
5468     pattern_res.id = 0;
5469     gstate_res.id = 0;
5470     status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
5471 						 &extents.bounded,
5472 						 &pattern_res, &gstate_res);
5473     if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
5474 	return CAIRO_STATUS_SUCCESS;
5475     if (unlikely (status))
5476 	return status;
5477 
5478     if (gstate_res.id != 0) {
5479 	group = _cairo_pdf_surface_create_smask_group (surface);
5480 	if (unlikely (group == NULL))
5481 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5482 
5483 	group->operation = PDF_PAINT;
5484 	status = _cairo_pattern_create_copy (&group->source, source);
5485 	if (unlikely (status)) {
5486 	    _cairo_pdf_smask_group_destroy (group);
5487 	    return status;
5488 	}
5489 	group->source_res = pattern_res;
5490 	status = _cairo_pdf_surface_add_smask_group (surface, group);
5491 	if (unlikely (status)) {
5492 	    _cairo_pdf_smask_group_destroy (group);
5493 	    return status;
5494 	}
5495 
5496 	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5497 	if (unlikely (status))
5498 	    return status;
5499 
5500 	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
5501 	if (unlikely (status))
5502 	    return status;
5503 
5504 	_cairo_output_stream_printf (surface->output,
5505 				     "q /s%d gs /x%d Do Q\n",
5506 				     gstate_res.id,
5507 				     group->group_res.id);
5508     } else {
5509 	status = _cairo_pdf_surface_select_pattern (surface, source,
5510 						    pattern_res, FALSE);
5511 	if (unlikely (status))
5512 	    return status;
5513 
5514 	_cairo_output_stream_printf (surface->output,
5515 				     "0 0 %f %f re f\n",
5516 				     surface->width, surface->height);
5517 
5518 	status = _cairo_pdf_surface_unselect_pattern (surface);
5519 	if (unlikely (status))
5520 	    return status;
5521     }
5522 
5523     return _cairo_output_stream_get_status (surface->output);
5524 }
5525 
5526 static cairo_int_status_t
_cairo_pdf_surface_mask(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,const cairo_pattern_t * mask,cairo_clip_t * clip)5527 _cairo_pdf_surface_mask	(void			*abstract_surface,
5528 			 cairo_operator_t	 op,
5529 			 const cairo_pattern_t	*source,
5530 			 const cairo_pattern_t	*mask,
5531 			 cairo_clip_t		*clip)
5532 {
5533     cairo_pdf_surface_t *surface = abstract_surface;
5534     cairo_pdf_smask_group_t *group;
5535     cairo_status_t status;
5536     cairo_composite_rectangles_t extents;
5537 
5538     status = _cairo_composite_rectangles_init_for_mask (&extents,
5539 							surface->width, surface->height,
5540 							op, source, mask, clip);
5541     if (unlikely (status)) {
5542 	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
5543 	    return CAIRO_STATUS_SUCCESS;
5544 
5545 	return status;
5546     }
5547 
5548     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
5549 	cairo_status_t source_status, mask_status;
5550 
5551 	source_status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
5552 	if (_cairo_status_is_error (source_status))
5553 	    return source_status;
5554 
5555 	if (mask->has_component_alpha) {
5556 	    mask_status = CAIRO_INT_STATUS_UNSUPPORTED;
5557 	} else {
5558 	    mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask, &extents.bounded);
5559 	    if (_cairo_status_is_error (mask_status))
5560 		return mask_status;
5561 	}
5562 
5563 	return _cairo_analysis_surface_merge_status (source_status,
5564 						     mask_status);
5565     } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
5566 	status = _cairo_pdf_surface_start_fallback (surface);
5567 	if (unlikely (status))
5568 	    return status;
5569     }
5570 
5571     assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
5572     assert (_cairo_pdf_surface_operation_supported (surface, op, mask, &extents.bounded));
5573 
5574     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
5575     if (unlikely (status))
5576 	return status;
5577 
5578     group = _cairo_pdf_surface_create_smask_group (surface);
5579     if (unlikely (group == NULL))
5580 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5581 
5582     group->operation = PDF_MASK;
5583     status = _cairo_pattern_create_copy (&group->source, source);
5584     if (unlikely (status)) {
5585 	_cairo_pdf_smask_group_destroy (group);
5586 	return status;
5587     }
5588     status = _cairo_pattern_create_copy (&group->mask, mask);
5589     if (unlikely (status)) {
5590 	_cairo_pdf_smask_group_destroy (group);
5591 	return status;
5592     }
5593     group->source_res = _cairo_pdf_surface_new_object (surface);
5594     if (group->source_res.id == 0) {
5595 	_cairo_pdf_smask_group_destroy (group);
5596 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5597     }
5598 
5599     status = _cairo_pdf_surface_add_smask_group (surface, group);
5600     if (unlikely (status)) {
5601 	_cairo_pdf_smask_group_destroy (group);
5602 	return status;
5603     }
5604 
5605     status = _cairo_pdf_surface_add_smask (surface, group->group_res);
5606     if (unlikely (status))
5607 	return status;
5608 
5609     status = _cairo_pdf_surface_add_xobject (surface, group->source_res);
5610     if (unlikely (status))
5611 	return status;
5612 
5613     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5614     if (unlikely (status))
5615 	return status;
5616 
5617     status = _cairo_pdf_surface_select_operator (surface, op);
5618     if (unlikely (status))
5619 	return status;
5620 
5621     _cairo_output_stream_printf (surface->output,
5622 				 "q /s%d gs /x%d Do Q\n",
5623 				 group->group_res.id,
5624 				 group->source_res.id);
5625 
5626     return _cairo_output_stream_get_status (surface->output);
5627 }
5628 
5629 static cairo_int_status_t
_cairo_pdf_surface_stroke(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_path_fixed_t * path,const cairo_stroke_style_t * style,const cairo_matrix_t * ctm,const cairo_matrix_t * ctm_inverse,double tolerance,cairo_antialias_t antialias,cairo_clip_t * clip)5630 _cairo_pdf_surface_stroke (void			*abstract_surface,
5631 			   cairo_operator_t	 op,
5632 			   const cairo_pattern_t *source,
5633 			   cairo_path_fixed_t	*path,
5634 			   const cairo_stroke_style_t	*style,
5635 			   const cairo_matrix_t	*ctm,
5636 			   const cairo_matrix_t	*ctm_inverse,
5637 			   double		 tolerance,
5638 			   cairo_antialias_t	 antialias,
5639 			   cairo_clip_t		*clip)
5640 {
5641     cairo_pdf_surface_t *surface = abstract_surface;
5642     cairo_pdf_smask_group_t *group;
5643     cairo_pdf_resource_t pattern_res, gstate_res;
5644     cairo_composite_rectangles_t extents;
5645     cairo_status_t status;
5646 
5647     status = _cairo_composite_rectangles_init_for_stroke (&extents,
5648 							  surface->width,
5649 							  surface->height,
5650 							  op, source,
5651 							  path, style, ctm,
5652 							  clip);
5653     if (unlikely (status)) {
5654 	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
5655 	    return CAIRO_STATUS_SUCCESS;
5656 
5657 	return status;
5658     }
5659 
5660     /* use the more accurate extents */
5661     if (extents.is_bounded) {
5662 	status = _cairo_path_fixed_stroke_extents (path, style,
5663 						   ctm, ctm_inverse,
5664 						   tolerance,
5665 						   &extents.mask);
5666 	if (unlikely (status))
5667 	    return status;
5668 
5669 	if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
5670 	    return CAIRO_STATUS_SUCCESS;
5671     }
5672 
5673     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
5674 	return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
5675 
5676     assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
5677 
5678     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
5679     if (unlikely (status))
5680 	return status;
5681 
5682     pattern_res.id = 0;
5683     gstate_res.id = 0;
5684     status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
5685 						 &extents.bounded,
5686 						 &pattern_res, &gstate_res);
5687     if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
5688 	return CAIRO_STATUS_SUCCESS;
5689     if (unlikely (status))
5690 	return status;
5691 
5692     status = _cairo_pdf_surface_select_operator (surface, op);
5693     if (unlikely (status))
5694 	return status;
5695 
5696     if (gstate_res.id != 0) {
5697 	group = _cairo_pdf_surface_create_smask_group (surface);
5698 	if (unlikely (group == NULL))
5699 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5700 
5701 	group->operation = PDF_STROKE;
5702 	status = _cairo_pattern_create_copy (&group->source, source);
5703 	if (unlikely (status)) {
5704 	    _cairo_pdf_smask_group_destroy (group);
5705 	    return status;
5706 	}
5707 	group->source_res = pattern_res;
5708 	status = _cairo_path_fixed_init_copy (&group->path, path);
5709 	if (unlikely (status)) {
5710 	    _cairo_pdf_smask_group_destroy (group);
5711 	    return status;
5712 	}
5713 
5714 	group->style = *style;
5715 	group->ctm = *ctm;
5716 	group->ctm_inverse = *ctm_inverse;
5717 	status = _cairo_pdf_surface_add_smask_group (surface, group);
5718 	if (unlikely (status)) {
5719 	    _cairo_pdf_smask_group_destroy (group);
5720 	    return status;
5721 	}
5722 
5723 	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5724 	if (unlikely (status))
5725 	    return status;
5726 
5727 	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
5728 	if (unlikely (status))
5729 	    return status;
5730 
5731 	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5732 	if (unlikely (status))
5733 	    return status;
5734 
5735 	_cairo_output_stream_printf (surface->output,
5736 				     "q /s%d gs /x%d Do Q\n",
5737 				     gstate_res.id,
5738 				     group->group_res.id);
5739     } else {
5740 	status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE);
5741 	if (unlikely (status))
5742 	    return status;
5743 
5744 	status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
5745 					      path,
5746 					      style,
5747 					      ctm,
5748 					      ctm_inverse);
5749 	if (unlikely (status))
5750 	    return status;
5751 
5752 	status = _cairo_pdf_surface_unselect_pattern (surface);
5753 	if (unlikely (status))
5754 	    return status;
5755     }
5756 
5757     return _cairo_output_stream_get_status (surface->output);
5758 }
5759 
5760 static cairo_int_status_t
_cairo_pdf_surface_fill(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_path_fixed_t * path,cairo_fill_rule_t fill_rule,double tolerance,cairo_antialias_t antialias,cairo_clip_t * clip)5761 _cairo_pdf_surface_fill (void			*abstract_surface,
5762 			 cairo_operator_t	 op,
5763 			 const cairo_pattern_t	*source,
5764 			 cairo_path_fixed_t	*path,
5765 			 cairo_fill_rule_t	 fill_rule,
5766 			 double			 tolerance,
5767 			 cairo_antialias_t	 antialias,
5768 			 cairo_clip_t		*clip)
5769 {
5770     cairo_pdf_surface_t *surface = abstract_surface;
5771     cairo_status_t status;
5772     cairo_pdf_smask_group_t *group;
5773     cairo_pdf_resource_t pattern_res, gstate_res;
5774     cairo_composite_rectangles_t extents;
5775 
5776     status = _cairo_composite_rectangles_init_for_fill (&extents,
5777 							surface->width,
5778 							surface->height,
5779 							op, source, path,
5780 							clip);
5781     if (unlikely (status)) {
5782 	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
5783 	    return CAIRO_STATUS_SUCCESS;
5784 
5785 	return status;
5786     }
5787 
5788     /* use the more accurate extents */
5789     if (extents.is_bounded) {
5790 	_cairo_path_fixed_fill_extents (path,
5791 					fill_rule,
5792 					tolerance,
5793 					&extents.mask);
5794 
5795 	if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
5796 	    return CAIRO_STATUS_SUCCESS;
5797     }
5798 
5799     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
5800 	return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
5801     } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
5802 	status = _cairo_pdf_surface_start_fallback (surface);
5803 	if (unlikely (status))
5804 	    return status;
5805     }
5806 
5807     assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
5808 
5809     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
5810     if (unlikely (status))
5811 	return status;
5812 
5813     status = _cairo_pdf_surface_select_operator (surface, op);
5814     if (unlikely (status))
5815 	return status;
5816 
5817     if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
5818 	source->extend == CAIRO_EXTEND_NONE)
5819     {
5820 	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5821 	if (unlikely (status))
5822 	    return status;
5823 
5824 	_cairo_output_stream_printf (surface->output, "q\n");
5825 	status =  _cairo_pdf_operators_clip (&surface->pdf_operators,
5826 					     path,
5827 					     fill_rule);
5828 	if (unlikely (status))
5829 	    return status;
5830 
5831 	status = _cairo_pdf_surface_paint_surface_pattern (surface,
5832 							   (cairo_surface_pattern_t *) source);
5833 	if (unlikely (status))
5834 	    return status;
5835 
5836 	_cairo_output_stream_printf (surface->output, "Q\n");
5837 	return _cairo_output_stream_get_status (surface->output);
5838     }
5839 
5840     pattern_res.id = 0;
5841     gstate_res.id = 0;
5842     status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
5843 						 &extents.bounded,
5844 						 &pattern_res, &gstate_res);
5845     if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
5846 	return CAIRO_STATUS_SUCCESS;
5847     if (unlikely (status))
5848 	return status;
5849 
5850     if (gstate_res.id != 0) {
5851 	group = _cairo_pdf_surface_create_smask_group (surface);
5852 	if (unlikely (group == NULL))
5853 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
5854 
5855 	group->operation = PDF_FILL;
5856 	status = _cairo_pattern_create_copy (&group->source, source);
5857 	if (unlikely (status)) {
5858 	    _cairo_pdf_smask_group_destroy (group);
5859 	    return status;
5860 	}
5861 	group->source_res = pattern_res;
5862 	status = _cairo_path_fixed_init_copy (&group->path, path);
5863 	if (unlikely (status)) {
5864 	    _cairo_pdf_smask_group_destroy (group);
5865 	    return status;
5866 	}
5867 
5868 	group->fill_rule = fill_rule;
5869 	status = _cairo_pdf_surface_add_smask_group (surface, group);
5870 	if (unlikely (status)) {
5871 	    _cairo_pdf_smask_group_destroy (group);
5872 	    return status;
5873 	}
5874 
5875 	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
5876 	if (unlikely (status))
5877 	    return status;
5878 
5879 	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
5880 	if (unlikely (status))
5881 	    return status;
5882 
5883 	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
5884 	if (unlikely (status))
5885 	    return status;
5886 
5887 	_cairo_output_stream_printf (surface->output,
5888 				     "q /s%d gs /x%d Do Q\n",
5889 				     gstate_res.id,
5890 				     group->group_res.id);
5891     } else {
5892 	status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
5893 	if (unlikely (status))
5894 	    return status;
5895 
5896 	status = _cairo_pdf_operators_fill (&surface->pdf_operators,
5897 					    path,
5898 					    fill_rule);
5899 	if (unlikely (status))
5900 	    return status;
5901 
5902 	status = _cairo_pdf_surface_unselect_pattern (surface);
5903 	if (unlikely (status))
5904 	    return status;
5905     }
5906 
5907     return _cairo_output_stream_get_status (surface->output);
5908 }
5909 
5910 static cairo_int_status_t
_cairo_pdf_surface_fill_stroke(void * abstract_surface,cairo_operator_t fill_op,const cairo_pattern_t * fill_source,cairo_fill_rule_t fill_rule,double fill_tolerance,cairo_antialias_t fill_antialias,cairo_path_fixed_t * path,cairo_operator_t stroke_op,const cairo_pattern_t * stroke_source,const cairo_stroke_style_t * stroke_style,const cairo_matrix_t * stroke_ctm,const cairo_matrix_t * stroke_ctm_inverse,double stroke_tolerance,cairo_antialias_t stroke_antialias,cairo_clip_t * clip)5911 _cairo_pdf_surface_fill_stroke (void			*abstract_surface,
5912 				cairo_operator_t	 fill_op,
5913 				const cairo_pattern_t	*fill_source,
5914 				cairo_fill_rule_t	 fill_rule,
5915 				double			 fill_tolerance,
5916 				cairo_antialias_t	 fill_antialias,
5917 				cairo_path_fixed_t	*path,
5918 				cairo_operator_t	 stroke_op,
5919 				const cairo_pattern_t	*stroke_source,
5920 				const cairo_stroke_style_t *stroke_style,
5921 				const cairo_matrix_t	*stroke_ctm,
5922 				const cairo_matrix_t	*stroke_ctm_inverse,
5923 				double			 stroke_tolerance,
5924 				cairo_antialias_t	 stroke_antialias,
5925 				cairo_clip_t		*clip)
5926 {
5927     cairo_pdf_surface_t *surface = abstract_surface;
5928     cairo_status_t status;
5929     cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res;
5930     cairo_rectangle_int_t extents;
5931 
5932     /* During analysis we return unsupported and let the _fill and
5933      * _stroke functions that are on the fallback path do the analysis
5934      * for us. During render we may still encounter unsupported
5935      * combinations of fill/stroke patterns. However we can return
5936      * unsupported anytime to let the _fill and _stroke functions take
5937      * over.
5938      */
5939     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
5940 	return CAIRO_INT_STATUS_UNSUPPORTED;
5941 
5942     /* PDF rendering of fill-stroke is not the same as cairo when
5943      * either the fill or stroke is not opaque.
5944      */
5945     if ( !_cairo_pattern_is_opaque (fill_source, NULL) ||
5946 	 !_cairo_pattern_is_opaque (stroke_source, NULL))
5947     {
5948 	return CAIRO_INT_STATUS_UNSUPPORTED;
5949     }
5950 
5951     if (fill_op != stroke_op)
5952 	return CAIRO_INT_STATUS_UNSUPPORTED;
5953 
5954     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
5955     if (unlikely (status))
5956 	return status;
5957 
5958     status = _cairo_pdf_surface_select_operator (surface, fill_op);
5959     if (unlikely (status))
5960 	return status;
5961 
5962     status = _cairo_surface_fill_extents (&surface->base,
5963 					  fill_op, fill_source, path, fill_rule,
5964 					  fill_tolerance, fill_antialias,
5965 					  clip, &extents);
5966     if (unlikely (status))
5967 	return status;
5968 
5969 
5970     fill_pattern_res.id = 0;
5971     gstate_res.id = 0;
5972     status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
5973 						 &extents,
5974 						 &fill_pattern_res,
5975 						 &gstate_res);
5976     if (unlikely (status))
5977 	return status;
5978 
5979     assert (gstate_res.id == 0);
5980 
5981     status = _cairo_surface_stroke_extents (&surface->base,
5982 					    stroke_op, stroke_source, path,
5983 					    stroke_style, stroke_ctm, stroke_ctm_inverse,
5984 					    stroke_tolerance, stroke_antialias,
5985 					    clip, &extents);
5986     if (unlikely (status))
5987 	return status;
5988 
5989     stroke_pattern_res.id = 0;
5990     gstate_res.id = 0;
5991     status = _cairo_pdf_surface_add_pdf_pattern (surface,
5992 						 stroke_source,
5993 						 &extents,
5994 						 &stroke_pattern_res,
5995 						 &gstate_res);
5996     if (unlikely (status))
5997 	return status;
5998 
5999     assert (gstate_res.id == 0);
6000 
6001     /* As PDF has separate graphics state for fill and stroke we can
6002      * select both at the same time */
6003     status = _cairo_pdf_surface_select_pattern (surface, fill_source,
6004 						fill_pattern_res, FALSE);
6005     if (unlikely (status))
6006 	return status;
6007 
6008     status = _cairo_pdf_surface_select_pattern (surface, stroke_source,
6009 						stroke_pattern_res, TRUE);
6010     if (unlikely (status))
6011 	return status;
6012 
6013     status = _cairo_pdf_operators_fill_stroke (&surface->pdf_operators,
6014 					       path,
6015 					       fill_rule,
6016 					       stroke_style,
6017 					       stroke_ctm,
6018 					       stroke_ctm_inverse);
6019     if (unlikely (status))
6020 	return status;
6021 
6022     status = _cairo_pdf_surface_unselect_pattern (surface);
6023     if (unlikely (status))
6024 	return status;
6025 
6026     return _cairo_output_stream_get_status (surface->output);
6027 }
6028 
6029 static cairo_bool_t
_cairo_pdf_surface_has_show_text_glyphs(void * abstract_surface)6030 _cairo_pdf_surface_has_show_text_glyphs	(void			*abstract_surface)
6031 {
6032     return TRUE;
6033 }
6034 
6035 static cairo_int_status_t
_cairo_pdf_surface_show_text_glyphs(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,const char * utf8,int utf8_len,cairo_glyph_t * glyphs,int num_glyphs,const cairo_text_cluster_t * clusters,int num_clusters,cairo_text_cluster_flags_t cluster_flags,cairo_scaled_font_t * scaled_font,cairo_clip_t * clip)6036 _cairo_pdf_surface_show_text_glyphs (void			*abstract_surface,
6037 				     cairo_operator_t		 op,
6038 				     const cairo_pattern_t	*source,
6039 				     const char                 *utf8,
6040 				     int                         utf8_len,
6041 				     cairo_glyph_t		*glyphs,
6042 				     int			 num_glyphs,
6043 				     const cairo_text_cluster_t *clusters,
6044 				     int                         num_clusters,
6045 				     cairo_text_cluster_flags_t  cluster_flags,
6046 				     cairo_scaled_font_t	*scaled_font,
6047 				     cairo_clip_t		*clip)
6048 {
6049     cairo_pdf_surface_t *surface = abstract_surface;
6050     cairo_pdf_smask_group_t *group;
6051     cairo_pdf_resource_t pattern_res, gstate_res;
6052     cairo_composite_rectangles_t extents;
6053     cairo_bool_t overlap;
6054     cairo_status_t status;
6055 
6056     status = _cairo_composite_rectangles_init_for_glyphs (&extents,
6057 							  surface->width,
6058 							  surface->height,
6059 							  op, source,
6060 							  scaled_font,
6061 							  glyphs, num_glyphs,
6062 							  clip,
6063 							  &overlap);
6064     if (unlikely (status)) {
6065 	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
6066 	    return CAIRO_STATUS_SUCCESS;
6067 
6068 	return status;
6069     }
6070 
6071     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
6072 	return _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
6073 
6074     assert (_cairo_pdf_surface_operation_supported (surface, op, source, &extents.bounded));
6075 
6076     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
6077     if (unlikely (status))
6078 	return status;
6079 
6080     pattern_res.id = 0;
6081     gstate_res.id = 0;
6082     status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
6083 						 &extents.bounded,
6084 						 &pattern_res, &gstate_res);
6085     if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
6086 	return CAIRO_STATUS_SUCCESS;
6087     if (unlikely (status))
6088 	return status;
6089 
6090     status = _cairo_pdf_surface_select_operator (surface, op);
6091     if (unlikely (status))
6092 	return status;
6093 
6094     if (gstate_res.id != 0) {
6095 	group = _cairo_pdf_surface_create_smask_group (surface);
6096 	if (unlikely (group == NULL))
6097 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6098 
6099 	group->operation = PDF_SHOW_GLYPHS;
6100 	status = _cairo_pattern_create_copy (&group->source, source);
6101 	if (unlikely (status)) {
6102 	    _cairo_pdf_smask_group_destroy (group);
6103 	    return status;
6104 	}
6105 	group->source_res = pattern_res;
6106 
6107 	if (utf8_len) {
6108 	    group->utf8 = malloc (utf8_len);
6109 	    if (unlikely (group->utf8 == NULL)) {
6110 		_cairo_pdf_smask_group_destroy (group);
6111 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6112 	    }
6113 	    memcpy (group->utf8, utf8, utf8_len);
6114 	}
6115 	group->utf8_len = utf8_len;
6116 
6117 	if (num_glyphs) {
6118 	    group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
6119 	    if (unlikely (group->glyphs == NULL)) {
6120 		_cairo_pdf_smask_group_destroy (group);
6121 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6122 	    }
6123 	    memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
6124 	}
6125 	group->num_glyphs = num_glyphs;
6126 
6127 	if (num_clusters) {
6128 	    group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
6129 	    if (unlikely (group->clusters == NULL)) {
6130 		_cairo_pdf_smask_group_destroy (group);
6131 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
6132 	    }
6133 	    memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
6134 	}
6135 	group->num_clusters = num_clusters;
6136 
6137 	group->scaled_font = cairo_scaled_font_reference (scaled_font);
6138 	status = _cairo_pdf_surface_add_smask_group (surface, group);
6139 	if (unlikely (status)) {
6140 	    _cairo_pdf_smask_group_destroy (group);
6141 	    return status;
6142 	}
6143 
6144 	status = _cairo_pdf_surface_add_smask (surface, gstate_res);
6145 	if (unlikely (status))
6146 	    return status;
6147 
6148 	status = _cairo_pdf_surface_add_xobject (surface, group->group_res);
6149 	if (unlikely (status))
6150 	    return status;
6151 
6152 	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6153 	if (unlikely (status))
6154 	    return status;
6155 
6156 	_cairo_output_stream_printf (surface->output,
6157 				     "q /s%d gs /x%d Do Q\n",
6158 				     gstate_res.id,
6159 				     group->group_res.id);
6160     } else {
6161 	status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
6162 	if (unlikely (status))
6163 	    return status;
6164 
6165 	/* Each call to show_glyphs() with a transclucent pattern must
6166 	 * be in a separate text object otherwise overlapping text
6167 	 * from separate calls to show_glyphs will not composite with
6168 	 * each other. */
6169 	if (! _cairo_pattern_is_opaque (source, &extents.bounded)) {
6170 	    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
6171 	    if (unlikely (status))
6172 		return status;
6173 	}
6174 
6175 	status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
6176 							utf8, utf8_len,
6177 							glyphs, num_glyphs,
6178 							clusters, num_clusters,
6179 							cluster_flags,
6180 							scaled_font);
6181 	if (unlikely (status))
6182 	    return status;
6183 
6184 	status = _cairo_pdf_surface_unselect_pattern (surface);
6185 	if (unlikely (status))
6186 	    return status;
6187     }
6188 
6189     return _cairo_output_stream_get_status (surface->output);
6190 }
6191 
6192 
6193 static void
_cairo_pdf_surface_set_paginated_mode(void * abstract_surface,cairo_paginated_mode_t paginated_mode)6194 _cairo_pdf_surface_set_paginated_mode (void			*abstract_surface,
6195 				       cairo_paginated_mode_t	 paginated_mode)
6196 {
6197     cairo_pdf_surface_t *surface = abstract_surface;
6198 
6199     surface->paginated_mode = paginated_mode;
6200 }
6201 
6202 static const cairo_surface_backend_t cairo_pdf_surface_backend = {
6203     CAIRO_SURFACE_TYPE_PDF,
6204     NULL, /* create similar: handled by wrapper */
6205     _cairo_pdf_surface_finish,
6206     NULL, /* acquire_source_image */
6207     NULL, /* release_source_image */
6208     NULL, /* acquire_dest_image */
6209     NULL, /* release_dest_image */
6210     NULL, /* clone_similar */
6211     NULL, /* composite */
6212     NULL, /* fill_rectangles */
6213     NULL, /* composite_trapezoids */
6214     NULL, /* create_span_renderer */
6215     NULL, /* check_span_renderer */
6216     NULL,  /* _cairo_pdf_surface_copy_page */
6217     _cairo_pdf_surface_show_page,
6218     _cairo_pdf_surface_get_extents,
6219     NULL, /* old_show_glyphs */
6220     _cairo_pdf_surface_get_font_options,
6221     NULL, /* flush */
6222     NULL, /* mark_dirty_rectangle */
6223     NULL, /* scaled_font_fini */
6224     NULL, /* scaled_glyph_fini */
6225 
6226     /* Here are the drawing functions */
6227 
6228     _cairo_pdf_surface_paint,
6229     _cairo_pdf_surface_mask,
6230     _cairo_pdf_surface_stroke,
6231     _cairo_pdf_surface_fill,
6232     NULL, /* show_glyphs */
6233     NULL, /* snapshot */
6234 
6235     NULL, /* is_compatible */
6236     _cairo_pdf_surface_fill_stroke,
6237     NULL, /* create_solid_pattern_surface */
6238     NULL, /* can_repaint_solid_pattern_surface */
6239     _cairo_pdf_surface_has_show_text_glyphs,
6240     _cairo_pdf_surface_show_text_glyphs,
6241 };
6242 
6243 static const cairo_paginated_surface_backend_t
6244 cairo_pdf_surface_paginated_backend = {
6245     _cairo_pdf_surface_start_page,
6246     _cairo_pdf_surface_set_paginated_mode,
6247     NULL, /* set_bounding_box */
6248     _cairo_pdf_surface_has_fallback_images,
6249     _cairo_pdf_surface_supports_fine_grained_fallbacks,
6250 };
6251