Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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