tizen 2.3.1 release
[framework/graphics/cairo.git] / src / cairo-ps-surface.c
1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /* cairo - a vector graphics library with display and print output
3  *
4  * Copyright © 2003 University of Southern California
5  * Copyright © 2005 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  *      Carl D. Worth <cworth@cworth.org>
38  *      Kristian Høgsberg <krh@redhat.com>
39  *      Keith Packard <keithp@keithp.com>
40  *      Adrian Johnson <ajohnson@redneon.com>
41  */
42
43
44 /*
45  * Design of the PS output:
46  *
47  * The PS output is harmonised with the PDF operations using PS procedures
48  * to emulate the PDF operators.
49  *
50  * This has a number of advantages:
51  *   1. A large chunk of code is shared between the PDF and PS backends.
52  *      See cairo-pdf-operators.
53  *   2. Using gs to do PS -> PDF and PDF -> PS will always work well.
54  */
55
56 #define _BSD_SOURCE /* for ctime_r(), snprintf(), strdup() */
57 #include "cairoint.h"
58
59 #include "cairo-ps.h"
60 #include "cairo-ps-surface-private.h"
61
62 #include "cairo-pdf-operators-private.h"
63 #include "cairo-pdf-shading-private.h"
64
65 #include "cairo-array-private.h"
66 #include "cairo-composite-rectangles-private.h"
67 #include "cairo-default-context-private.h"
68 #include "cairo-error-private.h"
69 #include "cairo-image-surface-inline.h"
70 #include "cairo-list-inline.h"
71 #include "cairo-scaled-font-subsets-private.h"
72 #include "cairo-paginated-private.h"
73 #include "cairo-recording-surface-private.h"
74 #include "cairo-surface-clipper-private.h"
75 #include "cairo-surface-snapshot-inline.h"
76 #include "cairo-surface-subsurface-private.h"
77 #include "cairo-output-stream-private.h"
78 #include "cairo-type3-glyph-surface-private.h"
79 #include "cairo-image-info-private.h"
80
81 #include <stdio.h>
82 #include <ctype.h>
83 #include <time.h>
84 #include <zlib.h>
85 #include <errno.h>
86
87 #define DEBUG_PS 0
88
89 #if DEBUG_PS
90 #define DEBUG_FALLBACK(s) \
91     fprintf (stderr, "%s::%d -- %s\n", __FUNCTION__, __LINE__, (s))
92 #else
93 #define DEBUG_FALLBACK(s)
94 #endif
95
96 #ifndef HAVE_CTIME_R
97 #define ctime_r(T, BUF) ctime (T)
98 #endif
99
100 /**
101  * SECTION:cairo-ps
102  * @Title: PostScript Surfaces
103  * @Short_Description: Rendering PostScript documents
104  * @See_Also: #cairo_surface_t
105  *
106  * The PostScript surface is used to render cairo graphics to Adobe
107  * PostScript files and is a multi-page vector surface backend.
108  **/
109
110 /**
111  * CAIRO_HAS_PS_SURFACE:
112  * 
113  * Defined if the PostScript surface backend is available.
114  * This macro can be used to conditionally compile backend-specific code.
115  *
116  * Since: 1.2
117  **/
118
119 typedef enum {
120     CAIRO_PS_COMPRESS_NONE,
121     CAIRO_PS_COMPRESS_LZW,
122     CAIRO_PS_COMPRESS_DEFLATE
123  } cairo_ps_compress_t;
124
125 static const cairo_surface_backend_t cairo_ps_surface_backend;
126 static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
127
128 static cairo_bool_t
129 _cairo_ps_surface_get_extents (void                    *abstract_surface,
130                                cairo_rectangle_int_t   *rectangle);
131
132 static const cairo_ps_level_t _cairo_ps_levels[] =
133 {
134     CAIRO_PS_LEVEL_2,
135     CAIRO_PS_LEVEL_3
136 };
137
138 #define CAIRO_PS_LEVEL_LAST ARRAY_LENGTH (_cairo_ps_levels)
139
140 static const char * _cairo_ps_level_strings[CAIRO_PS_LEVEL_LAST] =
141 {
142     "PS Level 2",
143     "PS Level 3"
144 };
145
146 static const char *_cairo_ps_supported_mime_types[] =
147 {
148     CAIRO_MIME_TYPE_JPEG,
149     NULL
150 };
151
152 typedef struct _cairo_page_standard_media {
153     const char *name;
154     int width;
155     int height;
156 } cairo_page_standard_media_t;
157
158 static const cairo_page_standard_media_t _cairo_page_standard_media[] =
159 {
160     { "A0",       2384, 3371 },
161     { "A1",       1685, 2384 },
162     { "A2",       1190, 1684 },
163     { "A3",        842, 1190 },
164     { "A4",        595,  842 },
165     { "A5",        420,  595 },
166     { "B4",        729, 1032 },
167     { "B5",        516,  729 },
168     { "Letter",    612,  792 },
169     { "Tabloid",   792, 1224 },
170     { "Ledger",   1224,  792 },
171     { "Legal",     612, 1008 },
172     { "Statement", 396,  612 },
173     { "Executive", 540,  720 },
174     { "Folio",     612,  936 },
175     { "Quarto",    610,  780 },
176     { "10x14",     720, 1008 },
177 };
178
179 typedef struct _cairo_page_media {
180     char *name;
181     int width;
182     int height;
183     cairo_list_t link;
184 } cairo_page_media_t;
185
186 static void
187 _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
188 {
189     char ctime_buf[26];
190     time_t now;
191     char **comments;
192     int i, num_comments;
193     int level;
194     const char *eps_header = "";
195     cairo_bool_t has_bbox;
196
197     if (surface->has_creation_date)
198         now = surface->creation_date;
199     else
200         now = time (NULL);
201
202     if (surface->ps_level_used == CAIRO_PS_LEVEL_2)
203         level = 2;
204     else
205         level = 3;
206
207     if (surface->eps)
208         eps_header = " EPSF-3.0";
209
210     _cairo_output_stream_printf (surface->final_stream,
211                                  "%%!PS-Adobe-3.0%s\n"
212                                  "%%%%Creator: cairo %s (http://cairographics.org)\n"
213                                  "%%%%CreationDate: %s"
214                                  "%%%%Pages: %d\n",
215                                  eps_header,
216                                  cairo_version_string (),
217                                  ctime_r (&now, ctime_buf),
218                                  surface->num_pages);
219
220     _cairo_output_stream_printf (surface->final_stream,
221                                  "%%%%DocumentData: Clean7Bit\n"
222                                  "%%%%LanguageLevel: %d\n",
223                                  level);
224
225     if (!cairo_list_is_empty (&surface->document_media)) {
226         cairo_page_media_t *page;
227         cairo_bool_t first = TRUE;
228
229         cairo_list_foreach_entry (page, cairo_page_media_t, &surface->document_media, link) {
230             if (first) {
231                 _cairo_output_stream_printf (surface->final_stream,
232                                              "%%%%DocumentMedia: ");
233                 first = FALSE;
234             } else {
235                 _cairo_output_stream_printf (surface->final_stream,
236                                              "%%%%+ ");
237             }
238             _cairo_output_stream_printf (surface->final_stream,
239                                          "%s %d %d 0 () ()\n",
240                                          page->name,
241                                          page->width,
242                                          page->height);
243         }
244     }
245
246     has_bbox = FALSE;
247     num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
248     comments = _cairo_array_index (&surface->dsc_header_comments, 0);
249     if (comments == NULL)
250         return;
251
252     for (i = 0; i < num_comments; i++) {
253         _cairo_output_stream_printf (surface->final_stream,
254                                      "%s\n", comments[i]);
255         if (strncmp (comments[i], "%%BoundingBox:", 14) == 0)
256             has_bbox = TRUE;
257
258         free (comments[i]);
259         comments[i] = NULL;
260     }
261
262     if (!has_bbox) {
263         _cairo_output_stream_printf (surface->final_stream,
264                                      "%%%%BoundingBox: %d %d %d %d\n",
265                                      surface->bbox_x1,
266                                      surface->bbox_y1,
267                                      surface->bbox_x2,
268                                      surface->bbox_y2);
269     }
270
271     _cairo_output_stream_printf (surface->final_stream,
272                                  "%%%%EndComments\n");
273
274     _cairo_output_stream_printf (surface->final_stream,
275                                  "%%%%BeginProlog\n");
276
277     if (surface->eps) {
278         _cairo_output_stream_printf (surface->final_stream,
279                                      "save\n"
280                                      "50 dict begin\n");
281     } else {
282         _cairo_output_stream_printf (surface->final_stream,
283                                      "/languagelevel where\n"
284                                      "{ pop languagelevel } { 1 } ifelse\n"
285                                      "%d lt { /Helvetica findfont 12 scalefont setfont 50 500 moveto\n"
286                                      "  (This print job requires a PostScript Language Level %d printer.) show\n"
287                                      "  showpage quit } if\n",
288                                      level,
289                                      level);
290     }
291
292     _cairo_output_stream_printf (surface->final_stream,
293                                  "/q { gsave } bind def\n"
294                                  "/Q { grestore } bind def\n"
295                                  "/cm { 6 array astore concat } bind def\n"
296                                  "/w { setlinewidth } bind def\n"
297                                  "/J { setlinecap } bind def\n"
298                                  "/j { setlinejoin } bind def\n"
299                                  "/M { setmiterlimit } bind def\n"
300                                  "/d { setdash } bind def\n"
301                                  "/m { moveto } bind def\n"
302                                  "/l { lineto } bind def\n"
303                                  "/c { curveto } bind def\n"
304                                  "/h { closepath } bind def\n"
305                                  "/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto\n"
306                                  "      0 exch rlineto 0 rlineto closepath } bind def\n"
307                                  "/S { stroke } bind def\n"
308                                  "/f { fill } bind def\n"
309                                  "/f* { eofill } bind def\n"
310                                  "/n { newpath } bind def\n"
311                                  "/W { clip } bind def\n"
312                                  "/W* { eoclip } bind def\n"
313                                  "/BT { } bind def\n"
314                                  "/ET { } bind def\n"
315                                  "/pdfmark where { pop globaldict /?pdfmark /exec load put }\n"
316                                  "    { globaldict begin /?pdfmark /pop load def /pdfmark\n"
317                                  "    /cleartomark load def end } ifelse\n"
318                                  "/BDC { mark 3 1 roll /BDC pdfmark } bind def\n"
319                                  "/EMC { mark /EMC pdfmark } bind def\n"
320                                  "/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def\n"
321                                  "/Tj { show currentpoint cairo_store_point } bind def\n"
322                                  "/TJ {\n"
323                                  "  {\n"
324                                  "    dup\n"
325                                  "    type /stringtype eq\n"
326                                  "    { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse\n"
327                                  "  } forall\n"
328                                  "  currentpoint cairo_store_point\n"
329                                  "} bind def\n"
330                                  "/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore\n"
331                                  "    cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def\n"
332                                  "/Tf { pop /cairo_font exch def /cairo_font_matrix where\n"
333                                  "      { pop cairo_selectfont } if } bind def\n"
334                                  "/Td { matrix translate cairo_font_matrix matrix concatmatrix dup\n"
335                                  "      /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point\n"
336                                  "      /cairo_font where { pop cairo_selectfont } if } bind def\n"
337                                  "/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def\n"
338                                  "      cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def\n"
339                                  "/g { setgray } bind def\n"
340                                  "/rg { setrgbcolor } bind def\n"
341                                  "/d1 { setcachedevice } bind def\n");
342
343     _cairo_output_stream_printf (surface->final_stream,
344                                  "%%%%EndProlog\n");
345
346     num_comments = _cairo_array_num_elements (&surface->dsc_setup_comments);
347     if (num_comments) {
348         _cairo_output_stream_printf (surface->final_stream,
349                                      "%%%%BeginSetup\n");
350
351         comments = _cairo_array_index (&surface->dsc_setup_comments, 0);
352         for (i = 0; i < num_comments; i++) {
353             _cairo_output_stream_printf (surface->final_stream,
354                                          "%s\n", comments[i]);
355             free (comments[i]);
356             comments[i] = NULL;
357         }
358
359         _cairo_output_stream_printf (surface->final_stream,
360                                      "%%%%EndSetup\n");
361     }
362 }
363
364 static cairo_status_t
365 _cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t            *surface,
366                                           cairo_scaled_font_subset_t    *font_subset)
367
368
369 {
370     cairo_type1_subset_t subset;
371     cairo_status_t status;
372     int length;
373     char name[64];
374
375     snprintf (name, sizeof name, "f-%d-%d",
376               font_subset->font_id, font_subset->subset_id);
377     status = _cairo_type1_subset_init (&subset, name, font_subset, TRUE);
378     if (unlikely (status))
379         return status;
380
381     /* FIXME: Figure out document structure convention for fonts */
382
383 #if DEBUG_PS
384     _cairo_output_stream_printf (surface->final_stream,
385                                  "%% _cairo_ps_surface_emit_type1_font_subset\n");
386 #endif
387
388     length = subset.header_length + subset.data_length + subset.trailer_length;
389     _cairo_output_stream_write (surface->final_stream, subset.data, length);
390
391     _cairo_type1_subset_fini (&subset);
392
393     return CAIRO_STATUS_SUCCESS;
394 }
395
396
397 static cairo_status_t
398 _cairo_ps_surface_emit_type1_font_fallback (cairo_ps_surface_t          *surface,
399                                             cairo_scaled_font_subset_t  *font_subset)
400 {
401     cairo_type1_subset_t subset;
402     cairo_status_t status;
403     int length;
404     char name[64];
405
406     snprintf (name, sizeof name, "f-%d-%d",
407               font_subset->font_id, font_subset->subset_id);
408     status = _cairo_type1_fallback_init_hex (&subset, name, font_subset);
409     if (unlikely (status))
410         return status;
411
412     /* FIXME: Figure out document structure convention for fonts */
413
414 #if DEBUG_PS
415     _cairo_output_stream_printf (surface->final_stream,
416                                  "%% _cairo_ps_surface_emit_type1_font_fallback\n");
417 #endif
418
419     length = subset.header_length + subset.data_length + subset.trailer_length;
420     _cairo_output_stream_write (surface->final_stream, subset.data, length);
421
422     _cairo_type1_fallback_fini (&subset);
423
424     return CAIRO_STATUS_SUCCESS;
425 }
426
427 static cairo_status_t
428 _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t         *surface,
429                                              cairo_scaled_font_subset_t *font_subset)
430
431
432 {
433     cairo_truetype_subset_t subset;
434     cairo_status_t status;
435     unsigned int i, begin, end;
436
437     status = _cairo_truetype_subset_init_ps (&subset, font_subset);
438     if (unlikely (status))
439         return status;
440
441     /* FIXME: Figure out document structure convention for fonts */
442
443 #if DEBUG_PS
444     _cairo_output_stream_printf (surface->final_stream,
445                                  "%% _cairo_ps_surface_emit_truetype_font_subset\n");
446 #endif
447
448     _cairo_output_stream_printf (surface->final_stream,
449                                  "11 dict begin\n"
450                                  "/FontType 42 def\n"
451                                  "/FontName /%s def\n"
452                                  "/PaintType 0 def\n"
453                                  "/FontMatrix [ 1 0 0 1 0 0 ] def\n"
454                                  "/FontBBox [ 0 0 0 0 ] def\n"
455                                  "/Encoding 256 array def\n"
456                                  "0 1 255 { Encoding exch /.notdef put } for\n",
457                                  subset.ps_name);
458
459     /* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
460
461     if (font_subset->is_latin) {
462         for (i = 1; i < 256; i++) {
463             if (font_subset->latin_to_subset_glyph_index[i] > 0) {
464                 if (font_subset->glyph_names != NULL) {
465                     _cairo_output_stream_printf (surface->final_stream,
466                                                  "Encoding %d /%s put\n",
467                                                  i, font_subset->glyph_names[font_subset->latin_to_subset_glyph_index[i]]);
468                 } else {
469                     _cairo_output_stream_printf (surface->final_stream,
470                                                  "Encoding %d /g%ld put\n", i, font_subset->latin_to_subset_glyph_index[i]);
471                 }
472             }
473         }
474     } else {
475         for (i = 1; i < font_subset->num_glyphs; i++) {
476             if (font_subset->glyph_names != NULL) {
477                 _cairo_output_stream_printf (surface->final_stream,
478                                              "Encoding %d /%s put\n",
479                                              i, font_subset->glyph_names[i]);
480             } else {
481                 _cairo_output_stream_printf (surface->final_stream,
482                                              "Encoding %d /g%d put\n", i, i);
483             }
484         }
485     }
486
487     _cairo_output_stream_printf (surface->final_stream,
488                                  "/CharStrings %d dict dup begin\n"
489                                  "/.notdef 0 def\n",
490                                  font_subset->num_glyphs);
491
492     for (i = 1; i < font_subset->num_glyphs; i++) {
493         if (font_subset->glyph_names != NULL) {
494             _cairo_output_stream_printf (surface->final_stream,
495                                          "/%s %d def\n",
496                                          font_subset->glyph_names[i], i);
497         } else {
498             _cairo_output_stream_printf (surface->final_stream,
499                                          "/g%d %d def\n", i, i);
500         }
501     }
502
503     _cairo_output_stream_printf (surface->final_stream,
504                                  "end readonly def\n");
505
506     _cairo_output_stream_printf (surface->final_stream,
507                                  "/sfnts [\n");
508     begin = 0;
509     end = 0;
510     for (i = 0; i < subset.num_string_offsets; i++) {
511         end = subset.string_offsets[i];
512         _cairo_output_stream_printf (surface->final_stream,"<");
513         _cairo_output_stream_write_hex_string (surface->final_stream,
514                                                subset.data + begin, end - begin);
515         _cairo_output_stream_printf (surface->final_stream,"00>\n");
516         begin = end;
517     }
518     if (subset.data_length > end) {
519         _cairo_output_stream_printf (surface->final_stream,"<");
520         _cairo_output_stream_write_hex_string (surface->final_stream,
521                                                subset.data + end, subset.data_length - end);
522         _cairo_output_stream_printf (surface->final_stream,"00>\n");
523     }
524
525     _cairo_output_stream_printf (surface->final_stream,
526                                  "] def\n"
527                                  "/f-%d-%d currentdict end definefont pop\n",
528                                  font_subset->font_id,
529                                  font_subset->subset_id);
530
531     _cairo_truetype_subset_fini (&subset);
532
533     return CAIRO_STATUS_SUCCESS;
534 }
535
536 static cairo_status_t
537 _cairo_ps_emit_imagemask (cairo_image_surface_t *image,
538                           cairo_output_stream_t *stream)
539 {
540     uint8_t *row, *byte;
541     int rows, cols;
542
543     /* The only image type supported by Type 3 fonts are 1-bit image
544      * masks */
545     assert (image->format == CAIRO_FORMAT_A1);
546
547     _cairo_output_stream_printf (stream,
548                                  "<<\n"
549                                  "   /ImageType 1\n"
550                                  "   /Width %d\n"
551                                  "   /Height %d\n"
552                                  "   /ImageMatrix [%d 0 0 %d 0 %d]\n"
553                                  "   /Decode [1 0]\n"
554                                  "   /BitsPerComponent 1\n",
555                                  image->width,
556                                  image->height,
557                                  image->width,
558                                  -image->height,
559                                  image->height);
560
561     _cairo_output_stream_printf (stream,
562                                  "   /DataSource {<\n   ");
563     for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
564         for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
565             uint8_t output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
566             _cairo_output_stream_printf (stream, "%02x ", output_byte);
567         }
568         _cairo_output_stream_printf (stream, "\n   ");
569     }
570     _cairo_output_stream_printf (stream, ">}\n>>\n");
571
572     _cairo_output_stream_printf (stream,
573                                  "imagemask\n");
574
575     return _cairo_output_stream_get_status (stream);
576 }
577
578 static cairo_int_status_t
579 _cairo_ps_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
580                                             void                       *closure)
581 {
582     cairo_ps_surface_t *surface = closure;
583     cairo_status_t status = CAIRO_STATUS_SUCCESS;
584     unsigned int i;
585     cairo_surface_t *type3_surface;
586
587     type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
588                                                        NULL,
589                                                        _cairo_ps_emit_imagemask,
590                                                        surface->font_subsets);
591
592     for (i = 0; i < font_subset->num_glyphs; i++) {
593         status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
594                                                            font_subset->glyphs[i]);
595         if (unlikely (status))
596             break;
597
598     }
599     cairo_surface_finish (type3_surface);
600     cairo_surface_destroy (type3_surface);
601
602     return status;
603 }
604
605 static cairo_status_t
606 _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t            *surface,
607                                           cairo_scaled_font_subset_t    *font_subset)
608
609
610 {
611     cairo_status_t status;
612     unsigned int i;
613     cairo_box_t font_bbox = {{0,0},{0,0}};
614     cairo_box_t bbox = {{0,0},{0,0}};
615     cairo_surface_t *type3_surface;
616     double width;
617
618     if (font_subset->num_glyphs == 0)
619         return CAIRO_STATUS_SUCCESS;
620
621 #if DEBUG_PS
622     _cairo_output_stream_printf (surface->final_stream,
623                                  "%% _cairo_ps_surface_emit_type3_font_subset\n");
624 #endif
625
626     _cairo_output_stream_printf (surface->final_stream,
627                                  "8 dict begin\n"
628                                  "/FontType 3 def\n"
629                                  "/FontMatrix [1 0 0 1 0 0] def\n"
630                                  "/Encoding 256 array def\n"
631                                  "0 1 255 { Encoding exch /.notdef put } for\n");
632
633     type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
634                                                        NULL,
635                                                        _cairo_ps_emit_imagemask,
636                                                        surface->font_subsets);
637     status = type3_surface->status;
638     if (unlikely (status)) {
639         cairo_surface_destroy (type3_surface);
640         return status;
641     }
642
643     for (i = 0; i < font_subset->num_glyphs; i++) {
644         if (font_subset->glyph_names != NULL) {
645             _cairo_output_stream_printf (surface->final_stream,
646                                          "Encoding %d /%s put\n",
647                                          i, font_subset->glyph_names[i]);
648         } else {
649             _cairo_output_stream_printf (surface->final_stream,
650                                          "Encoding %d /g%d put\n", i, i);
651         }
652     }
653
654     _cairo_output_stream_printf (surface->final_stream,
655                                  "/Glyphs [\n");
656
657     for (i = 0; i < font_subset->num_glyphs; i++) {
658         _cairo_output_stream_printf (surface->final_stream,
659                                      "    { %% %d\n", i);
660         status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
661                                                         surface->final_stream,
662                                                         font_subset->glyphs[i],
663                                                         &bbox,
664                                                         &width);
665         if (unlikely (status))
666             break;
667
668         _cairo_output_stream_printf (surface->final_stream,
669                                      "    }\n");
670         if (i == 0) {
671             font_bbox.p1.x = bbox.p1.x;
672             font_bbox.p1.y = bbox.p1.y;
673             font_bbox.p2.x = bbox.p2.x;
674             font_bbox.p2.y = bbox.p2.y;
675         } else {
676             if (bbox.p1.x < font_bbox.p1.x)
677                 font_bbox.p1.x = bbox.p1.x;
678             if (bbox.p1.y < font_bbox.p1.y)
679                 font_bbox.p1.y = bbox.p1.y;
680             if (bbox.p2.x > font_bbox.p2.x)
681                 font_bbox.p2.x = bbox.p2.x;
682             if (bbox.p2.y > font_bbox.p2.y)
683                 font_bbox.p2.y = bbox.p2.y;
684         }
685     }
686     cairo_surface_finish (type3_surface);
687     cairo_surface_destroy (type3_surface);
688     if (unlikely (status))
689         return status;
690
691     _cairo_output_stream_printf (surface->final_stream,
692                                  "] def\n"
693                                  "/FontBBox [%f %f %f %f] def\n"
694                                  "/BuildChar {\n"
695                                  "  exch /Glyphs get\n"
696                                  "  exch get\n"
697                                  "  10 dict begin exec end\n"
698                                  "} bind def\n"
699                                  "currentdict\n"
700                                  "end\n"
701                                  "/f-%d-%d exch definefont pop\n",
702                                  _cairo_fixed_to_double (font_bbox.p1.x),
703                                  - _cairo_fixed_to_double (font_bbox.p2.y),
704                                  _cairo_fixed_to_double (font_bbox.p2.x),
705                                  - _cairo_fixed_to_double (font_bbox.p1.y),
706                                  font_subset->font_id,
707                                  font_subset->subset_id);
708
709     return CAIRO_STATUS_SUCCESS;
710 }
711
712 static cairo_int_status_t
713 _cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
714                                             void                        *closure)
715 {
716     cairo_ps_surface_t *surface = closure;
717     cairo_int_status_t status;
718
719     status = _cairo_scaled_font_subset_create_glyph_names (font_subset);
720     if (_cairo_int_status_is_error (status))
721         return status;
722
723     status = _cairo_ps_surface_emit_type1_font_subset (surface, font_subset);
724     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
725         return status;
726
727     status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset);
728     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
729         return status;
730
731     status = _cairo_ps_surface_emit_type1_font_fallback (surface, font_subset);
732     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
733         return status;
734
735     ASSERT_NOT_REACHED;
736     return CAIRO_STATUS_SUCCESS;
737 }
738
739 static cairo_int_status_t
740 _cairo_ps_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
741                                            void                       *closure)
742 {
743     cairo_ps_surface_t *surface = closure;
744     cairo_int_status_t status;
745
746     status = _cairo_scaled_font_subset_create_glyph_names (font_subset);
747     if (_cairo_int_status_is_error (status))
748         return status;
749
750     status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset);
751     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
752         return status;
753
754     ASSERT_NOT_REACHED;
755     return CAIRO_INT_STATUS_SUCCESS;
756 }
757
758 static cairo_status_t
759 _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface)
760 {
761     cairo_status_t status;
762
763 #if DEBUG_PS
764     _cairo_output_stream_printf (surface->final_stream,
765                                  "%% _cairo_ps_surface_emit_font_subsets\n");
766 #endif
767
768     status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
769                                                       _cairo_ps_surface_analyze_user_font_subset,
770                                                       surface);
771     if (unlikely (status))
772         return status;
773
774     status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
775                                                           _cairo_ps_surface_emit_unscaled_font_subset,
776                                                           surface);
777     if (unlikely (status))
778         return status;
779
780     status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
781                                                         _cairo_ps_surface_emit_scaled_font_subset,
782                                                         surface);
783     if (unlikely (status))
784         return status;
785
786     return _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
787                                                     _cairo_ps_surface_emit_scaled_font_subset,
788                                                     surface);
789 }
790
791 static cairo_status_t
792 _cairo_ps_surface_emit_body (cairo_ps_surface_t *surface)
793 {
794     char    buf[4096];
795     int     n;
796
797     if (ferror (surface->tmpfile) != 0)
798         return _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR);
799
800     rewind (surface->tmpfile);
801     while ((n = fread (buf, 1, sizeof (buf), surface->tmpfile)) > 0)
802         _cairo_output_stream_write (surface->final_stream, buf, n);
803
804     if (ferror (surface->tmpfile) != 0)
805         return _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR);
806
807     return CAIRO_STATUS_SUCCESS;
808 }
809
810 static void
811 _cairo_ps_surface_emit_footer (cairo_ps_surface_t *surface)
812 {
813     _cairo_output_stream_printf (surface->final_stream,
814                                  "%%%%Trailer\n");
815
816     if (surface->eps) {
817         _cairo_output_stream_printf (surface->final_stream,
818                                      "end restore\n");
819     }
820
821     _cairo_output_stream_printf (surface->final_stream,
822                                  "%%%%EOF\n");
823 }
824
825 static cairo_bool_t
826 _path_covers_bbox (cairo_ps_surface_t *surface,
827                    cairo_path_fixed_t *path)
828 {
829     cairo_box_t box;
830
831     if (_cairo_path_fixed_is_box (path, &box)) {
832         cairo_rectangle_int_t rect;
833
834         _cairo_box_round_to_rectangle (&box, &rect);
835
836         /* skip trivial whole-page clips */
837         if (_cairo_rectangle_intersect (&rect, &surface->page_bbox)) {
838             if (rect.x == surface->page_bbox.x &&
839                 rect.width == surface->page_bbox.width &&
840                 rect.y == surface->page_bbox.y &&
841                 rect.height == surface->page_bbox.height)
842             {
843                 return TRUE;
844             }
845         }
846     }
847
848     return FALSE;
849 }
850
851 static cairo_status_t
852 _cairo_ps_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
853                                                cairo_path_fixed_t *path,
854                                                cairo_fill_rule_t   fill_rule,
855                                                double               tolerance,
856                                                cairo_antialias_t   antialias)
857 {
858     cairo_ps_surface_t *surface = cairo_container_of (clipper,
859                                                       cairo_ps_surface_t,
860                                                       clipper);
861     cairo_output_stream_t *stream = surface->stream;
862     cairo_status_t status;
863
864     assert (surface->paginated_mode != CAIRO_PAGINATED_MODE_ANALYZE);
865
866 #if DEBUG_PS
867     _cairo_output_stream_printf (stream,
868                                  "%% _cairo_ps_surface_intersect_clip_path\n");
869 #endif
870
871     if (path == NULL) {
872         status = _cairo_pdf_operators_flush (&surface->pdf_operators);
873         if (unlikely (status))
874             return status;
875
876         _cairo_output_stream_printf (stream, "Q q\n");
877
878         surface->current_pattern_is_solid_color = FALSE;
879         _cairo_pdf_operators_reset (&surface->pdf_operators);
880
881         return CAIRO_STATUS_SUCCESS;
882     }
883
884     if (_path_covers_bbox (surface, path))
885         return CAIRO_STATUS_SUCCESS;
886
887     return _cairo_pdf_operators_clip (&surface->pdf_operators,
888                                       path,
889                                       fill_rule);
890 }
891
892 /* PLRM specifies a tolerance of 5 points when matching page sizes */
893 static cairo_bool_t
894 _ps_page_dimension_equal (int a, int b)
895 {
896     return (abs (a - b) < 5);
897 }
898
899 static const char *
900 _cairo_ps_surface_get_page_media (cairo_ps_surface_t     *surface)
901 {
902     int width, height, i;
903     char buf[50];
904     cairo_page_media_t *page;
905     const char *page_name;
906
907     width = _cairo_lround (surface->width);
908     height = _cairo_lround (surface->height);
909
910     /* search previously used page sizes */
911     cairo_list_foreach_entry (page, cairo_page_media_t, &surface->document_media, link) {
912         if (_ps_page_dimension_equal (width, page->width) &&
913             _ps_page_dimension_equal (height, page->height))
914             return page->name;
915     }
916
917     /* search list of standard page sizes */
918     page_name = NULL;
919     for (i = 0; i < ARRAY_LENGTH (_cairo_page_standard_media); i++) {
920         if (_ps_page_dimension_equal (width, _cairo_page_standard_media[i].width) &&
921             _ps_page_dimension_equal (height, _cairo_page_standard_media[i].height))
922         {
923             page_name = _cairo_page_standard_media[i].name;
924             width = _cairo_page_standard_media[i].width;
925             height = _cairo_page_standard_media[i].height;
926             break;
927         }
928     }
929
930     page = malloc (sizeof (cairo_page_media_t));
931     if (unlikely (page == NULL)) {
932         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
933         return NULL;
934     }
935
936     if (page_name) {
937         page->name = strdup (page_name);
938     } else {
939         snprintf (buf, sizeof (buf), "%dx%dmm",
940                   (int) _cairo_lround (surface->width * 25.4/72),
941                   (int) _cairo_lround (surface->height * 25.4/72));
942         page->name = strdup (buf);
943     }
944
945     if (unlikely (page->name == NULL)) {
946         free (page);
947         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
948         return NULL;
949     }
950
951     page->width = width;
952     page->height = height;
953     cairo_list_add_tail (&page->link, &surface->document_media);
954
955     return page->name;
956 }
957
958 static cairo_surface_t *
959 _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
960                                               double                 width,
961                                               double                 height)
962 {
963     cairo_status_t status, status_ignored;
964     cairo_ps_surface_t *surface;
965
966     surface = malloc (sizeof (cairo_ps_surface_t));
967     if (unlikely (surface == NULL)) {
968         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
969         goto CLEANUP;
970     }
971
972     _cairo_surface_init (&surface->base,
973                          &cairo_ps_surface_backend,
974                          NULL, /* device */
975                          CAIRO_CONTENT_COLOR_ALPHA);
976
977     surface->final_stream = stream;
978
979     surface->tmpfile = tmpfile ();
980     if (surface->tmpfile == NULL) {
981         switch (errno) {
982         case ENOMEM:
983             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
984             break;
985         default:
986             status = _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR);
987             break;
988         }
989         goto CLEANUP_SURFACE;
990     }
991
992     surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile);
993     status = _cairo_output_stream_get_status (surface->stream);
994     if (unlikely (status))
995         goto CLEANUP_OUTPUT_STREAM;
996
997     surface->font_subsets = _cairo_scaled_font_subsets_create_simple ();
998     if (unlikely (surface->font_subsets == NULL)) {
999         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1000         goto CLEANUP_OUTPUT_STREAM;
1001     }
1002
1003     _cairo_scaled_font_subsets_enable_latin_subset (surface->font_subsets, TRUE);
1004     surface->has_creation_date = FALSE;
1005     surface->eps = FALSE;
1006     surface->ps_level = CAIRO_PS_LEVEL_3;
1007     surface->ps_level_used = CAIRO_PS_LEVEL_2;
1008     surface->width  = width;
1009     surface->height = height;
1010     cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, height);
1011     surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
1012     surface->force_fallbacks = FALSE;
1013     surface->content = CAIRO_CONTENT_COLOR_ALPHA;
1014     surface->use_string_datasource = FALSE;
1015     surface->current_pattern_is_solid_color = FALSE;
1016
1017     surface->page_bbox.x = 0;
1018     surface->page_bbox.y = 0;
1019     surface->page_bbox.width  = width;
1020     surface->page_bbox.height = height;
1021
1022     _cairo_surface_clipper_init (&surface->clipper,
1023                                  _cairo_ps_surface_clipper_intersect_clip_path);
1024
1025     _cairo_pdf_operators_init (&surface->pdf_operators,
1026                                surface->stream,
1027                                &surface->cairo_to_ps,
1028                                surface->font_subsets);
1029     surface->num_pages = 0;
1030
1031     cairo_list_init (&surface->document_media);
1032     _cairo_array_init (&surface->dsc_header_comments, sizeof (char *));
1033     _cairo_array_init (&surface->dsc_setup_comments, sizeof (char *));
1034     _cairo_array_init (&surface->dsc_page_setup_comments, sizeof (char *));
1035
1036     surface->dsc_comment_target = &surface->dsc_header_comments;
1037
1038     surface->paginated_surface = _cairo_paginated_surface_create (
1039                                            &surface->base,
1040                                            CAIRO_CONTENT_COLOR_ALPHA,
1041                                            &cairo_ps_surface_paginated_backend);
1042     status = surface->paginated_surface->status;
1043     if (status == CAIRO_STATUS_SUCCESS) {
1044         /* paginated keeps the only reference to surface now, drop ours */
1045         cairo_surface_destroy (&surface->base);
1046         return surface->paginated_surface;
1047     }
1048
1049     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
1050  CLEANUP_OUTPUT_STREAM:
1051     status_ignored = _cairo_output_stream_destroy (surface->stream);
1052     fclose (surface->tmpfile);
1053  CLEANUP_SURFACE:
1054     free (surface);
1055  CLEANUP:
1056     /* destroy stream on behalf of caller */
1057     status_ignored = _cairo_output_stream_destroy (stream);
1058
1059     return _cairo_surface_create_in_error (status);
1060 }
1061
1062 /**
1063  * cairo_ps_surface_create:
1064  * @filename: a filename for the PS output (must be writable), %NULL may be
1065  *            used to specify no output. This will generate a PS surface that
1066  *            may be queried and used as a source, without generating a
1067  *            temporary file.
1068  * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
1069  * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
1070  *
1071  * Creates a PostScript surface of the specified size in points to be
1072  * written to @filename. See cairo_ps_surface_create_for_stream() for
1073  * a more flexible mechanism for handling the PostScript output than
1074  * simply writing it to a named file.
1075  *
1076  * Note that the size of individual pages of the PostScript output can
1077  * vary. See cairo_ps_surface_set_size().
1078  *
1079  * Return value: a pointer to the newly created surface. The caller
1080  * owns the surface and should call cairo_surface_destroy() when done
1081  * with it.
1082  *
1083  * This function always returns a valid pointer, but it will return a
1084  * pointer to a "nil" surface if an error such as out of memory
1085  * occurs. You can use cairo_surface_status() to check for this.
1086  *
1087  * Since: 1.2
1088  **/
1089 cairo_surface_t *
1090 cairo_ps_surface_create (const char             *filename,
1091                          double                  width_in_points,
1092                          double                  height_in_points)
1093 {
1094     cairo_output_stream_t *stream;
1095
1096     stream = _cairo_output_stream_create_for_filename (filename);
1097     if (_cairo_output_stream_get_status (stream))
1098         return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream));
1099
1100     return _cairo_ps_surface_create_for_stream_internal (stream,
1101                                                          width_in_points,
1102                                                          height_in_points);
1103 }
1104
1105 /**
1106  * cairo_ps_surface_create_for_stream:
1107  * @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
1108  *              to indicate a no-op @write_func. With a no-op @write_func,
1109  *              the surface may be queried or used as a source without
1110  *              generating any temporary files.
1111  * @closure: the closure argument for @write_func
1112  * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
1113  * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
1114  *
1115  * Creates a PostScript surface of the specified size in points to be
1116  * written incrementally to the stream represented by @write_func and
1117  * @closure. See cairo_ps_surface_create() for a more convenient way
1118  * to simply direct the PostScript output to a named file.
1119  *
1120  * Note that the size of individual pages of the PostScript
1121  * output can vary. See cairo_ps_surface_set_size().
1122  *
1123  * Return value: a pointer to the newly created surface. The caller
1124  * owns the surface and should call cairo_surface_destroy() when done
1125  * with it.
1126  *
1127  * This function always returns a valid pointer, but it will return a
1128  * pointer to a "nil" surface if an error such as out of memory
1129  * occurs. You can use cairo_surface_status() to check for this.
1130  *
1131  * Since: 1.2
1132  **/
1133 cairo_surface_t *
1134 cairo_ps_surface_create_for_stream (cairo_write_func_t  write_func,
1135                                     void               *closure,
1136                                     double              width_in_points,
1137                                     double              height_in_points)
1138 {
1139     cairo_output_stream_t *stream;
1140
1141     stream = _cairo_output_stream_create (write_func, NULL, closure);
1142     if (_cairo_output_stream_get_status (stream))
1143         return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream));
1144
1145     return _cairo_ps_surface_create_for_stream_internal (stream,
1146                                                          width_in_points,
1147                                                          height_in_points);
1148 }
1149
1150 static cairo_bool_t
1151 _cairo_surface_is_ps (cairo_surface_t *surface)
1152 {
1153     return surface->backend == &cairo_ps_surface_backend;
1154 }
1155
1156 /* If the abstract_surface is a paginated surface, and that paginated
1157  * surface's target is a ps_surface, then set ps_surface to that
1158  * target. Otherwise return FALSE.
1159  */
1160 static cairo_bool_t
1161 _extract_ps_surface (cairo_surface_t     *surface,
1162                      cairo_bool_t         set_error_on_failure,
1163                      cairo_ps_surface_t **ps_surface)
1164 {
1165     cairo_surface_t *target;
1166
1167     if (surface->status)
1168         return FALSE;
1169     if (surface->finished) {
1170         if (set_error_on_failure)
1171             _cairo_surface_set_error (surface,
1172                                       _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1173         return FALSE;
1174     }
1175
1176     if (! _cairo_surface_is_paginated (surface)) {
1177         if (set_error_on_failure)
1178             _cairo_surface_set_error (surface,
1179                                       _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1180         return FALSE;
1181     }
1182
1183     target = _cairo_paginated_surface_get_target (surface);
1184     if (target->status) {
1185         if (set_error_on_failure)
1186             _cairo_surface_set_error (surface, target->status);
1187         return FALSE;
1188     }
1189     if (target->finished) {
1190         if (set_error_on_failure)
1191             _cairo_surface_set_error (surface,
1192                                       _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1193         return FALSE;
1194     }
1195
1196     if (! _cairo_surface_is_ps (target)) {
1197         if (set_error_on_failure)
1198             _cairo_surface_set_error (surface,
1199                                       _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1200         return FALSE;
1201     }
1202
1203     *ps_surface = (cairo_ps_surface_t *) target;
1204     return TRUE;
1205 }
1206
1207 /**
1208  * cairo_ps_surface_restrict_to_level:
1209  * @surface: a PostScript #cairo_surface_t
1210  * @level: PostScript level
1211  *
1212  * Restricts the generated PostSript file to @level. See
1213  * cairo_ps_get_levels() for a list of available level values that
1214  * can be used here.
1215  *
1216  * This function should only be called before any drawing operations
1217  * have been performed on the given surface. The simplest way to do
1218  * this is to call this function immediately after creating the
1219  * surface.
1220  *
1221  * Since: 1.6
1222  **/
1223 void
1224 cairo_ps_surface_restrict_to_level (cairo_surface_t  *surface,
1225                                     cairo_ps_level_t  level)
1226 {
1227     cairo_ps_surface_t *ps_surface = NULL;
1228
1229     if (! _extract_ps_surface (surface, TRUE, &ps_surface))
1230         return;
1231
1232     if (level < CAIRO_PS_LEVEL_LAST)
1233         ps_surface->ps_level = level;
1234 }
1235
1236 /**
1237  * cairo_ps_get_levels:
1238  * @levels: supported level list
1239  * @num_levels: list length
1240  *
1241  * Used to retrieve the list of supported levels. See
1242  * cairo_ps_surface_restrict_to_level().
1243  *
1244  * Since: 1.6
1245  **/
1246 void
1247 cairo_ps_get_levels (cairo_ps_level_t const     **levels,
1248                      int                         *num_levels)
1249 {
1250     if (levels != NULL)
1251         *levels = _cairo_ps_levels;
1252
1253     if (num_levels != NULL)
1254         *num_levels = CAIRO_PS_LEVEL_LAST;
1255 }
1256
1257 /**
1258  * cairo_ps_level_to_string:
1259  * @level: a level id
1260  *
1261  * Get the string representation of the given @level id. This function
1262  * will return %NULL if @level id isn't valid. See cairo_ps_get_levels()
1263  * for a way to get the list of valid level ids.
1264  *
1265  * Return value: the string associated to given level.
1266  *
1267  * Since: 1.6
1268  **/
1269 const char *
1270 cairo_ps_level_to_string (cairo_ps_level_t level)
1271 {
1272     if (level >= CAIRO_PS_LEVEL_LAST)
1273         return NULL;
1274
1275     return _cairo_ps_level_strings[level];
1276 }
1277
1278 /**
1279  * cairo_ps_surface_set_eps:
1280  * @surface: a PostScript #cairo_surface_t
1281  * @eps: %TRUE to output EPS format PostScript
1282  *
1283  * If @eps is %TRUE, the PostScript surface will output Encapsulated
1284  * PostScript.
1285  *
1286  * This function should only be called before any drawing operations
1287  * have been performed on the current page. The simplest way to do
1288  * this is to call this function immediately after creating the
1289  * surface. An Encapsulated PostScript file should never contain more
1290  * than one page.
1291  *
1292  * Since: 1.6
1293  **/
1294 void
1295 cairo_ps_surface_set_eps (cairo_surface_t       *surface,
1296                           cairo_bool_t           eps)
1297 {
1298     cairo_ps_surface_t *ps_surface = NULL;
1299
1300     if (! _extract_ps_surface (surface, TRUE, &ps_surface))
1301         return;
1302
1303     ps_surface->eps = eps;
1304 }
1305
1306 /**
1307  * cairo_ps_surface_get_eps:
1308  * @surface: a PostScript #cairo_surface_t
1309  *
1310  * Check whether the PostScript surface will output Encapsulated PostScript.
1311  *
1312  * Return value: %TRUE if the surface will output Encapsulated PostScript.
1313  *
1314  * Since: 1.6
1315  **/
1316 cairo_public cairo_bool_t
1317 cairo_ps_surface_get_eps (cairo_surface_t       *surface)
1318 {
1319     cairo_ps_surface_t *ps_surface = NULL;
1320
1321     if (! _extract_ps_surface (surface, FALSE, &ps_surface))
1322         return FALSE;
1323
1324     return ps_surface->eps;
1325 }
1326
1327 /**
1328  * cairo_ps_surface_set_size:
1329  * @surface: a PostScript #cairo_surface_t
1330  * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
1331  * @height_in_points: new surface height, in points (1 point == 1/72.0 inch)
1332  *
1333  * Changes the size of a PostScript surface for the current (and
1334  * subsequent) pages.
1335  *
1336  * This function should only be called before any drawing operations
1337  * have been performed on the current page. The simplest way to do
1338  * this is to call this function immediately after creating the
1339  * surface or immediately after completing a page with either
1340  * cairo_show_page() or cairo_copy_page().
1341  *
1342  * Since: 1.2
1343  **/
1344 void
1345 cairo_ps_surface_set_size (cairo_surface_t      *surface,
1346                            double                width_in_points,
1347                            double                height_in_points)
1348 {
1349     cairo_ps_surface_t *ps_surface = NULL;
1350     cairo_status_t status;
1351
1352     if (! _extract_ps_surface (surface, TRUE, &ps_surface))
1353         return;
1354
1355     ps_surface->width = width_in_points;
1356     ps_surface->height = height_in_points;
1357     cairo_matrix_init (&ps_surface->cairo_to_ps, 1, 0, 0, -1, 0, height_in_points);
1358     _cairo_pdf_operators_set_cairo_to_pdf_matrix (&ps_surface->pdf_operators,
1359                                                   &ps_surface->cairo_to_ps);
1360     status = _cairo_paginated_surface_set_size (ps_surface->paginated_surface,
1361                                                 width_in_points,
1362                                                 height_in_points);
1363     if (status)
1364         status = _cairo_surface_set_error (surface, status);
1365 }
1366
1367 /**
1368  * cairo_ps_surface_dsc_comment:
1369  * @surface: a PostScript #cairo_surface_t
1370  * @comment: a comment string to be emitted into the PostScript output
1371  *
1372  * Emit a comment into the PostScript output for the given surface.
1373  *
1374  * The comment is expected to conform to the PostScript Language
1375  * Document Structuring Conventions (DSC). Please see that manual for
1376  * details on the available comments and their meanings. In
1377  * particular, the \%\%IncludeFeature comment allows a
1378  * device-independent means of controlling printer device features. So
1379  * the PostScript Printer Description Files Specification will also be
1380  * a useful reference.
1381  *
1382  * The comment string must begin with a percent character (\%) and the
1383  * total length of the string (including any initial percent
1384  * characters) must not exceed 255 characters. Violating either of
1385  * these conditions will place @surface into an error state. But
1386  * beyond these two conditions, this function will not enforce
1387  * conformance of the comment with any particular specification.
1388  *
1389  * The comment string should not have a trailing newline.
1390  *
1391  * The DSC specifies different sections in which particular comments
1392  * can appear. This function provides for comments to be emitted
1393  * within three sections: the header, the Setup section, and the
1394  * PageSetup section.  Comments appearing in the first two sections
1395  * apply to the entire document while comments in the BeginPageSetup
1396  * section apply only to a single page.
1397  *
1398  * For comments to appear in the header section, this function should
1399  * be called after the surface is created, but before a call to
1400  * cairo_ps_surface_dsc_begin_setup().
1401  *
1402  * For comments to appear in the Setup section, this function should
1403  * be called after a call to cairo_ps_surface_dsc_begin_setup() but
1404  * before a call to cairo_ps_surface_dsc_begin_page_setup().
1405  *
1406  * For comments to appear in the PageSetup section, this function
1407  * should be called after a call to
1408  * cairo_ps_surface_dsc_begin_page_setup().
1409  *
1410  * Note that it is only necessary to call
1411  * cairo_ps_surface_dsc_begin_page_setup() for the first page of any
1412  * surface. After a call to cairo_show_page() or cairo_copy_page()
1413  * comments are unambiguously directed to the PageSetup section of the
1414  * current page. But it doesn't hurt to call this function at the
1415  * beginning of every page as that consistency may make the calling
1416  * code simpler.
1417  *
1418  * As a final note, cairo automatically generates several comments on
1419  * its own. As such, applications must not manually generate any of
1420  * the following comments:
1421  *
1422  * Header section: \%!PS-Adobe-3.0, \%\%Creator, \%\%CreationDate, \%\%Pages,
1423  * \%\%BoundingBox, \%\%DocumentData, \%\%LanguageLevel, \%\%EndComments.
1424  *
1425  * Setup section: \%\%BeginSetup, \%\%EndSetup
1426  *
1427  * PageSetup section: \%\%BeginPageSetup, \%\%PageBoundingBox, \%\%EndPageSetup.
1428  *
1429  * Other sections: \%\%BeginProlog, \%\%EndProlog, \%\%Page, \%\%Trailer, \%\%EOF
1430  *
1431  * Here is an example sequence showing how this function might be used:
1432  *
1433  * <informalexample><programlisting>
1434  * cairo_surface_t *surface = cairo_ps_surface_create (filename, width, height);
1435  * ...
1436  * cairo_ps_surface_dsc_comment (surface, "%%Title: My excellent document");
1437  * cairo_ps_surface_dsc_comment (surface, "%%Copyright: Copyright (C) 2006 Cairo Lover")
1438  * ...
1439  * cairo_ps_surface_dsc_begin_setup (surface);
1440  * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *MediaColor White");
1441  * ...
1442  * cairo_ps_surface_dsc_begin_page_setup (surface);
1443  * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *PageSize A3");
1444  * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *InputSlot LargeCapacity");
1445  * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *MediaType Glossy");
1446  * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *MediaColor Blue");
1447  * ... draw to first page here ..
1448  * cairo_show_page (cr);
1449  * ...
1450  * cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *PageSize A5");
1451  * ...
1452  * </programlisting></informalexample>
1453  *
1454  * Since: 1.2
1455  **/
1456 void
1457 cairo_ps_surface_dsc_comment (cairo_surface_t   *surface,
1458                               const char        *comment)
1459 {
1460     cairo_ps_surface_t *ps_surface = NULL;
1461     cairo_status_t status;
1462     char *comment_copy;
1463
1464     if (! _extract_ps_surface (surface, TRUE, &ps_surface))
1465         return;
1466
1467     /* A couple of sanity checks on the comment value. */
1468     if (comment == NULL) {
1469         status = _cairo_surface_set_error (surface, CAIRO_STATUS_NULL_POINTER);
1470         return;
1471     }
1472
1473     if (comment[0] != '%' || strlen (comment) > 255) {
1474         status = _cairo_surface_set_error (surface, CAIRO_STATUS_INVALID_DSC_COMMENT);
1475         return;
1476     }
1477
1478     /* Then, copy the comment and store it in the appropriate array. */
1479     comment_copy = strdup (comment);
1480     if (unlikely (comment_copy == NULL)) {
1481         status = _cairo_surface_set_error (surface, CAIRO_STATUS_NO_MEMORY);
1482         return;
1483     }
1484
1485     status = _cairo_array_append (ps_surface->dsc_comment_target, &comment_copy);
1486     if (unlikely (status)) {
1487         free (comment_copy);
1488         status = _cairo_surface_set_error (surface, status);
1489         return;
1490     }
1491 }
1492
1493 /**
1494  * cairo_ps_surface_dsc_begin_setup:
1495  * @surface: a PostScript #cairo_surface_t
1496  *
1497  * This function indicates that subsequent calls to
1498  * cairo_ps_surface_dsc_comment() should direct comments to the Setup
1499  * section of the PostScript output.
1500  *
1501  * This function should be called at most once per surface, and must
1502  * be called before any call to cairo_ps_surface_dsc_begin_page_setup()
1503  * and before any drawing is performed to the surface.
1504  *
1505  * See cairo_ps_surface_dsc_comment() for more details.
1506  *
1507  * Since: 1.2
1508  **/
1509 void
1510 cairo_ps_surface_dsc_begin_setup (cairo_surface_t *surface)
1511 {
1512     cairo_ps_surface_t *ps_surface = NULL;
1513
1514     if (! _extract_ps_surface (surface, TRUE, &ps_surface))
1515         return;
1516
1517     if (ps_surface->dsc_comment_target == &ps_surface->dsc_header_comments)
1518         ps_surface->dsc_comment_target = &ps_surface->dsc_setup_comments;
1519 }
1520
1521 /**
1522  * cairo_ps_surface_dsc_begin_page_setup:
1523  * @surface: a PostScript #cairo_surface_t
1524  *
1525  * This function indicates that subsequent calls to
1526  * cairo_ps_surface_dsc_comment() should direct comments to the
1527  * PageSetup section of the PostScript output.
1528  *
1529  * This function call is only needed for the first page of a
1530  * surface. It should be called after any call to
1531  * cairo_ps_surface_dsc_begin_setup() and before any drawing is
1532  * performed to the surface.
1533  *
1534  * See cairo_ps_surface_dsc_comment() for more details.
1535  *
1536  * Since: 1.2
1537  **/
1538 void
1539 cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface)
1540 {
1541     cairo_ps_surface_t *ps_surface = NULL;
1542
1543     if (! _extract_ps_surface (surface, TRUE, &ps_surface))
1544         return;
1545
1546     if (ps_surface->dsc_comment_target == &ps_surface->dsc_header_comments ||
1547         ps_surface->dsc_comment_target == &ps_surface->dsc_setup_comments)
1548     {
1549         ps_surface->dsc_comment_target = &ps_surface->dsc_page_setup_comments;
1550     }
1551 }
1552
1553 static cairo_status_t
1554 _cairo_ps_surface_finish (void *abstract_surface)
1555 {
1556     cairo_status_t status, status2;
1557     cairo_ps_surface_t *surface = abstract_surface;
1558     int i, num_comments;
1559     char **comments;
1560
1561     status = surface->base.status;
1562     if (unlikely (status))
1563         goto CLEANUP;
1564
1565     _cairo_ps_surface_emit_header (surface);
1566
1567     status = _cairo_ps_surface_emit_font_subsets (surface);
1568     if (unlikely (status))
1569         goto CLEANUP;
1570
1571     status = _cairo_ps_surface_emit_body (surface);
1572     if (unlikely (status))
1573         goto CLEANUP;
1574
1575     _cairo_ps_surface_emit_footer (surface);
1576
1577 CLEANUP:
1578     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
1579
1580     status2 = _cairo_output_stream_destroy (surface->stream);
1581     if (status == CAIRO_STATUS_SUCCESS)
1582         status = status2;
1583
1584     fclose (surface->tmpfile);
1585
1586     status2 = _cairo_output_stream_destroy (surface->final_stream);
1587     if (status == CAIRO_STATUS_SUCCESS)
1588         status = status2;
1589
1590     while (! cairo_list_is_empty (&surface->document_media)) {
1591         cairo_page_media_t *page;
1592
1593         page = cairo_list_first_entry (&surface->document_media,
1594                                        cairo_page_media_t,
1595                                        link);
1596         cairo_list_del (&page->link);
1597         free (page->name);
1598         free (page);
1599     }
1600
1601     num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
1602     comments = _cairo_array_index (&surface->dsc_header_comments, 0);
1603     if (comments == NULL)
1604         return CAIRO_STATUS_NULL_POINTER;
1605
1606     for (i = 0; i < num_comments; i++)
1607         free (comments[i]);
1608     _cairo_array_fini (&surface->dsc_header_comments);
1609
1610     num_comments = _cairo_array_num_elements (&surface->dsc_setup_comments);
1611     comments = _cairo_array_index (&surface->dsc_setup_comments, 0);
1612     if (comments == NULL)
1613         return CAIRO_STATUS_NULL_POINTER;
1614
1615     for (i = 0; i < num_comments; i++)
1616         free (comments[i]);
1617     _cairo_array_fini (&surface->dsc_setup_comments);
1618
1619     num_comments = _cairo_array_num_elements (&surface->dsc_page_setup_comments);
1620     comments = _cairo_array_index (&surface->dsc_page_setup_comments, 0);
1621     if (comments == NULL)
1622         return CAIRO_STATUS_NULL_POINTER;
1623
1624     for (i = 0; i < num_comments; i++)
1625         free (comments[i]);
1626     _cairo_array_fini (&surface->dsc_page_setup_comments);
1627
1628     _cairo_surface_clipper_reset (&surface->clipper);
1629
1630     return status;
1631 }
1632
1633 static cairo_int_status_t
1634 _cairo_ps_surface_start_page (void *abstract_surface)
1635 {
1636     cairo_ps_surface_t *surface = abstract_surface;
1637
1638     /* Increment before print so page numbers start at 1. */
1639     surface->num_pages++;
1640
1641     return CAIRO_STATUS_SUCCESS;
1642 }
1643
1644 static cairo_int_status_t
1645 _cairo_ps_surface_show_page (void *abstract_surface)
1646 {
1647     cairo_ps_surface_t *surface = abstract_surface;
1648     cairo_int_status_t status;
1649
1650     if (surface->clipper.clip != NULL)
1651         _cairo_surface_clipper_reset (&surface->clipper);
1652
1653     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
1654     if (unlikely (status))
1655         return status;
1656
1657     _cairo_output_stream_printf (surface->stream,
1658                                  "Q Q\n"
1659                                  "showpage\n");
1660
1661     return CAIRO_STATUS_SUCCESS;
1662 }
1663
1664 static cairo_bool_t
1665 color_is_gray (double red, double green, double blue)
1666 {
1667     const double epsilon = 0.00001;
1668
1669     return (fabs (red - green) < epsilon &&
1670             fabs (red - blue) < epsilon);
1671 }
1672
1673 /**
1674  * _cairo_ps_surface_acquire_source_surface_from_pattern:
1675  * @surface: the ps surface
1676  * @pattern: A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source
1677  * @extents: extents of the operation that is using this source
1678  * @width: returns width of surface
1679  * @height: returns height of surface
1680  * @x_offset: returns x offset of surface
1681  * @y_offset: returns y offset of surface
1682  * @surface: returns surface of type image surface or recording surface
1683  * @image_extra: returns image extra for image type surface
1684  *
1685  * Acquire source surface or raster source pattern.
1686  **/
1687 static cairo_status_t
1688 _cairo_ps_surface_acquire_source_surface_from_pattern (cairo_ps_surface_t           *surface,
1689                                                        const cairo_pattern_t        *pattern,
1690                                                        const cairo_rectangle_int_t  *extents,
1691                                                        int                          *width,
1692                                                        int                          *height,
1693                                                        double                       *x_offset,
1694                                                        double                       *y_offset,
1695                                                        cairo_surface_t             **source_surface,
1696                                                        void                        **image_extra)
1697 {
1698     cairo_status_t          status;
1699     cairo_image_surface_t  *image;
1700
1701     *x_offset = *y_offset = 0;
1702     switch (pattern->type) {
1703     case CAIRO_PATTERN_TYPE_SURFACE: {
1704         cairo_surface_t *surf = ((cairo_surface_pattern_t *) pattern)->surface;
1705
1706         if (surf->type == CAIRO_SURFACE_TYPE_RECORDING) {
1707             if (surf->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1708                 cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) surf;
1709
1710                 *width  = sub->extents.width;
1711                 *height = sub->extents.height;
1712             } else {
1713                 cairo_surface_t *free_me = NULL;
1714                 cairo_recording_surface_t *recording_surface;
1715                 cairo_box_t bbox;
1716                 cairo_rectangle_int_t extents;
1717
1718                 recording_surface = (cairo_recording_surface_t *) surf;
1719                 if (_cairo_surface_is_snapshot (&recording_surface->base)) {
1720                     free_me = _cairo_surface_snapshot_get_target (&recording_surface->base);
1721                     recording_surface = (cairo_recording_surface_t *) free_me;
1722                 }
1723
1724                 status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL);
1725                 cairo_surface_destroy (free_me);
1726                 if (unlikely (status))
1727                     return status;
1728
1729                 _cairo_box_round_to_rectangle (&bbox, &extents);
1730                 *width  = extents.width;
1731                 *height = extents.height;
1732             }
1733             *source_surface = surf;
1734
1735             return CAIRO_STATUS_SUCCESS;
1736         } else {
1737             status =  _cairo_surface_acquire_source_image (surf, &image, image_extra);
1738             if (unlikely (status))
1739                 return status;
1740         }
1741     } break;
1742
1743     case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
1744         cairo_surface_t *surf;
1745         cairo_box_t box;
1746         cairo_rectangle_int_t rect;
1747
1748         /* get the operation extents in pattern space */
1749         _cairo_box_from_rectangle (&box, extents);
1750         _cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &box, NULL);
1751         _cairo_box_round_to_rectangle (&box, &rect);
1752         surf = _cairo_raster_source_pattern_acquire (pattern, &surface->base, &rect);
1753         if (!surf)
1754             return CAIRO_INT_STATUS_UNSUPPORTED;
1755         assert (_cairo_surface_is_image (surf));
1756         image = (cairo_image_surface_t *) surf;
1757     } break;
1758
1759     case CAIRO_PATTERN_TYPE_SOLID:
1760     case CAIRO_PATTERN_TYPE_LINEAR:
1761     case CAIRO_PATTERN_TYPE_RADIAL:
1762     case CAIRO_PATTERN_TYPE_MESH:
1763     default:
1764         ASSERT_NOT_REACHED;
1765         break;
1766     }
1767
1768     *width = image->width;
1769     *height = image->height;
1770     *source_surface = &image->base;
1771     return CAIRO_STATUS_SUCCESS;
1772 }
1773
1774 static void
1775 _cairo_ps_surface_release_source_surface_from_pattern (cairo_ps_surface_t           *surface,
1776                                                        const cairo_pattern_t        *pattern,
1777                                                        cairo_surface_t              *source,
1778                                                        void                         *image_extra)
1779 {
1780     switch (pattern->type) {
1781     case CAIRO_PATTERN_TYPE_SURFACE: {
1782         cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
1783         if (surf_pat->surface->type != CAIRO_SURFACE_TYPE_RECORDING) {
1784             cairo_image_surface_t *image  = (cairo_image_surface_t *) source;
1785             _cairo_surface_release_source_image (surf_pat->surface, image, image_extra);
1786         }
1787     } break;
1788
1789     case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1790         _cairo_raster_source_pattern_release (pattern, source);
1791         break;
1792
1793     case CAIRO_PATTERN_TYPE_SOLID:
1794     case CAIRO_PATTERN_TYPE_LINEAR:
1795     case CAIRO_PATTERN_TYPE_RADIAL:
1796     case CAIRO_PATTERN_TYPE_MESH:
1797     default:
1798
1799         ASSERT_NOT_REACHED;
1800         break;
1801     }
1802 }
1803
1804 /**
1805  * _cairo_ps_surface_create_padded_image_from_image:
1806  * @surface: the ps surface
1807  * @source: The source image
1808  * @extents: extents of the operation that is using this source
1809  * @width: returns width of padded image
1810  * @height: returns height of padded image
1811  * @x_offset: returns x offset of padded image
1812  * @y_offset: returns y offset of padded image
1813  * @image: returns the padded image or NULL if padding not required to fill @extents
1814  *
1815  * Creates a padded image if the source image does not fill the extents.
1816  **/
1817 static cairo_status_t
1818 _cairo_ps_surface_create_padded_image_from_image (cairo_ps_surface_t           *surface,
1819                                                   cairo_image_surface_t        *source,
1820                                                   const cairo_matrix_t         *source_matrix,
1821                                                   const cairo_rectangle_int_t  *extents,
1822                                                   int                          *width,
1823                                                   int                          *height,
1824                                                   double                       *x_offset,
1825                                                   double                       *y_offset,
1826                                                   cairo_image_surface_t       **image)
1827 {
1828     cairo_box_t box;
1829     cairo_rectangle_int_t rect;
1830     cairo_surface_t        *pad_image;
1831     cairo_surface_pattern_t pad_pattern;
1832     int w, h;
1833     cairo_int_status_t      status;
1834
1835     /* get the operation extents in pattern space */
1836     _cairo_box_from_rectangle (&box, extents);
1837     _cairo_matrix_transform_bounding_box_fixed (source_matrix, &box, NULL);
1838     _cairo_box_round_to_rectangle (&box, &rect);
1839
1840     /* Check if image needs padding to fill extents. */
1841     w = source->width;
1842     h = source->height;
1843     if (_cairo_fixed_integer_ceil(box.p1.x) < 0 ||
1844         _cairo_fixed_integer_ceil(box.p1.y) < 0 ||
1845         _cairo_fixed_integer_floor(box.p2.y) > w ||
1846         _cairo_fixed_integer_floor(box.p2.y) > h)
1847     {
1848         pad_image =
1849             _cairo_image_surface_create_with_pixman_format (NULL,
1850                                                             source->pixman_format,
1851                                                             rect.width, rect.height,
1852                                                             0);
1853         if (pad_image->status) {
1854             status = pad_image->status;
1855             cairo_surface_destroy (pad_image);
1856             status;
1857         }
1858
1859         _cairo_pattern_init_for_surface (&pad_pattern, &source->base);
1860         cairo_matrix_init_translate (&pad_pattern.base.matrix, rect.x, rect.y);
1861         pad_pattern.base.extend = CAIRO_EXTEND_PAD;
1862         status = _cairo_surface_paint (pad_image,
1863                                        CAIRO_OPERATOR_SOURCE,
1864                                        &pad_pattern.base,
1865                                        NULL);
1866         _cairo_pattern_fini (&pad_pattern.base);
1867         *image = (cairo_image_surface_t *) pad_image;
1868         *width = rect.width;
1869         *height = rect.height;
1870         *x_offset = rect.x;
1871         *y_offset = rect.y;
1872     } else {
1873         *image = NULL;
1874         status = CAIRO_STATUS_SUCCESS;
1875     }
1876
1877     return status;
1878 }
1879
1880 static cairo_int_status_t
1881 _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t            *surface,
1882                                                         const cairo_pattern_t         *pattern,
1883                                                         const cairo_rectangle_int_t   *extents)
1884 {
1885     int width, height;
1886     double x_offset, y_offset;
1887     cairo_surface_t *source;
1888     cairo_image_surface_t *image;
1889     void *image_extra;
1890     cairo_int_status_t      status;
1891     cairo_image_transparency_t transparency;
1892
1893     status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface,
1894                                                                     pattern,
1895                                                                     extents,
1896                                                                     &width,
1897                                                                     &height,
1898                                                                     &x_offset,
1899                                                                     &y_offset,
1900                                                                     &source,
1901                                                                     &image_extra);
1902     if (unlikely (status))
1903         return status;
1904
1905     image = (cairo_image_surface_t *) source;
1906     if (image->base.status)
1907         return image->base.status;
1908
1909     transparency = _cairo_image_analyze_transparency (image);
1910     switch (transparency) {
1911     case CAIRO_IMAGE_IS_OPAQUE:
1912         status = CAIRO_STATUS_SUCCESS;
1913         break;
1914
1915     case CAIRO_IMAGE_HAS_BILEVEL_ALPHA:
1916         if (surface->ps_level == CAIRO_PS_LEVEL_2) {
1917             status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
1918         } else {
1919             surface->ps_level_used = CAIRO_PS_LEVEL_3;
1920             status = CAIRO_STATUS_SUCCESS;
1921         }
1922         break;
1923
1924     case CAIRO_IMAGE_HAS_ALPHA:
1925         status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
1926         break;
1927
1928     case CAIRO_IMAGE_UNKNOWN:
1929         ASSERT_NOT_REACHED;
1930     }
1931
1932     _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra);
1933
1934     return status;
1935 }
1936
1937 static cairo_bool_t
1938 surface_pattern_supported (const cairo_surface_pattern_t *pattern)
1939 {
1940     if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
1941         return TRUE;
1942
1943     if (pattern->surface->backend->acquire_source_image == NULL)
1944         return FALSE;
1945
1946     /* Does an ALPHA-only source surface even make sense? Maybe, but I
1947      * don't think it's worth the extra code to support it. */
1948
1949 /* XXX: Need to write this function here...
1950     content = pattern->surface->content;
1951     if (content == CAIRO_CONTENT_ALPHA)
1952         return FALSE;
1953 */
1954
1955     return TRUE;
1956 }
1957
1958 static cairo_bool_t
1959 _gradient_pattern_supported (cairo_ps_surface_t    *surface,
1960                              const cairo_pattern_t *pattern)
1961 {
1962     double min_alpha, max_alpha;
1963
1964     if (surface->ps_level == CAIRO_PS_LEVEL_2)
1965         return FALSE;
1966
1967     /* Alpha gradients are only supported (by flattening the alpha)
1968      * if there is no variation in the alpha across the gradient. */
1969     _cairo_pattern_alpha_range (pattern, &min_alpha, &max_alpha);
1970     if (min_alpha != max_alpha)
1971         return FALSE;
1972
1973     surface->ps_level_used = CAIRO_PS_LEVEL_3;
1974
1975     return TRUE;
1976 }
1977
1978 static cairo_bool_t
1979 pattern_supported (cairo_ps_surface_t *surface, const cairo_pattern_t *pattern)
1980 {
1981     switch (pattern->type) {
1982     case CAIRO_PATTERN_TYPE_SOLID:
1983         return TRUE;
1984
1985     case CAIRO_PATTERN_TYPE_LINEAR:
1986     case CAIRO_PATTERN_TYPE_RADIAL:
1987     case CAIRO_PATTERN_TYPE_MESH:
1988         return _gradient_pattern_supported (surface, pattern);
1989
1990     case CAIRO_PATTERN_TYPE_SURFACE:
1991         return surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
1992
1993     case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1994         return TRUE;
1995
1996     default:
1997         ASSERT_NOT_REACHED;
1998         return FALSE;
1999     }
2000 }
2001
2002 static cairo_bool_t
2003 mask_supported (cairo_ps_surface_t *surface,
2004                 const cairo_pattern_t *mask,
2005                 const cairo_rectangle_int_t *extents)
2006 {
2007     if (surface->ps_level == CAIRO_PS_LEVEL_2)
2008         return FALSE;
2009
2010     if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
2011         cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask;
2012         if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE) {
2013             /* check if mask if opaque or bilevel alpha */
2014             if (_cairo_ps_surface_analyze_surface_pattern_transparency (surface, mask, extents) == CAIRO_INT_STATUS_SUCCESS) {
2015                 surface->ps_level_used = CAIRO_PS_LEVEL_3;
2016                 return TRUE;
2017             }
2018         }
2019     }
2020
2021     return FALSE;
2022 }
2023
2024 static cairo_int_status_t
2025 _cairo_ps_surface_analyze_operation (cairo_ps_surface_t    *surface,
2026                                      cairo_operator_t       op,
2027                                      const cairo_pattern_t       *pattern,
2028                                      const cairo_pattern_t       *mask,
2029                                      const cairo_rectangle_int_t *extents)
2030 {
2031     double min_alpha;
2032
2033     if (surface->force_fallbacks &&
2034         surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
2035     {
2036         return CAIRO_INT_STATUS_UNSUPPORTED;
2037     }
2038
2039     if (! pattern_supported (surface, pattern))
2040         return CAIRO_INT_STATUS_UNSUPPORTED;
2041
2042     if (! (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER))
2043         return CAIRO_INT_STATUS_UNSUPPORTED;
2044
2045     /* Mask is only supported when the mask is an image with opaque or bilevel alpha. */
2046     if (mask && !mask_supported (surface, mask, extents))
2047         return CAIRO_INT_STATUS_UNSUPPORTED;
2048
2049     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
2050         cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
2051
2052         if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
2053             if (pattern->extend == CAIRO_EXTEND_PAD) {
2054                 cairo_box_t box;
2055                 cairo_rectangle_int_t rect;
2056                 cairo_rectangle_int_t rec_extents;
2057
2058                 /* get the operation extents in pattern space */
2059                 _cairo_box_from_rectangle (&box, extents);
2060                 _cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &box, NULL);
2061                 _cairo_box_round_to_rectangle (&box, &rect);
2062
2063                 /* Check if surface needs padding to fill extents */
2064                 if (_cairo_surface_get_extents (surface_pattern->surface, &rec_extents)) {
2065                     if (_cairo_fixed_integer_ceil(box.p1.x) < rec_extents.x ||
2066                         _cairo_fixed_integer_ceil(box.p1.y) < rec_extents.y ||
2067                         _cairo_fixed_integer_floor(box.p2.y) > rec_extents.x + rec_extents.width ||
2068                         _cairo_fixed_integer_floor(box.p2.y) > rec_extents.y + rec_extents.height)
2069                     {
2070                         return CAIRO_INT_STATUS_UNSUPPORTED;
2071                     }
2072                 }
2073             }
2074             return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN;
2075         }
2076     }
2077
2078     if (op == CAIRO_OPERATOR_SOURCE) {
2079         if (mask)
2080             return CAIRO_INT_STATUS_UNSUPPORTED;
2081         else
2082             return CAIRO_STATUS_SUCCESS;
2083     }
2084
2085     /* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If
2086      * the pattern contains transparency, we return
2087      * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis
2088      * surface. If the analysis surface determines that there is
2089      * anything drawn under this operation, a fallback image will be
2090      * used. Otherwise the operation will be replayed during the
2091      * render stage and we blend the transparency into the white
2092      * background to convert the pattern to opaque.
2093      */
2094     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE || pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
2095         return _cairo_ps_surface_analyze_surface_pattern_transparency (surface, pattern, extents);
2096
2097     /* Patterns whose drawn part is opaque are directly supported;
2098        those whose drawn part is partially transparent can be
2099        supported by flattening the alpha. */
2100     _cairo_pattern_alpha_range (pattern, &min_alpha, NULL);
2101     if (CAIRO_ALPHA_IS_OPAQUE (min_alpha))
2102         return CAIRO_STATUS_SUCCESS;
2103
2104     return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
2105 }
2106
2107 static cairo_bool_t
2108 _cairo_ps_surface_operation_supported (cairo_ps_surface_t    *surface,
2109                                        cairo_operator_t       op,
2110                                        const cairo_pattern_t       *pattern,
2111                                        const cairo_pattern_t       *mask,
2112                                        const cairo_rectangle_int_t *extents)
2113 {
2114     return _cairo_ps_surface_analyze_operation (surface, op, pattern, mask, extents) != CAIRO_INT_STATUS_UNSUPPORTED;
2115 }
2116
2117 /* The "standard" implementation limit for PostScript string sizes is
2118  * 65535 characters (see PostScript Language Reference, Appendix
2119  * B). We go one short of that because we sometimes need two
2120  * characters in a string to represent a single ASCII85 byte, (for the
2121  * escape sequences "\\", "\(", and "\)") and we must not split these
2122  * across two strings. So we'd be in trouble if we went right to the
2123  * limit and one of these escape sequences just happened to land at
2124  * the end.
2125  */
2126 #define STRING_ARRAY_MAX_STRING_SIZE (65535-1)
2127 #define STRING_ARRAY_MAX_COLUMN      72
2128
2129 typedef struct _string_array_stream {
2130     cairo_output_stream_t base;
2131     cairo_output_stream_t *output;
2132     int column;
2133     int string_size;
2134     cairo_bool_t use_strings;
2135 } string_array_stream_t;
2136
2137 static cairo_status_t
2138 _string_array_stream_write (cairo_output_stream_t *base,
2139                             const unsigned char   *data,
2140                             unsigned int           length)
2141 {
2142     string_array_stream_t *stream = (string_array_stream_t *) base;
2143     unsigned char c;
2144     const unsigned char backslash = '\\';
2145
2146     if (length == 0)
2147         return CAIRO_STATUS_SUCCESS;
2148
2149     while (length--) {
2150         if (stream->string_size == 0 && stream->use_strings) {
2151             _cairo_output_stream_printf (stream->output, "(");
2152             stream->column++;
2153         }
2154
2155         c = *data++;
2156         if (stream->use_strings) {
2157             switch (c) {
2158             case '\\':
2159             case '(':
2160             case ')':
2161                 _cairo_output_stream_write (stream->output, &backslash, 1);
2162                 stream->column++;
2163                 stream->string_size++;
2164                 break;
2165             }
2166         }
2167         /* Have to be careful to never split the final ~> sequence. */
2168         if (c == '~') {
2169             _cairo_output_stream_write (stream->output, &c, 1);
2170             stream->column++;
2171             stream->string_size++;
2172
2173             if (length-- == 0)
2174                 break;
2175
2176             c = *data++;
2177         }
2178         _cairo_output_stream_write (stream->output, &c, 1);
2179         stream->column++;
2180         stream->string_size++;
2181
2182         if (stream->use_strings &&
2183             stream->string_size >= STRING_ARRAY_MAX_STRING_SIZE)
2184         {
2185             _cairo_output_stream_printf (stream->output, ")\n");
2186             stream->string_size = 0;
2187             stream->column = 0;
2188         }
2189         if (stream->column >= STRING_ARRAY_MAX_COLUMN) {
2190             _cairo_output_stream_printf (stream->output, "\n ");
2191             stream->string_size += 2;
2192             stream->column = 1;
2193         }
2194     }
2195
2196     return _cairo_output_stream_get_status (stream->output);
2197 }
2198
2199 static cairo_status_t
2200 _string_array_stream_close (cairo_output_stream_t *base)
2201 {
2202     cairo_status_t status;
2203     string_array_stream_t *stream = (string_array_stream_t *) base;
2204
2205     if (stream->use_strings)
2206         _cairo_output_stream_printf (stream->output, ")\n");
2207
2208     status = _cairo_output_stream_get_status (stream->output);
2209
2210     return status;
2211 }
2212
2213 /* A string_array_stream wraps an existing output stream. It takes the
2214  * data provided to it and output one or more consecutive string
2215  * objects, each within the standard PostScript implementation limit
2216  * of 65k characters.
2217  *
2218  * The strings are each separated by a space character for easy
2219  * inclusion within an array object, (but the array delimiters are not
2220  * added by the string_array_stream).
2221  *
2222  * The string array stream is also careful to wrap the output within
2223  * STRING_ARRAY_MAX_COLUMN columns (+/- 1). The stream also adds
2224  * necessary escaping for special characters within a string,
2225  * (specifically '\', '(', and ')').
2226  */
2227 static cairo_output_stream_t *
2228 _string_array_stream_create (cairo_output_stream_t *output)
2229 {
2230     string_array_stream_t *stream;
2231
2232     stream = malloc (sizeof (string_array_stream_t));
2233     if (unlikely (stream == NULL)) {
2234         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2235         return (cairo_output_stream_t *) &_cairo_output_stream_nil;
2236     }
2237
2238     _cairo_output_stream_init (&stream->base,
2239                                _string_array_stream_write,
2240                                NULL,
2241                                _string_array_stream_close);
2242     stream->output = output;
2243     stream->column = 0;
2244     stream->string_size = 0;
2245     stream->use_strings = TRUE;
2246
2247     return &stream->base;
2248 }
2249
2250 /* A base85_array_stream wraps an existing output stream. It wraps the
2251  * output within STRING_ARRAY_MAX_COLUMN columns (+/- 1). The output
2252  * is not enclosed in strings like string_array_stream.
2253  */
2254 static cairo_output_stream_t *
2255 _base85_array_stream_create (cairo_output_stream_t *output)
2256 {
2257     string_array_stream_t *stream;
2258
2259     stream = malloc (sizeof (string_array_stream_t));
2260     if (unlikely (stream == NULL)) {
2261         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2262         return (cairo_output_stream_t *) &_cairo_output_stream_nil;
2263     }
2264
2265     _cairo_output_stream_init (&stream->base,
2266                                _string_array_stream_write,
2267                                NULL,
2268                                _string_array_stream_close);
2269     stream->output = output;
2270     stream->column = 0;
2271     stream->string_size = 0;
2272     stream->use_strings = FALSE;
2273
2274     return &stream->base;
2275 }
2276
2277
2278 /* PS Output - this section handles output of the parts of the recording
2279  * surface we can render natively in PS. */
2280
2281 static cairo_status_t
2282 _cairo_ps_surface_flatten_image_transparency (cairo_ps_surface_t    *surface,
2283                                               cairo_image_surface_t *image,
2284                                               cairo_image_surface_t **opaque_image)
2285 {
2286     cairo_surface_t *opaque;
2287     cairo_surface_pattern_t pattern;
2288     cairo_status_t status;
2289
2290     opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
2291                                          image->width,
2292                                          image->height);
2293     if (unlikely (opaque->status)) {
2294         status = opaque->status;
2295         cairo_surface_destroy (opaque);
2296         return status;
2297     }
2298
2299     if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) {
2300         status = _cairo_surface_paint (opaque,
2301                                        CAIRO_OPERATOR_SOURCE,
2302                                        &_cairo_pattern_white.base,
2303                                        NULL);
2304         if (unlikely (status)) {
2305             cairo_surface_destroy (opaque);
2306             return status;
2307         }
2308     }
2309
2310     _cairo_pattern_init_for_surface (&pattern, &image->base);
2311     pattern.base.filter = CAIRO_FILTER_NEAREST;
2312     status = _cairo_surface_paint (opaque, CAIRO_OPERATOR_OVER, &pattern.base, NULL);
2313     _cairo_pattern_fini (&pattern.base);
2314     if (unlikely (status)) {
2315         cairo_surface_destroy (opaque);
2316         return status;
2317     }
2318
2319     *opaque_image = (cairo_image_surface_t *) opaque;
2320     return CAIRO_STATUS_SUCCESS;
2321 }
2322
2323 static cairo_status_t
2324 _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t    *surface,
2325                                       const unsigned char   *data,
2326                                       unsigned long          length,
2327                                       cairo_ps_compress_t    compress,
2328                                       cairo_bool_t           use_strings)
2329 {
2330     cairo_output_stream_t *base85_stream, *string_array_stream, *deflate_stream;
2331     unsigned char *data_compressed;
2332     unsigned long data_compressed_size;
2333     cairo_status_t status, status2;
2334
2335     if (use_strings)
2336         string_array_stream = _string_array_stream_create (surface->stream);
2337     else
2338         string_array_stream = _base85_array_stream_create (surface->stream);
2339
2340     status = _cairo_output_stream_get_status (string_array_stream);
2341     if (unlikely (status))
2342         return _cairo_output_stream_destroy (string_array_stream);
2343
2344     base85_stream = _cairo_base85_stream_create (string_array_stream);
2345     status = _cairo_output_stream_get_status (base85_stream);
2346     if (unlikely (status)) {
2347         status2 = _cairo_output_stream_destroy (string_array_stream);
2348         return _cairo_output_stream_destroy (base85_stream);
2349     }
2350
2351     switch (compress) {
2352         case CAIRO_PS_COMPRESS_NONE:
2353             _cairo_output_stream_write (base85_stream, data, length);
2354             break;
2355
2356         case CAIRO_PS_COMPRESS_LZW:
2357             /* XXX: Should fix cairo-lzw to provide a stream-based interface
2358              * instead. */
2359             data_compressed_size = length;
2360             data_compressed = _cairo_lzw_compress ((unsigned char*)data, &data_compressed_size);
2361             if (unlikely (data_compressed == NULL)) {
2362                 status = _cairo_output_stream_destroy (string_array_stream);
2363                 status = _cairo_output_stream_destroy (base85_stream);
2364                 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2365             }
2366             _cairo_output_stream_write (base85_stream, data_compressed, data_compressed_size);
2367             free (data_compressed);
2368             break;
2369
2370         case CAIRO_PS_COMPRESS_DEFLATE:
2371             deflate_stream = _cairo_deflate_stream_create (base85_stream);
2372             if (_cairo_output_stream_get_status (deflate_stream)) {
2373                 return _cairo_output_stream_destroy (deflate_stream);
2374             }
2375             _cairo_output_stream_write (deflate_stream, data, length);
2376             status = _cairo_output_stream_destroy (deflate_stream);
2377             if (unlikely (status)) {
2378                 status2 = _cairo_output_stream_destroy (string_array_stream);
2379                 status2 = _cairo_output_stream_destroy (base85_stream);
2380                 return _cairo_output_stream_destroy (deflate_stream);
2381             }
2382             break;
2383     }
2384     status = _cairo_output_stream_destroy (base85_stream);
2385
2386     /* Mark end of base85 data */
2387     _cairo_output_stream_printf (string_array_stream, "~>");
2388     status2 = _cairo_output_stream_destroy (string_array_stream);
2389     if (status == CAIRO_STATUS_SUCCESS)
2390         status = status2;
2391
2392     return status;
2393 }
2394
2395 static cairo_status_t
2396 _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
2397                               cairo_image_surface_t *image_surf,
2398                               cairo_operator_t       op,
2399                               cairo_filter_t         filter,
2400                               cairo_bool_t           stencil_mask)
2401 {
2402     cairo_status_t status;
2403     unsigned char *data;
2404     unsigned long data_size;
2405     cairo_image_surface_t *ps_image;
2406     int x, y, i, a;
2407     cairo_image_transparency_t transparency;
2408     cairo_bool_t use_mask;
2409     uint32_t *pixel32;
2410     uint8_t *pixel8;
2411     int bit;
2412     cairo_image_color_t color;
2413     const char *interpolate;
2414     cairo_ps_compress_t compress;
2415     const char *compress_filter;
2416     cairo_image_surface_t *image;
2417
2418     if (image_surf->base.status)
2419         return image_surf->base.status;
2420
2421     image  = image_surf;
2422     if (image->format != CAIRO_FORMAT_RGB24 &&
2423         image->format != CAIRO_FORMAT_ARGB32 &&
2424         image->format != CAIRO_FORMAT_A8 &&
2425         image->format != CAIRO_FORMAT_A1)
2426     {
2427         cairo_surface_t *surf;
2428         cairo_surface_pattern_t pattern;
2429
2430         surf = _cairo_image_surface_create_with_content (image_surf->base.content,
2431                                                          image_surf->width,
2432                                                          image_surf->height);
2433         image = (cairo_image_surface_t *) surf;
2434         if (surf->status) {
2435             status = surf->status;
2436             goto bail0;
2437         }
2438
2439         _cairo_pattern_init_for_surface (&pattern, &image_surf->base);
2440         status = _cairo_surface_paint (surf,
2441                                        CAIRO_OPERATOR_SOURCE, &pattern.base,
2442                                        NULL);
2443         _cairo_pattern_fini (&pattern.base);
2444         if (unlikely (status))
2445             goto bail0;
2446     }
2447     ps_image = image;
2448
2449     switch (filter) {
2450     default:
2451     case CAIRO_FILTER_GOOD:
2452     case CAIRO_FILTER_BEST:
2453     case CAIRO_FILTER_BILINEAR:
2454         interpolate = "true";
2455         break;
2456     case CAIRO_FILTER_FAST:
2457     case CAIRO_FILTER_NEAREST:
2458     case CAIRO_FILTER_GAUSSIAN:
2459         interpolate = "false";
2460         break;
2461     }
2462
2463     if (stencil_mask) {
2464         use_mask = FALSE;
2465         color = CAIRO_IMAGE_IS_MONOCHROME;
2466         transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
2467     } else {
2468         transparency = _cairo_image_analyze_transparency (image);
2469
2470         /* PostScript can not represent the alpha channel, so we blend the
2471            current image over a white (or black for CONTENT_COLOR
2472            surfaces) RGB surface to eliminate it. */
2473
2474         if (op == CAIRO_OPERATOR_SOURCE ||
2475             transparency == CAIRO_IMAGE_HAS_ALPHA ||
2476             (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA &&
2477              surface->ps_level == CAIRO_PS_LEVEL_2))
2478         {
2479             status = _cairo_ps_surface_flatten_image_transparency (surface,
2480                                                                    image,
2481                                                                    &ps_image);
2482             if (unlikely (status))
2483                 return status;
2484
2485             use_mask = FALSE;
2486         } else if (transparency == CAIRO_IMAGE_IS_OPAQUE) {
2487             use_mask = FALSE;
2488         } else { /* transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA */
2489             use_mask = TRUE;
2490         }
2491
2492         color = _cairo_image_analyze_color (ps_image);
2493     }
2494
2495     /* Type 2 (mask and image interleaved) has the mask and image
2496      * samples interleaved by row.  The mask row is first, one bit per
2497      * pixel with (bit 7 first). The row is padded to byte
2498      * boundaries. The image data is 3 bytes per pixel RGB format. */
2499     switch (color) {
2500     default:
2501     case CAIRO_IMAGE_UNKNOWN_COLOR:
2502         ASSERT_NOT_REACHED;
2503     case CAIRO_IMAGE_IS_COLOR:
2504         data_size = ps_image->width * 3;
2505         break;
2506     case CAIRO_IMAGE_IS_GRAYSCALE:
2507         data_size = ps_image->width;
2508         break;
2509     case CAIRO_IMAGE_IS_MONOCHROME:
2510         data_size = (ps_image->width + 7)/8;
2511         break;
2512     }
2513     if (use_mask)
2514         data_size += (ps_image->width + 7)/8;
2515     data_size *= ps_image->height;
2516     data = malloc (data_size);
2517     if (unlikely (data == NULL)) {
2518         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2519         goto bail1;
2520     }
2521
2522     i = 0;
2523     for (y = 0; y < ps_image->height; y++) {
2524         if (stencil_mask || use_mask) {
2525             /* mask row */
2526             if (ps_image->format == CAIRO_FORMAT_A1) {
2527                 pixel8 = (uint8_t *) (ps_image->data + y * ps_image->stride);
2528
2529                 for (x = 0; x < (ps_image->width + 7) / 8; x++, pixel8++) {
2530                     a = *pixel8;
2531                     a = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (a);
2532                     data[i++] = a;
2533                 }
2534             } else {
2535                 pixel8 = (uint8_t *) (ps_image->data + y * ps_image->stride);
2536                 pixel32 = (uint32_t *) (ps_image->data + y * ps_image->stride);
2537                 bit = 7;
2538                 for (x = 0; x < ps_image->width; x++) {
2539                     if (ps_image->format == CAIRO_FORMAT_ARGB32) {
2540                         a = (*pixel32 & 0xff000000) >> 24;
2541                         pixel32++;
2542                     } else {
2543                         a = *pixel8;
2544                         pixel8++;
2545                     }
2546
2547                     if (transparency == CAIRO_IMAGE_HAS_ALPHA) {
2548                         data[i++] = a;
2549                     } else { /* transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA or CAIRO_IMAGE_IS_OPAQUE */
2550                         if (bit == 7)
2551                             data[i] = 0;
2552                         if (a != 0)
2553                             data[i] |= (1 << bit);
2554                         bit--;
2555                         if (bit < 0) {
2556                             bit = 7;
2557                             i++;
2558                         }
2559                     }
2560                 }
2561                 if (bit != 7)
2562                     i++;
2563             }
2564         }
2565         if (stencil_mask)
2566             continue;
2567
2568         /* image row*/
2569         pixel32 = (uint32_t *) (ps_image->data + y * ps_image->stride);
2570         bit = 7;
2571         for (x = 0; x < ps_image->width; x++, pixel32++) {
2572             int r, g, b;
2573
2574             if (ps_image->format == CAIRO_FORMAT_ARGB32) {
2575                 /* At this point ARGB32 images are either opaque or
2576                  * bilevel alpha so we don't need to unpremultiply. */
2577                 if (((*pixel32 & 0xff000000) >> 24) == 0) {
2578                     r = g = b = 0;
2579                 } else {
2580                     r = (*pixel32 & 0x00ff0000) >> 16;
2581                     g = (*pixel32 & 0x0000ff00) >>  8;
2582                     b = (*pixel32 & 0x000000ff) >>  0;
2583                 }
2584             } else if (ps_image->format == CAIRO_FORMAT_RGB24) {
2585                 r = (*pixel32 & 0x00ff0000) >> 16;
2586                 g = (*pixel32 & 0x0000ff00) >>  8;
2587                 b = (*pixel32 & 0x000000ff) >>  0;
2588             } else {
2589                 r = g = b = 0;
2590             }
2591
2592             switch (color) {
2593                 case CAIRO_IMAGE_IS_COLOR:
2594                 case CAIRO_IMAGE_UNKNOWN_COLOR:
2595                     data[i++] = r;
2596                     data[i++] = g;
2597                     data[i++] = b;
2598                     break;
2599
2600                 case CAIRO_IMAGE_IS_GRAYSCALE:
2601                     data[i++] = r;
2602                     break;
2603
2604                 case CAIRO_IMAGE_IS_MONOCHROME:
2605                     if (bit == 7)
2606                         data[i] = 0;
2607                     if (r != 0)
2608                         data[i] |= (1 << bit);
2609                     bit--;
2610                     if (bit < 0) {
2611                         bit = 7;
2612                         i++;
2613                     }
2614                     break;
2615             }
2616         }
2617         if (bit != 7)
2618             i++;
2619     }
2620
2621     if (surface->ps_level == CAIRO_PS_LEVEL_2) {
2622         compress = CAIRO_PS_COMPRESS_LZW;
2623         compress_filter = "LZWDecode";
2624     } else {
2625         compress = CAIRO_PS_COMPRESS_DEFLATE;
2626         compress_filter = "FlateDecode";
2627         surface->ps_level_used = CAIRO_PS_LEVEL_3;
2628     }
2629
2630     if (surface->use_string_datasource) {
2631         /* Emit the image data as a base85-encoded string which will
2632          * be used as the data source for the image operator later. */
2633         _cairo_output_stream_printf (surface->stream,
2634                                      "/CairoImageData [\n");
2635
2636         status = _cairo_ps_surface_emit_base85_string (surface,
2637                                                        data,
2638                                                        data_size,
2639                                                        compress,
2640                                                        TRUE);
2641         if (unlikely (status))
2642             goto bail2;
2643
2644         _cairo_output_stream_printf (surface->stream,
2645                                      "] def\n");
2646         _cairo_output_stream_printf (surface->stream,
2647                                      "/CairoImageDataIndex 0 def\n");
2648     }
2649
2650     if (use_mask) {
2651         _cairo_output_stream_printf (surface->stream,
2652                                      "%s setcolorspace\n"
2653                                      "5 dict dup begin\n"
2654                                      "  /ImageType 3 def\n"
2655                                      "  /InterleaveType 2 def\n"
2656                                      "  /DataDict 8 dict def\n"
2657                                      "    DataDict begin\n"
2658                                      "    /ImageType 1 def\n"
2659                                      "    /Width %d def\n"
2660                                      "    /Height %d def\n"
2661                                      "    /Interpolate %s def\n"
2662                                      "    /BitsPerComponent %d def\n"
2663                                      "    /Decode [ %s ] def\n",
2664                                      color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray",
2665                                      ps_image->width,
2666                                      ps_image->height,
2667                                      interpolate,
2668                                      color == CAIRO_IMAGE_IS_MONOCHROME ? 1 : 8,
2669                                      color == CAIRO_IMAGE_IS_COLOR ? "0 1 0 1 0 1" : "0 1");
2670
2671         if (surface->use_string_datasource) {
2672             _cairo_output_stream_printf (surface->stream,
2673                                          "    /DataSource {\n"
2674                                          "      CairoImageData CairoImageDataIndex get\n"
2675                                          "      /CairoImageDataIndex CairoImageDataIndex 1 add def\n"
2676                                          "      CairoImageDataIndex CairoImageData length 1 sub gt\n"
2677                                          "       { /CairoImageDataIndex 0 def } if\n"
2678                                          "    } /ASCII85Decode filter /%s filter def\n",
2679                                          compress_filter);
2680         } else {
2681             _cairo_output_stream_printf (surface->stream,
2682                                          "    /DataSource currentfile /ASCII85Decode filter /%s filter def\n",
2683                                          compress_filter);
2684         }
2685
2686         _cairo_output_stream_printf (surface->stream,
2687                                      "    /ImageMatrix [ 1 0 0 -1 0 %d ] def\n"
2688                                      "  end\n"
2689                                      "  /MaskDict 8 dict def\n"
2690                                      "     MaskDict begin\n"
2691                                      "    /ImageType 1 def\n"
2692                                      "    /Width %d def\n"
2693                                      "    /Height %d def\n"
2694                                      "    /Interpolate %s def\n"
2695                                      "    /BitsPerComponent 1 def\n"
2696                                      "    /Decode [ 1 0 ] def\n"
2697                                      "    /ImageMatrix [ 1 0 0 -1 0 %d ] def\n"
2698                                      "  end\n"
2699                                      "end\n"
2700                                      "image\n",
2701                                      ps_image->height,
2702                                      ps_image->width,
2703                                      ps_image->height,
2704                                      interpolate,
2705                                      ps_image->height);
2706     } else {
2707         if (!stencil_mask) {
2708             _cairo_output_stream_printf (surface->stream,
2709                                          "%s setcolorspace\n",
2710                                          color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray");
2711         }
2712         _cairo_output_stream_printf (surface->stream,
2713                                      "8 dict dup begin\n"
2714                                      "  /ImageType 1 def\n"
2715                                      "  /Width %d def\n"
2716                                      "  /Height %d def\n"
2717                                      "  /Interpolate %s def\n"
2718                                      "  /BitsPerComponent %d def\n"
2719                                      "  /Decode [ %s ] def\n",
2720                                      ps_image->width,
2721                                      ps_image->height,
2722                                      interpolate,
2723                                      color == CAIRO_IMAGE_IS_MONOCHROME ? 1 : 8,
2724                                      stencil_mask ? "1 0" : color == CAIRO_IMAGE_IS_COLOR ? "0 1 0 1 0 1" : "0 1");
2725         if (surface->use_string_datasource) {
2726             _cairo_output_stream_printf (surface->stream,
2727                                          "  /DataSource {\n"
2728                                          "    CairoImageData CairoImageDataIndex get\n"
2729                                          "    /CairoImageDataIndex CairoImageDataIndex 1 add def\n"
2730                                          "    CairoImageDataIndex CairoImageData length 1 sub gt\n"
2731                                          "     { /CairoImageDataIndex 0 def } if\n"
2732                                          "  } /ASCII85Decode filter /%s filter def\n",
2733                                          compress_filter);
2734         } else {
2735             _cairo_output_stream_printf (surface->stream,
2736                                          "  /DataSource currentfile /ASCII85Decode filter /%s filter def\n",
2737                                          compress_filter);
2738         }
2739
2740         _cairo_output_stream_printf (surface->stream,
2741                                      "  /Interpolate %s def\n"
2742                                      "  /ImageMatrix [ 1 0 0 -1 0 %d ] def\n"
2743                                      "end\n"
2744                                      "%s\n",
2745                                      interpolate,
2746                                      ps_image->height,
2747                                      stencil_mask ? "imagemask" : "image");
2748     }
2749
2750     if (!surface->use_string_datasource) {
2751         /* Emit the image data as a base85-encoded string which will
2752          * be used as the data source for the image operator. */
2753         status = _cairo_ps_surface_emit_base85_string (surface,
2754                                                        data,
2755                                                        data_size,
2756                                                        compress,
2757                                                        FALSE);
2758         _cairo_output_stream_printf (surface->stream, "\n");
2759     } else {
2760         status = CAIRO_STATUS_SUCCESS;
2761     }
2762
2763 bail2:
2764     free (data);
2765
2766 bail1:
2767     if (!use_mask && ps_image != image)
2768         cairo_surface_destroy (&ps_image->base);
2769
2770 bail0:
2771     if (image != image_surf)
2772         cairo_surface_destroy (&image->base);
2773
2774     return status;
2775 }
2776
2777 static cairo_status_t
2778 _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t    *surface,
2779                                    cairo_surface_t       *source,
2780                                    int                    width,
2781                                    int                    height)
2782 {
2783     cairo_status_t status;
2784     const unsigned char *mime_data;
2785     unsigned long mime_data_length;
2786     cairo_image_info_t info;
2787     const char *colorspace;
2788     const char *decode;
2789
2790     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
2791                                  &mime_data, &mime_data_length);
2792     if (unlikely (source->status))
2793         return source->status;
2794     if (mime_data == NULL)
2795         return CAIRO_INT_STATUS_UNSUPPORTED;
2796
2797     status = _cairo_image_info_get_jpeg_info (&info, mime_data, mime_data_length);
2798     if (unlikely (status))
2799         return status;
2800
2801     switch (info.num_components) {
2802         case 1:
2803             colorspace = "/DeviceGray";
2804             decode = "0 1";
2805             break;
2806         case 3:
2807             colorspace = "/DeviceRGB";
2808             decode =  "0 1 0 1 0 1";
2809             break;
2810         case 4:
2811             colorspace = "/DeviceCMYK";
2812             decode =  "0 1 0 1 0 1 0 1";
2813             break;
2814         default:
2815             return CAIRO_INT_STATUS_UNSUPPORTED;
2816     }
2817
2818     if (surface->use_string_datasource) {
2819         /* Emit the image data as a base85-encoded string which will
2820          * be used as the data source for the image operator later. */
2821         _cairo_output_stream_printf (surface->stream,
2822                                      "/CairoImageData [\n");
2823
2824         status = _cairo_ps_surface_emit_base85_string (surface,
2825                                                        mime_data,
2826                                                        mime_data_length,
2827                                                        CAIRO_PS_COMPRESS_NONE,
2828                                                        TRUE);
2829         if (unlikely (status))
2830             return status;
2831
2832         _cairo_output_stream_printf (surface->stream,
2833                                      "] def\n");
2834         _cairo_output_stream_printf (surface->stream,
2835                                      "/CairoImageDataIndex 0 def\n");
2836     }
2837
2838     _cairo_output_stream_printf (surface->stream,
2839                                  "%s setcolorspace\n"
2840                                  "8 dict dup begin\n"
2841                                  "  /ImageType 1 def\n"
2842                                  "  /Width %d def\n"
2843                                  "  /Height %d def\n"
2844                                  "  /BitsPerComponent %d def\n"
2845                                  "  /Decode [ %s ] def\n",
2846                                  colorspace,
2847                                  info.width,
2848                                  info.height,
2849                                  info.bits_per_component,
2850                                  decode);
2851
2852     if (surface->use_string_datasource) {
2853         _cairo_output_stream_printf (surface->stream,
2854                                      "  /DataSource {\n"
2855                                      "    CairoImageData CairoImageDataIndex get\n"
2856                                      "    /CairoImageDataIndex CairoImageDataIndex 1 add def\n"
2857                                      "    CairoImageDataIndex CairoImageData length 1 sub gt\n"
2858                                      "     { /CairoImageDataIndex 0 def } if\n"
2859                                      "  } /ASCII85Decode filter /DCTDecode filter def\n");
2860     } else {
2861         _cairo_output_stream_printf (surface->stream,
2862                                      "  /DataSource currentfile /ASCII85Decode filter /DCTDecode filter def\n");
2863     }
2864
2865     _cairo_output_stream_printf (surface->stream,
2866                                  "  /ImageMatrix [ 1 0 0 -1 0 %d ] def\n"
2867                                  "end\n"
2868                                  "image\n",
2869                                  info.height);
2870
2871     if (!surface->use_string_datasource) {
2872         /* Emit the image data as a base85-encoded string which will
2873          * be used as the data source for the image operator. */
2874         status = _cairo_ps_surface_emit_base85_string (surface,
2875                                                        mime_data,
2876                                                        mime_data_length,
2877                                                        CAIRO_PS_COMPRESS_NONE,
2878                                                        FALSE);
2879     }
2880
2881     return status;
2882 }
2883
2884 static cairo_status_t
2885 _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface,
2886                                           cairo_surface_t    *recording_surface)
2887 {
2888     double old_width, old_height;
2889     cairo_matrix_t old_cairo_to_ps;
2890     cairo_content_t old_content;
2891     cairo_rectangle_int_t old_page_bbox;
2892     cairo_surface_t *free_me = NULL;
2893     cairo_surface_clipper_t old_clipper;
2894     cairo_box_t bbox;
2895     cairo_int_status_t status;
2896
2897     old_content = surface->content;
2898     old_width = surface->width;
2899     old_height = surface->height;
2900     old_page_bbox = surface->page_bbox;
2901     old_cairo_to_ps = surface->cairo_to_ps;
2902     old_clipper = surface->clipper;
2903     _cairo_surface_clipper_init (&surface->clipper,
2904                                  _cairo_ps_surface_clipper_intersect_clip_path);
2905
2906     if (_cairo_surface_is_snapshot (recording_surface))
2907         free_me = recording_surface = _cairo_surface_snapshot_get_target (recording_surface);
2908
2909     status =
2910         _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
2911                                            &bbox,
2912                                            NULL);
2913     if (unlikely (status))
2914         goto err;
2915
2916 #if DEBUG_PS
2917     _cairo_output_stream_printf (surface->stream,
2918                                  "%% _cairo_ps_surface_emit_recording_surface (%f, %f), (%f, %f)\n",
2919                                  _cairo_fixed_to_double (bbox.p1.x),
2920                                  _cairo_fixed_to_double (bbox.p1.y),
2921                                  _cairo_fixed_to_double (bbox.p2.x),
2922                                  _cairo_fixed_to_double (bbox.p2.y));
2923 #endif
2924
2925     surface->width = _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x);
2926     surface->height = _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y);
2927     _cairo_box_round_to_rectangle (&bbox, &surface->page_bbox);
2928
2929     surface->current_pattern_is_solid_color = FALSE;
2930     _cairo_pdf_operators_reset (&surface->pdf_operators);
2931     cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, surface->height);
2932     _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
2933                                                   &surface->cairo_to_ps);
2934     _cairo_output_stream_printf (surface->stream, "  q\n");
2935
2936     if (recording_surface->content == CAIRO_CONTENT_COLOR) {
2937         surface->content = CAIRO_CONTENT_COLOR;
2938         _cairo_output_stream_printf (surface->stream,
2939                                      "  0 g %d %d %d %d rectfill\n",
2940                                      surface->page_bbox.x,
2941                                      surface->page_bbox.y,
2942                                      surface->page_bbox.width,
2943                                      surface->page_bbox.height);
2944     }
2945
2946     status = _cairo_recording_surface_replay_region (recording_surface,
2947                                                      NULL,
2948                                                      &surface->base,
2949                                                      CAIRO_RECORDING_REGION_NATIVE);
2950     assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
2951     if (unlikely (status))
2952         goto err;
2953
2954     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
2955     if (unlikely (status))
2956         goto err;
2957
2958     _cairo_output_stream_printf (surface->stream, "  Q\n");
2959
2960     _cairo_surface_clipper_reset (&surface->clipper);
2961     surface->clipper = old_clipper;
2962     surface->content = old_content;
2963     surface->width = old_width;
2964     surface->height = old_height;
2965     surface->page_bbox = old_page_bbox;
2966     surface->current_pattern_is_solid_color = FALSE;
2967     _cairo_pdf_operators_reset (&surface->pdf_operators);
2968     surface->cairo_to_ps = old_cairo_to_ps;
2969
2970     _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
2971                                                   &surface->cairo_to_ps);
2972
2973 err:
2974     cairo_surface_destroy (free_me);
2975     return status;
2976 }
2977
2978 static cairo_int_status_t
2979 _cairo_ps_surface_emit_recording_subsurface (cairo_ps_surface_t *surface,
2980                                              cairo_surface_t    *recording_surface,
2981                                              const cairo_rectangle_int_t *extents)
2982 {
2983     double old_width, old_height;
2984     cairo_matrix_t old_cairo_to_ps;
2985     cairo_content_t old_content;
2986     cairo_rectangle_int_t old_page_bbox;
2987     cairo_surface_clipper_t old_clipper;
2988     cairo_surface_t *free_me = NULL;
2989     cairo_int_status_t status;
2990
2991     old_content = surface->content;
2992     old_width = surface->width;
2993     old_height = surface->height;
2994     old_page_bbox = surface->page_bbox;
2995     old_cairo_to_ps = surface->cairo_to_ps;
2996     old_clipper = surface->clipper;
2997     _cairo_surface_clipper_init (&surface->clipper,
2998                                  _cairo_ps_surface_clipper_intersect_clip_path);
2999
3000 #if DEBUG_PS
3001     _cairo_output_stream_printf (surface->stream,
3002                                  "%% _cairo_ps_surface_emit_recording_subsurface (%d, %d), (%d, %d)\n",
3003                                  extents->x, extents->y,
3004                                  extents->width, extents->height);
3005 #endif
3006
3007     surface->page_bbox.x = surface->page_bbox.y = 0;
3008     surface->page_bbox.width = surface->width  = extents->width;
3009     surface->page_bbox.height = surface->height = extents->height;
3010
3011     surface->current_pattern_is_solid_color = FALSE;
3012     _cairo_pdf_operators_reset (&surface->pdf_operators);
3013     cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, surface->height);
3014     _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
3015                                                   &surface->cairo_to_ps);
3016     _cairo_output_stream_printf (surface->stream, "  q\n");
3017
3018     if (_cairo_surface_is_snapshot (recording_surface))
3019         free_me = recording_surface = _cairo_surface_snapshot_get_target (recording_surface);
3020
3021     if (recording_surface->content == CAIRO_CONTENT_COLOR) {
3022         surface->content = CAIRO_CONTENT_COLOR;
3023         _cairo_output_stream_printf (surface->stream,
3024                                      "  0 g %d %d %d %d rectfill\n",
3025                                      surface->page_bbox.x,
3026                                      surface->page_bbox.y,
3027                                      surface->page_bbox.width,
3028                                      surface->page_bbox.height);
3029     }
3030
3031     status = _cairo_recording_surface_replay_region (recording_surface,
3032                                                      extents,
3033                                                      &surface->base,
3034                                                      CAIRO_RECORDING_REGION_NATIVE);
3035     assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
3036     if (unlikely (status))
3037         goto err;
3038
3039     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3040     if (unlikely (status))
3041         goto err;
3042
3043     _cairo_output_stream_printf (surface->stream, "  Q\n");
3044
3045     _cairo_surface_clipper_reset (&surface->clipper);
3046     surface->clipper = old_clipper;
3047     surface->content = old_content;
3048     surface->width = old_width;
3049     surface->height = old_height;
3050     surface->page_bbox = old_page_bbox;
3051     surface->current_pattern_is_solid_color = FALSE;
3052     _cairo_pdf_operators_reset (&surface->pdf_operators);
3053     surface->cairo_to_ps = old_cairo_to_ps;
3054
3055     _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
3056                                                   &surface->cairo_to_ps);
3057
3058 err:
3059     cairo_surface_destroy (free_me);
3060     return status;
3061 }
3062
3063 static void
3064 _cairo_ps_surface_flatten_transparency (cairo_ps_surface_t      *surface,
3065                                         const cairo_color_t     *color,
3066                                         double                  *red,
3067                                         double                  *green,
3068                                         double                  *blue)
3069 {
3070     *red   = color->red;
3071     *green = color->green;
3072     *blue  = color->blue;
3073
3074     if (! CAIRO_COLOR_IS_OPAQUE (color)) {
3075         *red   *= color->alpha;
3076         *green *= color->alpha;
3077         *blue  *= color->alpha;
3078         if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) {
3079             double one_minus_alpha = 1. - color->alpha;
3080             *red   += one_minus_alpha;
3081             *green += one_minus_alpha;
3082             *blue  += one_minus_alpha;
3083         }
3084     }
3085 }
3086
3087 static void
3088 _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t    *surface,
3089                                       cairo_solid_pattern_t *pattern)
3090 {
3091     double red, green, blue;
3092
3093     _cairo_ps_surface_flatten_transparency (surface, &pattern->color, &red, &green, &blue);
3094
3095     if (color_is_gray (red, green, blue))
3096         _cairo_output_stream_printf (surface->stream,
3097                                      "%f g\n",
3098                                      red);
3099     else
3100         _cairo_output_stream_printf (surface->stream,
3101                                      "%f %f %f rg\n",
3102                                      red, green, blue);
3103 }
3104
3105 static cairo_status_t
3106 _cairo_ps_surface_emit_surface (cairo_ps_surface_t      *surface,
3107                                 cairo_pattern_t         *source_pattern,
3108                                 cairo_surface_t         *source_surface,
3109                                 cairo_operator_t         op,
3110                                 int                      width,
3111                                 int                      height,
3112                                 cairo_bool_t             stencil_mask)
3113 {
3114     cairo_int_status_t status;
3115
3116     if (source_surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
3117         if (source_surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
3118             cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source_surface;
3119             status = _cairo_ps_surface_emit_recording_subsurface (surface, sub->target, &sub->extents);
3120         } else {
3121             status = _cairo_ps_surface_emit_recording_surface (surface, source_surface);
3122         }
3123     } else {
3124         cairo_image_surface_t *image = (cairo_image_surface_t *) source_surface;
3125         if (source_pattern->extend != CAIRO_EXTEND_PAD) {
3126             status = _cairo_ps_surface_emit_jpeg_image (surface, source_surface,
3127                                                         width, height);
3128             if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3129                 return status;
3130         }
3131
3132         status = _cairo_ps_surface_emit_image (surface, image,
3133                                                op, source_pattern->filter, stencil_mask);
3134     }
3135
3136     return status;
3137 }
3138
3139
3140 static void
3141 _path_fixed_init_rectangle (cairo_path_fixed_t *path,
3142                             cairo_rectangle_int_t *rect)
3143 {
3144     cairo_status_t status;
3145
3146     _cairo_path_fixed_init (path);
3147
3148     status = _cairo_path_fixed_move_to (path,
3149                                         _cairo_fixed_from_int (rect->x),
3150                                         _cairo_fixed_from_int (rect->y));
3151     assert (status == CAIRO_STATUS_SUCCESS);
3152     status = _cairo_path_fixed_rel_line_to (path,
3153                                             _cairo_fixed_from_int (rect->width),
3154                                             _cairo_fixed_from_int (0));
3155     assert (status == CAIRO_STATUS_SUCCESS);
3156     status = _cairo_path_fixed_rel_line_to (path,
3157                                             _cairo_fixed_from_int (0),
3158                                             _cairo_fixed_from_int (rect->height));
3159     assert (status == CAIRO_STATUS_SUCCESS);
3160     status = _cairo_path_fixed_rel_line_to (path,
3161                                             _cairo_fixed_from_int (-rect->width),
3162                                             _cairo_fixed_from_int (0));
3163     assert (status == CAIRO_STATUS_SUCCESS);
3164
3165     status = _cairo_path_fixed_close_path (path);
3166     assert (status == CAIRO_STATUS_SUCCESS);
3167 }
3168
3169 static cairo_status_t
3170 _cairo_ps_surface_paint_surface (cairo_ps_surface_t     *surface,
3171                                  cairo_pattern_t        *pattern,
3172                                  cairo_rectangle_int_t  *extents,
3173                                  cairo_operator_t        op,
3174                                  cairo_bool_t            stencil_mask)
3175 {
3176     cairo_status_t status;
3177     int width, height;
3178     cairo_matrix_t cairo_p2d, ps_p2d;
3179     cairo_path_fixed_t path;
3180     double x_offset, y_offset;
3181     cairo_surface_t *source;
3182     cairo_image_surface_t *image = NULL;
3183     void *image_extra;
3184
3185     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3186     if (unlikely (status))
3187         return status;
3188
3189     status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface,
3190                                                                     pattern,
3191                                                                     extents,
3192                                                                     &width, &height,
3193                                                                     &x_offset, &y_offset,
3194                                                                     &source,
3195                                                                     &image_extra);
3196     if (unlikely (status))
3197         return status;
3198
3199     if (pattern->extend == CAIRO_EXTEND_PAD &&
3200         pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
3201         ((cairo_surface_pattern_t *)pattern)->surface->type == CAIRO_SURFACE_TYPE_IMAGE) {
3202         cairo_image_surface_t *img;
3203
3204         img = (cairo_image_surface_t *) source;
3205         status = _cairo_ps_surface_create_padded_image_from_image (surface,
3206                                                                    img,
3207                                                                    &pattern->matrix,
3208                                                                    extents,
3209                                                                    &width, &height,
3210                                                                    &x_offset, &y_offset,
3211                                                                    &image);
3212         if (unlikely (status))
3213             goto release_source;
3214     }
3215
3216     _path_fixed_init_rectangle (&path, extents);
3217     status = _cairo_pdf_operators_clip (&surface->pdf_operators,
3218                                         &path,
3219                                         CAIRO_FILL_RULE_WINDING);
3220     _cairo_path_fixed_fini (&path);
3221     if (unlikely (status))
3222         goto release_source;
3223
3224     cairo_p2d = pattern->matrix;
3225
3226     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
3227         double x_scale = cairo_p2d.xx;
3228         double y_scale = cairo_p2d.yy;
3229
3230         _cairo_output_stream_printf (surface->stream,
3231                                      "%% Fallback Image: x=%f y=%f w=%d h=%d ",
3232                                      -cairo_p2d.x0/x_scale,
3233                                      -cairo_p2d.y0/y_scale,
3234                                      (int)(width/x_scale),
3235                                      (int)(height/y_scale));
3236         if (x_scale == y_scale) {
3237             _cairo_output_stream_printf (surface->stream,
3238                                          "res=%fppi ",
3239                                          x_scale*72);
3240         } else {
3241             _cairo_output_stream_printf (surface->stream,
3242                                          "res=%fx%fppi ",
3243                                          x_scale*72,
3244                                          y_scale*72);
3245         }
3246         _cairo_output_stream_printf (surface->stream,
3247                                      "size=%ld\n",
3248                                      (long)width*height*3);
3249     } else {
3250         if (op == CAIRO_OPERATOR_SOURCE) {
3251             _cairo_output_stream_printf (surface->stream,
3252                                          "%d g 0 0 %f %f rectfill\n",
3253                                          surface->content == CAIRO_CONTENT_COLOR ? 0 : 1,
3254                                          surface->width,
3255                                          surface->height);
3256         }
3257     }
3258
3259     status = cairo_matrix_invert (&cairo_p2d);
3260     /* cairo_pattern_set_matrix ensures the matrix is invertible */
3261     assert (status == CAIRO_STATUS_SUCCESS);
3262
3263     ps_p2d = surface->cairo_to_ps;
3264     cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d);
3265     cairo_matrix_translate (&ps_p2d, x_offset, y_offset);
3266     cairo_matrix_translate (&ps_p2d, 0.0, height);
3267     cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
3268
3269     if (! _cairo_matrix_is_identity (&ps_p2d)) {
3270         _cairo_output_stream_printf (surface->stream,
3271                                      "[ %f %f %f %f %f %f ] concat\n",
3272                                      ps_p2d.xx, ps_p2d.yx,
3273                                      ps_p2d.xy, ps_p2d.yy,
3274                                      ps_p2d.x0, ps_p2d.y0);
3275     }
3276
3277     status = _cairo_ps_surface_emit_surface (surface,
3278                                              pattern,
3279                                              image ? &image->base : source,
3280                                              op,
3281                                              width, height,
3282                                              stencil_mask);
3283
3284   release_source:
3285     if (image)
3286         cairo_surface_destroy (&image->base);
3287
3288     _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra);
3289
3290     return status;
3291 }
3292
3293 static cairo_status_t
3294 _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t      *surface,
3295                                         cairo_pattern_t         *pattern,
3296                                         cairo_rectangle_int_t   *extents,
3297                                         cairo_operator_t         op)
3298 {
3299     cairo_status_t status;
3300     int pattern_width = 0; /* squelch bogus compiler warning */
3301     int pattern_height = 0; /* squelch bogus compiler warning */
3302     double xstep, ystep;
3303     cairo_matrix_t cairo_p2d, ps_p2d;
3304     cairo_bool_t old_use_string_datasource;
3305     double x_offset, y_offset;
3306     cairo_surface_t *source;
3307     cairo_image_surface_t *image = NULL;
3308     void *image_extra;
3309
3310     cairo_p2d = pattern->matrix;
3311     status = cairo_matrix_invert (&cairo_p2d);
3312     /* cairo_pattern_set_matrix ensures the matrix is invertible */
3313     assert (status == CAIRO_STATUS_SUCCESS);
3314
3315     status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface,
3316                                                                     pattern,
3317                                                                     extents,
3318                                                                     &pattern_width, &pattern_height,
3319                                                                     &x_offset, &y_offset,
3320                                                                     &source,
3321                                                                     &image_extra);
3322     if (unlikely (status))
3323         return status;
3324
3325     if (pattern->extend == CAIRO_EXTEND_PAD) {
3326         cairo_image_surface_t *img;
3327
3328         assert (source->type == CAIRO_SURFACE_TYPE_IMAGE);
3329         img = (cairo_image_surface_t *) source;
3330         status = _cairo_ps_surface_create_padded_image_from_image (surface,
3331                                                                    img,
3332                                                                    &pattern->matrix,
3333                                                                    extents,
3334                                                                    &pattern_width, &pattern_height,
3335                                                                    &x_offset, &y_offset,
3336                                                                    &image);
3337         if (unlikely (status))
3338             goto release_source;
3339     }
3340
3341     switch (pattern->extend) {
3342     case CAIRO_EXTEND_PAD:
3343     case CAIRO_EXTEND_NONE:
3344     {
3345         /* In PS/PDF, (as far as I can tell), all patterns are
3346          * repeating. So we support cairo's EXTEND_NONE semantics
3347          * by setting the repeat step size to a size large enough
3348          * to guarantee that no more than a single occurrence will
3349          * be visible.
3350          *
3351          * First, map the surface extents into pattern space (since
3352          * xstep and ystep are in pattern space).  Then use an upper
3353          * bound on the length of the diagonal of the pattern image
3354          * and the surface as repeat size.  This guarantees to never
3355          * repeat visibly.
3356          */
3357         double x1 = 0.0, y1 = 0.0;
3358         double x2 = surface->width, y2 = surface->height;
3359         _cairo_matrix_transform_bounding_box (&pattern->matrix,
3360                                               &x1, &y1, &x2, &y2,
3361                                               NULL);
3362
3363         /* Rather than computing precise bounds of the union, just
3364          * add the surface extents unconditionally. We only
3365          * required an answer that's large enough, we don't really
3366          * care if it's not as tight as possible.*/
3367         xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
3368                               pattern_width + pattern_height);
3369         break;
3370     }
3371     case CAIRO_EXTEND_REPEAT:
3372         xstep = pattern_width;
3373         ystep = pattern_height;
3374         break;
3375     case CAIRO_EXTEND_REFLECT:
3376         xstep = pattern_width*2;
3377         ystep = pattern_height*2;
3378         break;
3379         /* All the rest (if any) should have been analyzed away, so these
3380          * cases should be unreachable. */
3381     default:
3382         ASSERT_NOT_REACHED;
3383         xstep = 0;
3384         ystep = 0;
3385     }
3386
3387     _cairo_output_stream_printf (surface->stream,
3388                                  "/CairoPattern {\n");
3389
3390     old_use_string_datasource = surface->use_string_datasource;
3391     surface->use_string_datasource = TRUE;
3392     if (op == CAIRO_OPERATOR_SOURCE) {
3393         _cairo_output_stream_printf (surface->stream,
3394                                      "%d g 0 0 %f %f rectfill\n",
3395                                      surface->content == CAIRO_CONTENT_COLOR ? 0 : 1,
3396                                      xstep, ystep);
3397     }
3398     status = _cairo_ps_surface_emit_surface (surface,
3399                                              pattern,
3400                                              image ? &image->base : source,
3401                                              op,
3402                                              pattern_width, pattern_height, FALSE);
3403     if (unlikely (status))
3404         goto release_source;
3405
3406     surface->use_string_datasource = old_use_string_datasource;
3407     _cairo_output_stream_printf (surface->stream,
3408                                  "} bind def\n");
3409
3410     _cairo_output_stream_printf (surface->stream,
3411                                  "<< /PatternType 1\n"
3412                                  "   /PaintType 1\n"
3413                                  "   /TilingType 1\n");
3414     _cairo_output_stream_printf (surface->stream,
3415                                  "   /XStep %f /YStep %f\n",
3416                                  xstep, ystep);
3417
3418     if (pattern->extend == CAIRO_EXTEND_REFLECT) {
3419         _cairo_output_stream_printf (surface->stream,
3420                                      "   /BBox [0 0 %d %d]\n"
3421                                      "   /PaintProc {\n"
3422                                      "      CairoPattern\n"
3423                                      "      [-1 0 0  1 %d 0] concat CairoPattern\n"
3424                                      "      [ 1 0 0 -1 0 %d] concat CairoPattern\n"
3425                                      "      [-1 0 0  1 %d 0] concat CairoPattern\n"
3426                                      "      CairoPattern\n"
3427                                      "   } bind\n",
3428                                      pattern_width*2, pattern_height*2,
3429                                      pattern_width*2,
3430                                      pattern_height*2,
3431                                      pattern_width*2);
3432     } else {
3433         if (op == CAIRO_OPERATOR_SOURCE) {
3434             _cairo_output_stream_printf (surface->stream,
3435                                          "   /BBox [0 0 %f %f]\n",
3436                                          xstep, ystep);
3437         } else {
3438             _cairo_output_stream_printf (surface->stream,
3439                                          "   /BBox [0 0 %d %d]\n",
3440                                          pattern_width, pattern_height);
3441         }
3442         _cairo_output_stream_printf (surface->stream,
3443                                      "   /PaintProc { CairoPattern }\n");
3444     }
3445
3446     _cairo_output_stream_printf (surface->stream,
3447                                  ">>\n");
3448
3449     cairo_p2d = pattern->matrix;
3450     status = cairo_matrix_invert (&cairo_p2d);
3451     /* cairo_pattern_set_matrix ensures the matrix is invertible */
3452     assert (status == CAIRO_STATUS_SUCCESS);
3453
3454     cairo_matrix_init_identity (&ps_p2d);
3455     cairo_matrix_translate (&ps_p2d, 0.0, surface->height);
3456     cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
3457     cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d);
3458     cairo_matrix_translate (&ps_p2d, 0.0, pattern_height);
3459     cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
3460
3461     _cairo_output_stream_printf (surface->stream,
3462                                  "[ %f %f %f %f %f %f ]\n",
3463                                  ps_p2d.xx, ps_p2d.yx,
3464                                  ps_p2d.xy, ps_p2d.yy,
3465                                  ps_p2d.x0, ps_p2d.y0);
3466     _cairo_output_stream_printf (surface->stream,
3467                                  "makepattern setpattern\n");
3468
3469   release_source:
3470     if (image)
3471         cairo_surface_destroy (&image->base);
3472
3473     _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra);
3474
3475     return status;
3476 }
3477
3478 typedef struct _cairo_ps_color_stop {
3479     double offset;
3480     double color[4];
3481 } cairo_ps_color_stop_t;
3482
3483 static void
3484 _cairo_ps_surface_emit_linear_colorgradient (cairo_ps_surface_t     *surface,
3485                                              cairo_ps_color_stop_t  *stop1,
3486                                              cairo_ps_color_stop_t  *stop2)
3487 {
3488     _cairo_output_stream_printf (surface->stream,
3489                                  "   << /FunctionType 2\n"
3490                                  "      /Domain [ 0 1 ]\n"
3491                                  "      /C0 [ %f %f %f ]\n"
3492                                  "      /C1 [ %f %f %f ]\n"
3493                                  "      /N 1\n"
3494                                  "   >>\n",
3495                                  stop1->color[0],
3496                                  stop1->color[1],
3497                                  stop1->color[2],
3498                                  stop2->color[0],
3499                                  stop2->color[1],
3500                                  stop2->color[2]);
3501 }
3502
3503 static void
3504 _cairo_ps_surface_emit_stitched_colorgradient (cairo_ps_surface_t    *surface,
3505                                                unsigned int           n_stops,
3506                                                cairo_ps_color_stop_t  stops[])
3507 {
3508     unsigned int i;
3509
3510     _cairo_output_stream_printf (surface->stream,
3511                                  "<< /FunctionType 3\n"
3512                                  "   /Domain [ 0 1 ]\n"
3513                                  "   /Functions [\n");
3514     for (i = 0; i < n_stops - 1; i++)
3515         _cairo_ps_surface_emit_linear_colorgradient (surface, &stops[i], &stops[i+1]);
3516
3517     _cairo_output_stream_printf (surface->stream, "   ]\n");
3518
3519     _cairo_output_stream_printf (surface->stream, "   /Bounds [ ");
3520     for (i = 1; i < n_stops-1; i++)
3521         _cairo_output_stream_printf (surface->stream, "%f ", stops[i].offset);
3522     _cairo_output_stream_printf (surface->stream, "]\n");
3523
3524     _cairo_output_stream_printf (surface->stream, "   /Encode [ 1 1 %d { pop 0 1 } for ]\n",
3525                                  n_stops - 1);
3526
3527     _cairo_output_stream_printf (surface->stream, ">>\n");
3528 }
3529
3530 static void
3531 calc_gradient_color (cairo_ps_color_stop_t *new_stop,
3532                      cairo_ps_color_stop_t *stop1,
3533                      cairo_ps_color_stop_t *stop2)
3534 {
3535     int i;
3536     double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
3537
3538     for (i = 0; i < 4; i++)
3539         new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
3540 }
3541
3542 #define COLOR_STOP_EPSILON 1e-6
3543
3544 static cairo_status_t
3545 _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t       *surface,
3546                                       cairo_gradient_pattern_t *pattern)
3547 {
3548     cairo_ps_color_stop_t *allstops, *stops;
3549     unsigned int i, n_stops;
3550
3551     allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_ps_color_stop_t));
3552     if (unlikely (allstops == NULL))
3553         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3554
3555     stops = &allstops[1];
3556     n_stops = pattern->n_stops;
3557
3558     for (i = 0; i < n_stops; i++) {
3559         cairo_gradient_stop_t *stop = &pattern->stops[i];
3560
3561         stops[i].color[0] = stop->color.red;
3562         stops[i].color[1] = stop->color.green;
3563         stops[i].color[2] = stop->color.blue;
3564         stops[i].color[3] = stop->color.alpha;
3565         stops[i].offset = pattern->stops[i].offset;
3566     }
3567
3568     if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
3569         pattern->base.extend == CAIRO_EXTEND_REFLECT)
3570     {
3571         if (stops[0].offset > COLOR_STOP_EPSILON) {
3572             if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
3573                 memcpy (allstops, stops, sizeof (cairo_ps_color_stop_t));
3574             else
3575                 calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
3576             stops = allstops;
3577             n_stops++;
3578         }
3579         stops[0].offset = 0.0;
3580
3581         if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
3582             if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
3583                 memcpy (&stops[n_stops],
3584                         &stops[n_stops - 1],
3585                         sizeof (cairo_ps_color_stop_t));
3586             } else {
3587                 calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
3588             }
3589             n_stops++;
3590         }
3591         stops[n_stops-1].offset = 1.0;
3592     }
3593
3594     for (i = 0; i < n_stops; i++) {
3595         double red, green, blue;
3596         cairo_color_t color;
3597
3598         _cairo_color_init_rgba (&color,
3599                                 stops[i].color[0],
3600                                 stops[i].color[1],
3601                                 stops[i].color[2],
3602                                 stops[i].color[3]);
3603         _cairo_ps_surface_flatten_transparency (surface, &color,
3604                                                 &red, &green, &blue);
3605         stops[i].color[0] = red;
3606         stops[i].color[1] = green;
3607         stops[i].color[2] = blue;
3608     }
3609
3610     _cairo_output_stream_printf (surface->stream,
3611                                  "/CairoFunction\n");
3612     if (stops[0].offset == stops[n_stops - 1].offset) {
3613         /*
3614          * The first and the last stops have the same offset, but we
3615          * don't want a function with an empty domain, because that
3616          * would provoke underdefined behaviour from rasterisers.
3617          * This can only happen with EXTEND_PAD, because EXTEND_NONE
3618          * is optimised into a clear pattern in cairo-gstate, and
3619          * REFLECT/REPEAT are always transformed to have the first
3620          * stop at t=0 and the last stop at t=1.  Thus we want a step
3621          * function going from the first color to the last one.
3622          *
3623          * This can be accomplished by stitching three functions:
3624          *  - a constant first color function,
3625          *  - a step from the first color to the last color (with empty domain)
3626          *  - a constant last color function
3627          */
3628         cairo_ps_color_stop_t pad_stops[4];
3629
3630         assert (pattern->base.extend == CAIRO_EXTEND_PAD);
3631
3632         pad_stops[0] = pad_stops[1] = stops[0];
3633         pad_stops[2] = pad_stops[3] = stops[n_stops - 1];
3634
3635         pad_stops[0].offset = 0;
3636         pad_stops[3].offset = 1;
3637
3638         _cairo_ps_surface_emit_stitched_colorgradient (surface, 4, pad_stops);
3639     } else if (n_stops == 2) {
3640         /* no need for stitched function */
3641         _cairo_ps_surface_emit_linear_colorgradient (surface, &stops[0], &stops[1]);
3642     } else {
3643         /* multiple stops: stitch. XXX possible optimization: regulary spaced
3644          * stops do not require stitching. XXX */
3645         _cairo_ps_surface_emit_stitched_colorgradient (surface, n_stops, stops);
3646     }
3647     _cairo_output_stream_printf (surface->stream,
3648                                  "def\n");
3649
3650     free (allstops);
3651
3652     return CAIRO_STATUS_SUCCESS;
3653 }
3654
3655 static cairo_status_t
3656 _cairo_ps_surface_emit_repeating_function (cairo_ps_surface_t       *surface,
3657                                            cairo_gradient_pattern_t *pattern,
3658                                            int                       begin,
3659                                            int                       end)
3660 {
3661     _cairo_output_stream_printf (surface->stream,
3662                                  "/CairoFunction\n"
3663                                  "<< /FunctionType 3\n"
3664                                  "   /Domain [ %d %d ]\n"
3665                                  "   /Functions [ %d {CairoFunction} repeat ]\n"
3666                                  "   /Bounds [ %d 1 %d {} for ]\n",
3667                                  begin,
3668                                  end,
3669                                  end - begin,
3670                                  begin + 1,
3671                                  end - 1);
3672
3673     if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
3674         _cairo_output_stream_printf (surface->stream, "   /Encode [ %d 1 %d { 2 mod 0 eq {0 1} {1 0} ifelse } for ]\n",
3675                                      begin,
3676                                      end - 1);
3677     } else {
3678         _cairo_output_stream_printf (surface->stream, "   /Encode [ %d 1 %d { pop 0 1 } for ]\n",
3679                                      begin,
3680                                      end - 1);
3681     }
3682
3683     _cairo_output_stream_printf (surface->stream, ">> def\n");
3684
3685     return CAIRO_STATUS_SUCCESS;
3686 }
3687
3688 static cairo_status_t
3689 _cairo_ps_surface_emit_gradient (cairo_ps_surface_t       *surface,
3690                                  cairo_gradient_pattern_t *pattern,
3691                                  cairo_bool_t              is_ps_pattern)
3692 {
3693     cairo_matrix_t pat_to_ps;
3694     cairo_circle_double_t start, end;
3695     double domain[2];
3696     cairo_status_t status;
3697
3698     assert (pattern->n_stops != 0);
3699
3700     status = _cairo_ps_surface_emit_pattern_stops (surface, pattern);
3701     if (unlikely (status))
3702         return status;
3703
3704     pat_to_ps = pattern->base.matrix;
3705     status = cairo_matrix_invert (&pat_to_ps);
3706     /* cairo_pattern_set_matrix ensures the matrix is invertible */
3707     assert (status == CAIRO_STATUS_SUCCESS);
3708     cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps);
3709
3710     if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
3711         pattern->base.extend == CAIRO_EXTEND_REFLECT)
3712     {
3713         double bounds_x1, bounds_x2, bounds_y1, bounds_y2;
3714         double x_scale, y_scale, tolerance;
3715
3716         /* TODO: use tighter extents */
3717         bounds_x1 = 0;
3718         bounds_y1 = 0;
3719         bounds_x2 = surface->width;
3720         bounds_y2 = surface->height;
3721         _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
3722                                               &bounds_x1, &bounds_y1,
3723                                               &bounds_x2, &bounds_y2,
3724                                               NULL);
3725
3726         x_scale = surface->base.x_resolution / surface->base.x_fallback_resolution;
3727         y_scale = surface->base.y_resolution / surface->base.y_fallback_resolution;
3728
3729         tolerance = fabs (_cairo_matrix_compute_determinant (&pattern->base.matrix));
3730         tolerance /= _cairo_matrix_transformed_circle_major_axis (&pattern->base.matrix, 1);
3731         tolerance *= MIN (x_scale, y_scale);
3732
3733         _cairo_gradient_pattern_box_to_parameter (pattern,
3734                                                   bounds_x1, bounds_y1,
3735                                                   bounds_x2, bounds_y2,
3736                                                   tolerance, domain);
3737     } else if (pattern->stops[0].offset == pattern->stops[pattern->n_stops - 1].offset) {
3738         /*
3739          * If the first and the last stop offset are the same, then
3740          * the color function is a step function.
3741          * _cairo_ps_surface_emit_pattern_stops emits it as a stitched
3742          * function no matter how many stops the pattern has.  The
3743          * domain of the stitched function will be [0 1] in this case.
3744          *
3745          * This is done to avoid emitting degenerate gradients for
3746          * EXTEND_PAD patterns having a step color function.
3747          */
3748         domain[0] = 0.0;
3749         domain[1] = 1.0;
3750
3751         assert (pattern->base.extend == CAIRO_EXTEND_PAD);
3752     } else {
3753         domain[0] = pattern->stops[0].offset;
3754         domain[1] = pattern->stops[pattern->n_stops - 1].offset;
3755     }
3756
3757     /* PS requires the first and last stop to be the same as the
3758      * extreme coordinates. For repeating patterns this moves the
3759      * extreme coordinates out to the begin/end of the repeating
3760      * function. For non repeating patterns this may move the extreme
3761      * coordinates in if there are not stops at offset 0 and 1. */
3762     _cairo_gradient_pattern_interpolate (pattern, domain[0], &start);
3763     _cairo_gradient_pattern_interpolate (pattern, domain[1], &end);
3764
3765     if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
3766         pattern->base.extend == CAIRO_EXTEND_REFLECT)
3767     {
3768         int repeat_begin, repeat_end;
3769
3770         repeat_begin = floor (domain[0]);
3771         repeat_end = ceil (domain[1]);
3772
3773         status = _cairo_ps_surface_emit_repeating_function (surface,
3774                                                             pattern,
3775                                                             repeat_begin,
3776                                                             repeat_end);
3777         if (unlikely (status))
3778             return status;
3779     } else if (pattern->n_stops <= 2) {
3780         /* For EXTEND_NONE and EXTEND_PAD if there are only two stops a
3781          * Type 2 function is used by itself without a stitching
3782          * function. Type 2 functions always have the domain [0 1] */
3783         domain[0] = 0.0;
3784         domain[1] = 1.0;
3785     }
3786
3787     if (is_ps_pattern) {
3788         _cairo_output_stream_printf (surface->stream,
3789                                      "<< /PatternType 2\n"
3790                                      "   /Shading\n");
3791     }
3792
3793     if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
3794         _cairo_output_stream_printf (surface->stream,
3795                                      "   << /ShadingType 2\n"
3796                                      "      /ColorSpace /DeviceRGB\n"
3797                                      "      /Coords [ %f %f %f %f ]\n",
3798                                      start.center.x, start.center.y,
3799                                      end.center.x, end.center.y);
3800     } else {
3801         _cairo_output_stream_printf (surface->stream,
3802                                      "   << /ShadingType 3\n"
3803                                      "      /ColorSpace /DeviceRGB\n"
3804                                      "      /Coords [ %f %f %f %f %f %f ]\n",
3805                                      start.center.x, start.center.y,
3806                                      MAX (start.radius, 0),
3807                                      end.center.x, end.center.y,
3808                                      MAX (end.radius, 0));
3809     }
3810
3811     if (pattern->base.extend != CAIRO_EXTEND_NONE) {
3812         _cairo_output_stream_printf (surface->stream,
3813                                      "      /Extend [ true true ]\n");
3814     } else {
3815         _cairo_output_stream_printf (surface->stream,
3816                                      "      /Extend [ false false ]\n");
3817     }
3818
3819     if (domain[0] == 0.0 && domain[1] == 1.0) {
3820         _cairo_output_stream_printf (surface->stream,
3821                                      "      /Function CairoFunction\n");
3822     } else {
3823         _cairo_output_stream_printf (surface->stream,
3824                                      "      /Function <<\n"
3825                                      "         /FunctionType 3\n"
3826                                      "         /Domain [ 0 1 ]\n"
3827                                      "         /Bounds [ ]\n"
3828                                      "         /Encode [ %f %f ]\n"
3829                                      "         /Functions [ CairoFunction ]\n"
3830                                      "      >>\n",
3831                                      domain[0], domain[1]);
3832     }
3833
3834     _cairo_output_stream_printf (surface->stream,
3835                                  "   >>\n");
3836
3837     if (is_ps_pattern) {
3838         _cairo_output_stream_printf (surface->stream,
3839                                      ">>\n"
3840                                      "[ %f %f %f %f %f %f ]\n"
3841                                      "makepattern setpattern\n",
3842                                      pat_to_ps.xx, pat_to_ps.yx,
3843                                      pat_to_ps.xy, pat_to_ps.yy,
3844                                      pat_to_ps.x0, pat_to_ps.y0);
3845     } else {
3846         _cairo_output_stream_printf (surface->stream,
3847                                      "shfill\n");
3848     }
3849
3850     return status;
3851 }
3852
3853 static cairo_status_t
3854 _cairo_ps_surface_emit_mesh_pattern (cairo_ps_surface_t     *surface,
3855                                      cairo_mesh_pattern_t   *pattern,
3856                                      cairo_bool_t            is_ps_pattern)
3857 {
3858     cairo_matrix_t pat_to_ps;
3859     cairo_status_t status;
3860     cairo_pdf_shading_t shading;
3861     int i;
3862
3863     if (_cairo_array_num_elements (&pattern->patches) == 0)
3864         return CAIRO_INT_STATUS_NOTHING_TO_DO;
3865
3866     pat_to_ps = pattern->base.matrix;
3867     status = cairo_matrix_invert (&pat_to_ps);
3868     /* cairo_pattern_set_matrix ensures the matrix is invertible */
3869     assert (status == CAIRO_STATUS_SUCCESS);
3870
3871     cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps);
3872
3873     status = _cairo_pdf_shading_init_color (&shading, pattern);
3874     if (unlikely (status))
3875         return status;
3876
3877     _cairo_output_stream_printf (surface->stream,
3878                                  "currentfile\n"
3879                                  "/ASCII85Decode filter /FlateDecode filter /ReusableStreamDecode filter\n");
3880
3881     status = _cairo_ps_surface_emit_base85_string (surface,
3882                                                    shading.data,
3883                                                    shading.data_length,
3884                                                    CAIRO_PS_COMPRESS_DEFLATE,
3885                                                    FALSE);
3886     if (status)
3887         return status;
3888
3889     _cairo_output_stream_printf (surface->stream,
3890                                  "\n"
3891                                  "/CairoData exch def\n");
3892
3893     if (is_ps_pattern) {
3894         _cairo_output_stream_printf (surface->stream,
3895                                      "<< /PatternType 2\n"
3896                                      "   /Shading\n");
3897     }
3898
3899     _cairo_output_stream_printf (surface->stream,
3900                                  "   << /ShadingType %d\n"
3901                                  "      /ColorSpace /DeviceRGB\n"
3902                                  "      /DataSource CairoData\n"
3903                                  "      /BitsPerCoordinate %d\n"
3904                                  "      /BitsPerComponent %d\n"
3905                                  "      /BitsPerFlag %d\n"
3906                                  "      /Decode [",
3907                                  shading.shading_type,
3908                                  shading.bits_per_coordinate,
3909                                  shading.bits_per_component,
3910                                  shading.bits_per_flag);
3911
3912     for (i = 0; i < shading.decode_array_length; i++)
3913         _cairo_output_stream_printf (surface->stream, "%f ", shading.decode_array[i]);
3914
3915     _cairo_output_stream_printf (surface->stream,
3916                                  "]\n"
3917                                  "   >>\n");
3918
3919     if (is_ps_pattern) {
3920         _cairo_output_stream_printf (surface->stream,
3921                                      ">>\n"
3922                                      "[ %f %f %f %f %f %f ]\n",
3923                                      pat_to_ps.xx, pat_to_ps.yx,
3924                                      pat_to_ps.xy, pat_to_ps.yy,
3925                                      pat_to_ps.x0, pat_to_ps.y0);
3926         _cairo_output_stream_printf (surface->stream,
3927                                      "makepattern\n"
3928                                      "setpattern\n");
3929     } else {
3930         _cairo_output_stream_printf (surface->stream, "shfill\n");
3931     }
3932
3933     _cairo_output_stream_printf (surface->stream,
3934                                  "currentdict /CairoData undef\n");
3935
3936     _cairo_pdf_shading_fini (&shading);
3937
3938     return status;
3939 }
3940
3941 static cairo_status_t
3942 _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
3943                                 const cairo_pattern_t *pattern,
3944                                 cairo_rectangle_int_t *extents,
3945                                 cairo_operator_t       op)
3946 {
3947     cairo_status_t status;
3948
3949     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
3950         cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
3951
3952         if (surface->current_pattern_is_solid_color == FALSE ||
3953             ! _cairo_color_equal (&surface->current_color, &solid->color))
3954         {
3955             status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3956             if (unlikely (status))
3957                 return status;
3958
3959             _cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
3960
3961             surface->current_pattern_is_solid_color = TRUE;
3962             surface->current_color = solid->color;
3963         }
3964
3965         return CAIRO_STATUS_SUCCESS;
3966     }
3967
3968     surface->current_pattern_is_solid_color = FALSE;
3969     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
3970     if (unlikely (status))
3971             return status;
3972
3973     switch (pattern->type) {
3974     case CAIRO_PATTERN_TYPE_SOLID:
3975
3976         _cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
3977         break;
3978
3979     case CAIRO_PATTERN_TYPE_SURFACE:
3980     case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3981         status = _cairo_ps_surface_emit_surface_pattern (surface,
3982                                                          (cairo_pattern_t *)pattern,
3983                                                          extents,
3984                                                          op);
3985         if (unlikely (status))
3986             return status;
3987         break;
3988
3989     case CAIRO_PATTERN_TYPE_LINEAR:
3990     case CAIRO_PATTERN_TYPE_RADIAL:
3991         status = _cairo_ps_surface_emit_gradient (surface,
3992                                                   (cairo_gradient_pattern_t *) pattern,
3993                                                   TRUE);
3994         if (unlikely (status))
3995             return status;
3996         break;
3997
3998     case CAIRO_PATTERN_TYPE_MESH:
3999         status = _cairo_ps_surface_emit_mesh_pattern (surface,
4000                                                       (cairo_mesh_pattern_t *) pattern,
4001                                                       TRUE);
4002         if (unlikely (status))
4003             return status;
4004         break;
4005     }
4006
4007     return CAIRO_STATUS_SUCCESS;
4008 }
4009
4010 static cairo_status_t
4011 _cairo_ps_surface_paint_gradient (cairo_ps_surface_t          *surface,
4012                                   const cairo_pattern_t       *source,
4013                                   const cairo_rectangle_int_t *extents)
4014 {
4015     cairo_matrix_t pat_to_ps;
4016     cairo_status_t status;
4017
4018     pat_to_ps = source->matrix;
4019     status = cairo_matrix_invert (&pat_to_ps);
4020     /* cairo_pattern_set_matrix ensures the matrix is invertible */
4021     assert (status == CAIRO_STATUS_SUCCESS);
4022     cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps);
4023
4024     if (! _cairo_matrix_is_identity (&pat_to_ps)) {
4025         _cairo_output_stream_printf (surface->stream,
4026                                      "[%f %f %f %f %f %f] concat\n",
4027                                      pat_to_ps.xx, pat_to_ps.yx,
4028                                      pat_to_ps.xy, pat_to_ps.yy,
4029                                      pat_to_ps.x0, pat_to_ps.y0);
4030     }
4031
4032     if (source->type == CAIRO_PATTERN_TYPE_MESH) {
4033         status = _cairo_ps_surface_emit_mesh_pattern (surface,
4034                                                       (cairo_mesh_pattern_t *)source,
4035                                                       FALSE);
4036         if (unlikely (status))
4037             return status;
4038     } else {
4039         status = _cairo_ps_surface_emit_gradient (surface,
4040                                                   (cairo_gradient_pattern_t *)source,
4041                                                   FALSE);
4042         if (unlikely (status))
4043             return status;
4044     }
4045
4046     return status;
4047 }
4048
4049 static cairo_status_t
4050 _cairo_ps_surface_paint_pattern (cairo_ps_surface_t           *surface,
4051                                  const cairo_pattern_t        *source,
4052                                  cairo_rectangle_int_t        *extents,
4053                                  cairo_operator_t              op,
4054                                  cairo_bool_t                  stencil_mask)
4055 {
4056     switch (source->type) {
4057     case CAIRO_PATTERN_TYPE_SURFACE:
4058     case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4059        return _cairo_ps_surface_paint_surface (surface,
4060                                                (cairo_pattern_t *)source,
4061                                                extents,
4062                                                op,
4063                                                stencil_mask);
4064
4065     case CAIRO_PATTERN_TYPE_LINEAR:
4066     case CAIRO_PATTERN_TYPE_RADIAL:
4067     case CAIRO_PATTERN_TYPE_MESH:
4068         return _cairo_ps_surface_paint_gradient (surface,
4069                                                   source,
4070                                                   extents);
4071
4072     case CAIRO_PATTERN_TYPE_SOLID:
4073     default:
4074        ASSERT_NOT_REACHED;
4075        return CAIRO_STATUS_SUCCESS;
4076     }
4077 }
4078
4079 static cairo_bool_t
4080 _can_paint_pattern (const cairo_pattern_t *pattern)
4081 {
4082     switch (pattern->type) {
4083     case CAIRO_PATTERN_TYPE_SOLID:
4084         return FALSE;
4085
4086     case CAIRO_PATTERN_TYPE_SURFACE:
4087     case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4088         return (pattern->extend == CAIRO_EXTEND_NONE ||
4089                 pattern->extend == CAIRO_EXTEND_PAD);
4090
4091     case CAIRO_PATTERN_TYPE_LINEAR:
4092     case CAIRO_PATTERN_TYPE_RADIAL:
4093     case CAIRO_PATTERN_TYPE_MESH:
4094         return TRUE;
4095
4096     default:
4097         ASSERT_NOT_REACHED;
4098         return FALSE;
4099     }
4100 }
4101
4102 static cairo_bool_t
4103 _cairo_ps_surface_get_extents (void                    *abstract_surface,
4104                                cairo_rectangle_int_t   *rectangle)
4105 {
4106     cairo_ps_surface_t *surface = abstract_surface;
4107
4108     rectangle->x = 0;
4109     rectangle->y = 0;
4110
4111     /* XXX: The conversion to integers here is pretty bogus, (not to
4112      * mention the aribitray limitation of width to a short(!). We
4113      * may need to come up with a better interface for get_extents.
4114      */
4115     rectangle->width  = ceil (surface->width);
4116     rectangle->height = ceil (surface->height);
4117
4118     return TRUE;
4119 }
4120
4121 static void
4122 _cairo_ps_surface_get_font_options (void                  *abstract_surface,
4123                                     cairo_font_options_t  *options)
4124 {
4125     _cairo_font_options_init_default (options);
4126
4127     cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
4128     cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
4129     cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
4130     _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_OFF);
4131 }
4132
4133 static cairo_int_status_t
4134 _cairo_ps_surface_set_clip (cairo_ps_surface_t *surface,
4135                             cairo_composite_rectangles_t *composite)
4136 {
4137     cairo_clip_t *clip = composite->clip;
4138
4139     if (_cairo_composite_rectangles_can_reduce_clip (composite, clip))
4140         clip = NULL;
4141
4142     if (clip == NULL) {
4143         if (_cairo_composite_rectangles_can_reduce_clip (composite,
4144                                                          surface->clipper.clip))
4145             return CAIRO_STATUS_SUCCESS;
4146     }
4147
4148     return _cairo_surface_clipper_set_clip (&surface->clipper, clip);
4149 }
4150
4151 static cairo_int_status_t
4152 _cairo_ps_surface_paint (void                   *abstract_surface,
4153                          cairo_operator_t        op,
4154                          const cairo_pattern_t  *source,
4155                          const cairo_clip_t     *clip)
4156 {
4157     cairo_ps_surface_t *surface = abstract_surface;
4158     cairo_output_stream_t *stream = surface->stream;
4159     cairo_composite_rectangles_t extents;
4160     cairo_status_t status;
4161
4162     status = _cairo_composite_rectangles_init_for_paint (&extents,
4163                                                          &surface->base,
4164                                                          op, source, clip);
4165     if (unlikely (status))
4166         return status;
4167
4168     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
4169         status = _cairo_ps_surface_analyze_operation (surface, op, source, NULL, &extents.bounded);
4170         goto cleanup_composite;
4171     }
4172
4173     assert (_cairo_ps_surface_operation_supported (surface, op, source, NULL, &extents.bounded));
4174
4175 #if DEBUG_PS
4176     _cairo_output_stream_printf (stream,
4177                                  "%% _cairo_ps_surface_paint\n");
4178 #endif
4179
4180     status = _cairo_ps_surface_set_clip (surface, &extents);
4181     if (unlikely (status))
4182         goto cleanup_composite;
4183
4184     if (_can_paint_pattern (source)) {
4185         status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4186         if (unlikely (status))
4187             goto cleanup_composite;
4188
4189         _cairo_output_stream_printf (stream, "q\n");
4190         status = _cairo_ps_surface_paint_pattern (surface,
4191                                                   source,
4192                                                   &extents.bounded, op, FALSE);
4193         if (unlikely (status))
4194             goto cleanup_composite;
4195
4196         _cairo_output_stream_printf (stream, "Q\n");
4197     } else {
4198         status = _cairo_ps_surface_emit_pattern (surface, source, &extents.bounded, op);
4199         if (unlikely (status))
4200             goto cleanup_composite;
4201
4202         _cairo_output_stream_printf (stream, "0 0 %f %f rectfill\n",
4203                                      surface->width, surface->height);
4204     }
4205
4206 cleanup_composite:
4207     _cairo_composite_rectangles_fini (&extents);
4208     return status;
4209 }
4210
4211 static cairo_int_status_t
4212 _cairo_ps_surface_mask (void                    *abstract_surface,
4213                         cairo_operator_t         op,
4214                         const cairo_pattern_t   *source,
4215                         const cairo_pattern_t   *mask,
4216                         const cairo_clip_t      *clip)
4217 {
4218     cairo_ps_surface_t *surface = abstract_surface;
4219     cairo_output_stream_t *stream = surface->stream;
4220     cairo_composite_rectangles_t extents;
4221     cairo_status_t status;
4222
4223     status = _cairo_composite_rectangles_init_for_mask (&extents,
4224                                                         &surface->base,
4225                                                         op, source, mask, clip);
4226     if (unlikely (status))
4227         return status;
4228
4229     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
4230         status = _cairo_ps_surface_analyze_operation (surface, op, source, mask, &extents.bounded);
4231         goto cleanup_composite;
4232     }
4233
4234     assert (_cairo_ps_surface_operation_supported (surface, op, source, mask, &extents.bounded));
4235
4236 #if DEBUG_PS
4237     _cairo_output_stream_printf (stream,
4238                                  "%% _cairo_ps_surface_mask\n");
4239 #endif
4240
4241     status = _cairo_ps_surface_set_clip (surface, &extents);
4242     if (unlikely (status))
4243         goto cleanup_composite;
4244
4245     status = _cairo_ps_surface_emit_pattern (surface, source, &extents.bounded, op);
4246     if (unlikely (status))
4247         goto cleanup_composite;
4248
4249     _cairo_output_stream_printf (stream, "q\n");
4250     status = _cairo_ps_surface_paint_pattern (surface,
4251                                               mask,
4252                                               &extents.bounded, op, TRUE);
4253     if (unlikely (status))
4254         goto cleanup_composite;
4255
4256     _cairo_output_stream_printf (stream, "Q\n");
4257
4258 cleanup_composite:
4259     _cairo_composite_rectangles_fini (&extents);
4260     return status;
4261 }
4262
4263 static cairo_int_status_t
4264 _cairo_ps_surface_stroke (void                  *abstract_surface,
4265                           cairo_operator_t       op,
4266                           const cairo_pattern_t *source,
4267                           const cairo_path_fixed_t      *path,
4268                           const cairo_stroke_style_t    *style,
4269                           const cairo_matrix_t  *ctm,
4270                           const cairo_matrix_t  *ctm_inverse,
4271                           double                 tolerance,
4272                           cairo_antialias_t      antialias,
4273                           const cairo_clip_t            *clip)
4274 {
4275     cairo_ps_surface_t *surface = abstract_surface;
4276     cairo_composite_rectangles_t extents;
4277     cairo_int_status_t status;
4278
4279     status = _cairo_composite_rectangles_init_for_stroke (&extents,
4280                                                           &surface->base,
4281                                                           op, source,
4282                                                           path, style, ctm,
4283                                                           clip);
4284     if (unlikely (status))
4285         return status;
4286
4287     /* use the more accurate extents */
4288     {
4289         cairo_rectangle_int_t r;
4290         cairo_box_t b;
4291
4292         status = _cairo_path_fixed_stroke_extents (path, style,
4293                                                    ctm, ctm_inverse,
4294                                                    tolerance,
4295                                                    &r);
4296         if (unlikely (status))
4297             goto cleanup_composite;
4298
4299         _cairo_box_from_rectangle (&b, &r);
4300         status = _cairo_composite_rectangles_intersect_mask_extents (&extents, &b);
4301         if (unlikely (status))
4302             goto cleanup_composite;
4303     }
4304
4305     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
4306         status = _cairo_ps_surface_analyze_operation (surface, op, source, NULL, &extents.bounded);
4307         goto cleanup_composite;
4308     }
4309
4310     assert (_cairo_ps_surface_operation_supported (surface, op, source, NULL, &extents.bounded));
4311
4312 #if DEBUG_PS
4313     _cairo_output_stream_printf (surface->stream,
4314                                  "%% _cairo_ps_surface_stroke\n");
4315 #endif
4316
4317     status = _cairo_ps_surface_set_clip (surface, &extents);
4318     if (unlikely (status))
4319         goto cleanup_composite;
4320
4321     status = _cairo_ps_surface_emit_pattern (surface, source, &extents.bounded, op);
4322     if (unlikely (status))
4323         goto cleanup_composite;
4324
4325     status = _cairo_pdf_operators_stroke (&surface->pdf_operators,
4326                                           path,
4327                                           style,
4328                                           ctm,
4329                                           ctm_inverse);
4330
4331 cleanup_composite:
4332     _cairo_composite_rectangles_fini (&extents);
4333     return status;
4334 }
4335
4336 static cairo_int_status_t
4337 _cairo_ps_surface_fill (void            *abstract_surface,
4338                         cairo_operator_t         op,
4339                         const cairo_pattern_t   *source,
4340                         const cairo_path_fixed_t*path,
4341                         cairo_fill_rule_t        fill_rule,
4342                         double                   tolerance,
4343                         cairo_antialias_t        antialias,
4344                         const cairo_clip_t              *clip)
4345 {
4346     cairo_ps_surface_t *surface = abstract_surface;
4347     cairo_composite_rectangles_t extents;
4348     cairo_int_status_t status;
4349
4350     status = _cairo_composite_rectangles_init_for_fill (&extents,
4351                                                         &surface->base,
4352                                                         op, source, path,
4353                                                         clip);
4354     if (unlikely (status))
4355         return status;
4356
4357     /* use the more accurate extents */
4358     {
4359         cairo_rectangle_int_t r;
4360         cairo_box_t b;
4361
4362         _cairo_path_fixed_fill_extents (path,
4363                                         fill_rule,
4364                                         tolerance,
4365                                         &r);
4366
4367         _cairo_box_from_rectangle (&b, &r);
4368         status = _cairo_composite_rectangles_intersect_mask_extents (&extents, &b);
4369         if (unlikely (status))
4370             goto cleanup_composite;
4371     }
4372
4373     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
4374         status = _cairo_ps_surface_analyze_operation (surface, op, source, NULL, &extents.bounded);
4375         goto cleanup_composite;
4376     }
4377
4378     assert (_cairo_ps_surface_operation_supported (surface, op, source, NULL, &extents.bounded));
4379
4380 #if DEBUG_PS
4381     _cairo_output_stream_printf (surface->stream,
4382                                  "%% _cairo_ps_surface_fill\n");
4383 #endif
4384
4385     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4386     if (unlikely (status))
4387         goto cleanup_composite;
4388
4389     status = _cairo_ps_surface_set_clip (surface, &extents);
4390     if (unlikely (status))
4391         goto cleanup_composite;
4392
4393     if (_can_paint_pattern (source)) {
4394         _cairo_output_stream_printf (surface->stream, "q\n");
4395
4396         status =  _cairo_pdf_operators_clip (&surface->pdf_operators,
4397                                              path,
4398                                              fill_rule);
4399         if (unlikely (status))
4400             goto cleanup_composite;
4401
4402         status = _cairo_ps_surface_paint_pattern (surface,
4403                                                   source,
4404                                                   &extents.bounded, op, FALSE);
4405         if (unlikely (status))
4406             goto cleanup_composite;
4407
4408         _cairo_output_stream_printf (surface->stream, "Q\n");
4409         _cairo_pdf_operators_reset (&surface->pdf_operators);
4410     } else {
4411         status = _cairo_ps_surface_emit_pattern (surface, source, &extents.bounded, op);
4412         if (unlikely (status))
4413             goto cleanup_composite;
4414
4415         status = _cairo_pdf_operators_fill (&surface->pdf_operators,
4416                                             path,
4417                                             fill_rule);
4418     }
4419
4420 cleanup_composite:
4421     _cairo_composite_rectangles_fini (&extents);
4422     return status;
4423 }
4424
4425 static cairo_bool_t
4426 _cairo_ps_surface_has_show_text_glyphs  (void                   *abstract_surface)
4427 {
4428     return TRUE;
4429 }
4430
4431 static cairo_int_status_t
4432 _cairo_ps_surface_show_text_glyphs (void                       *abstract_surface,
4433                                     cairo_operator_t            op,
4434                                     const cairo_pattern_t      *source,
4435                                     const char                 *utf8,
4436                                     int                         utf8_len,
4437                                     cairo_glyph_t              *glyphs,
4438                                     int                         num_glyphs,
4439                                     const cairo_text_cluster_t *clusters,
4440                                     int                         num_clusters,
4441                                     cairo_text_cluster_flags_t  cluster_flags,
4442                                     cairo_scaled_font_t        *scaled_font,
4443                                     const cairo_clip_t         *clip)
4444 {
4445     cairo_ps_surface_t *surface = abstract_surface;
4446     cairo_composite_rectangles_t extents;
4447     cairo_bool_t overlap;
4448     cairo_status_t status;
4449
4450     status = _cairo_composite_rectangles_init_for_glyphs (&extents,
4451                                                           &surface->base,
4452                                                           op, source,
4453                                                           scaled_font,
4454                                                           glyphs, num_glyphs,
4455                                                           clip,
4456                                                           &overlap);
4457     if (unlikely (status))
4458         return status;
4459
4460     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
4461         status = _cairo_ps_surface_analyze_operation (surface, op, source, NULL, &extents.bounded);
4462         goto cleanup_composite;
4463     }
4464
4465     assert (_cairo_ps_surface_operation_supported (surface, op, source, NULL, &extents.bounded));
4466
4467 #if DEBUG_PS
4468     _cairo_output_stream_printf (surface->stream,
4469                                  "%% _cairo_ps_surface_show_glyphs\n");
4470 #endif
4471
4472     status = _cairo_ps_surface_set_clip (surface, &extents);
4473     if (unlikely (status))
4474         goto cleanup_composite;
4475
4476     status = _cairo_ps_surface_emit_pattern (surface, source, &extents.bounded, op);
4477     if (unlikely (status))
4478         goto cleanup_composite;
4479
4480     status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
4481                                                     utf8, utf8_len,
4482                                                     glyphs, num_glyphs,
4483                                                     clusters, num_clusters,
4484                                                     cluster_flags,
4485                                                     scaled_font);
4486
4487 cleanup_composite:
4488     _cairo_composite_rectangles_fini (&extents);
4489     return status;
4490 }
4491
4492 static const char **
4493 _cairo_ps_surface_get_supported_mime_types (void                 *abstract_surface)
4494 {
4495     return _cairo_ps_supported_mime_types;
4496 }
4497
4498 static void
4499 _cairo_ps_surface_set_paginated_mode (void                      *abstract_surface,
4500                                       cairo_paginated_mode_t     paginated_mode)
4501 {
4502     cairo_ps_surface_t *surface = abstract_surface;
4503     cairo_status_t status;
4504
4505     surface->paginated_mode = paginated_mode;
4506
4507     if (surface->clipper.clip != NULL) {
4508         status = _cairo_pdf_operators_flush (&surface->pdf_operators);
4509
4510         _cairo_output_stream_printf (surface->stream, "Q q\n");
4511         _cairo_surface_clipper_reset (&surface->clipper);
4512     }
4513 }
4514
4515 static cairo_int_status_t
4516 _cairo_ps_surface_set_bounding_box (void                *abstract_surface,
4517                                     cairo_box_t         *bbox)
4518 {
4519     cairo_ps_surface_t *surface = abstract_surface;
4520     int i, num_comments;
4521     char **comments;
4522     int x1, y1, x2, y2;
4523     cairo_bool_t has_page_media, has_page_bbox;
4524     const char *page_media;
4525
4526     x1 = floor (_cairo_fixed_to_double (bbox->p1.x));
4527     y1 = floor (surface->height - _cairo_fixed_to_double (bbox->p2.y));
4528     x2 = ceil (_cairo_fixed_to_double (bbox->p2.x));
4529     y2 = ceil (surface->height - _cairo_fixed_to_double (bbox->p1.y));
4530
4531     surface->page_bbox.x = x1;
4532     surface->page_bbox.y = y1;
4533     surface->page_bbox.width  = x2 - x1;
4534     surface->page_bbox.height = y2 - y1;
4535
4536     _cairo_output_stream_printf (surface->stream,
4537                                  "%%%%Page: %d %d\n",
4538                                  surface->num_pages,
4539                                  surface->num_pages);
4540
4541     _cairo_output_stream_printf (surface->stream,
4542                                  "%%%%BeginPageSetup\n");
4543
4544     has_page_media = FALSE;
4545     has_page_bbox = FALSE;
4546     num_comments = _cairo_array_num_elements (&surface->dsc_page_setup_comments);
4547     comments = _cairo_array_index (&surface->dsc_page_setup_comments, 0);
4548     if (comments == NULL)
4549         return CAIRO_STATUS_NULL_POINTER;
4550
4551     for (i = 0; i < num_comments; i++) {
4552         _cairo_output_stream_printf (surface->stream,
4553                                      "%s\n", comments[i]);
4554         if (strncmp (comments[i], "%%PageMedia:", 11) == 0)
4555             has_page_media = TRUE;
4556
4557         if (strncmp (comments[i], "%%PageBoundingBox:", 18) == 0)
4558             has_page_bbox = TRUE;
4559
4560         free (comments[i]);
4561         comments[i] = NULL;
4562     }
4563     _cairo_array_truncate (&surface->dsc_page_setup_comments, 0);
4564
4565     if (!has_page_media && !surface->eps) {
4566         page_media = _cairo_ps_surface_get_page_media (surface);
4567         if (unlikely (page_media == NULL))
4568             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4569
4570         _cairo_output_stream_printf (surface->stream,
4571                                      "%%%%PageMedia: %s\n",
4572                                      page_media);
4573     }
4574
4575     if (!has_page_bbox) {
4576         _cairo_output_stream_printf (surface->stream,
4577                                      "%%%%PageBoundingBox: %d %d %d %d\n",
4578                                      x1, y1, x2, y2);
4579     }
4580
4581     _cairo_output_stream_printf (surface->stream,
4582                                  "%%%%EndPageSetup\n"
4583                                  "q %d %d %d %d rectclip q\n",
4584                                  surface->page_bbox.x,
4585                                  surface->page_bbox.y,
4586                                  surface->page_bbox.width,
4587                                  surface->page_bbox.height);
4588
4589     if (surface->num_pages == 1) {
4590         surface->bbox_x1 = x1;
4591         surface->bbox_y1 = y1;
4592         surface->bbox_x2 = x2;
4593         surface->bbox_y2 = y2;
4594     } else {
4595         if (x1 < surface->bbox_x1)
4596             surface->bbox_x1 = x1;
4597         if (y1 < surface->bbox_y1)
4598             surface->bbox_y1 = y1;
4599         if (x2 > surface->bbox_x2)
4600             surface->bbox_x2 = x2;
4601         if (y2 > surface->bbox_y2)
4602             surface->bbox_y2 = y2;
4603     }
4604     surface->current_pattern_is_solid_color = FALSE;
4605     _cairo_pdf_operators_reset (&surface->pdf_operators);
4606
4607     return _cairo_output_stream_get_status (surface->stream);
4608 }
4609
4610 static cairo_bool_t
4611 _cairo_ps_surface_supports_fine_grained_fallbacks (void     *abstract_surface)
4612 {
4613     return TRUE;
4614 }
4615
4616 static const cairo_surface_backend_t cairo_ps_surface_backend = {
4617     CAIRO_SURFACE_TYPE_PS,
4618     _cairo_ps_surface_finish,
4619
4620     _cairo_default_context_create,
4621
4622     NULL, /* create similar: handled by wrapper */
4623     NULL, /* create similar image */
4624     NULL, /* map to image */
4625     NULL, /* unmap image */
4626
4627     _cairo_surface_default_source,
4628     NULL, /* acquire_source_image */
4629     NULL, /* release_source_image */
4630     NULL, /* snapshot */
4631
4632     NULL, /* cairo_ps_surface_copy_page */
4633     _cairo_ps_surface_show_page,
4634
4635     _cairo_ps_surface_get_extents,
4636     _cairo_ps_surface_get_font_options,
4637
4638     NULL, /* flush */
4639     NULL, /* mark_dirty_rectangle */
4640
4641     /* Here are the drawing functions */
4642
4643     _cairo_ps_surface_paint, /* paint */
4644     _cairo_ps_surface_mask,
4645     _cairo_ps_surface_stroke,
4646     _cairo_ps_surface_fill,
4647     NULL, /* fill-stroke */
4648     NULL, /* show_glyphs */
4649     _cairo_ps_surface_has_show_text_glyphs,
4650     _cairo_ps_surface_show_text_glyphs,
4651     _cairo_ps_surface_get_supported_mime_types,
4652 };
4653
4654 static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend = {
4655     _cairo_ps_surface_start_page,
4656     _cairo_ps_surface_set_paginated_mode,
4657     _cairo_ps_surface_set_bounding_box,
4658     NULL, /* _cairo_ps_surface_has_fallback_images, */
4659     _cairo_ps_surface_supports_fine_grained_fallbacks,
4660 };