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