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 © 2008 Chris Wilson
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it either under the terms of the GNU Lesser General Public
  8.  * License version 2.1 as published by the Free Software Foundation
  9.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  10.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  11.  * notice, a recipient may use your version of this file under either
  12.  * the MPL or the LGPL.
  13.  *
  14.  * You should have received a copy of the LGPL along with this library
  15.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  17.  * You should have received a copy of the MPL along with this library
  18.  * in the file COPYING-MPL-1.1
  19.  *
  20.  * The contents of this file are subject to the Mozilla Public License
  21.  * Version 1.1 (the "License"); you may not use this file except in
  22.  * compliance with the License. You may obtain a copy of the License at
  23.  * http://www.mozilla.org/MPL/
  24.  *
  25.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  26.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  27.  * the specific language governing rights and limitations.
  28.  *
  29.  * The Original Code is the cairo graphics library.
  30.  *
  31.  * The Initial Developer of the Original Code is Chris Wilson.
  32.  *
  33.  * Contributor(s):
  34.  *      Chris Wilson <chris@chris-wilson.co.uk>
  35.  */
  36.  
  37. /* The script surface is one that records all operations performed on
  38.  * it in the form of a procedural script, similar in fashion to
  39.  * PostScript but using Cairo's imaging model. In essence, this is
  40.  * equivalent to the recording-surface, but as there is no impedance mismatch
  41.  * between Cairo and CairoScript, we can generate output immediately
  42.  * without having to copy and hold the data in memory.
  43.  */
  44.  
  45. /**
  46.  * SECTION:cairo-script
  47.  * @Title: Script Surfaces
  48.  * @Short_Description: Rendering to replayable scripts
  49.  * @See_Also: #cairo_surface_t
  50.  *
  51.  * The script surface provides the ability to render to a native
  52.  * script that matches the cairo drawing model. The scripts can
  53.  * be replayed using tools under the util/cairo-script directoriy,
  54.  * or with cairo-perf-trace.
  55.  **/
  56.  
  57. /**
  58.  * CAIRO_HAS_SCRIPT_SURFACE:
  59.  *
  60.  * Defined if the script surface backend is available.
  61.  * The script surface backend is always built in since 1.12.
  62.  *
  63.  * Since: 1.12
  64.  **/
  65.  
  66.  
  67. #include "cairoint.h"
  68.  
  69. #include "cairo-script.h"
  70. #include "cairo-script-private.h"
  71.  
  72. #include "cairo-analysis-surface-private.h"
  73. #include "cairo-default-context-private.h"
  74. #include "cairo-device-private.h"
  75. #include "cairo-error-private.h"
  76. #include "cairo-list-inline.h"
  77. #include "cairo-image-surface-private.h"
  78. #include "cairo-output-stream-private.h"
  79. #include "cairo-pattern-private.h"
  80. #include "cairo-recording-surface-inline.h"
  81. #include "cairo-scaled-font-private.h"
  82. #include "cairo-surface-clipper-private.h"
  83. #include "cairo-surface-snapshot-inline.h"
  84. #include "cairo-surface-subsurface-private.h"
  85. #include "cairo-surface-wrapper-private.h"
  86.  
  87. #if CAIRO_HAS_FT_FONT
  88. #include "cairo-ft-private.h"
  89. #endif
  90.  
  91. #include <ctype.h>
  92.  
  93. #ifdef WORDS_BIGENDIAN
  94. #define to_be32(x) x
  95. #else
  96. #define to_be32(x) bswap_32(x)
  97. #endif
  98.  
  99. #define _cairo_output_stream_puts(S, STR) \
  100.     _cairo_output_stream_write ((S), (STR), strlen (STR))
  101.  
  102. #define static cairo_warn static
  103.  
  104. typedef struct _cairo_script_context cairo_script_context_t;
  105. typedef struct _cairo_script_surface cairo_script_surface_t;
  106. typedef struct _cairo_script_implicit_context cairo_script_implicit_context_t;
  107. typedef struct _cairo_script_font cairo_script_font_t;
  108.  
  109. typedef struct _operand {
  110.     enum {
  111.         SURFACE,
  112.         DEFERRED,
  113.     } type;
  114.     cairo_list_t link;
  115. } operand_t;
  116.  
  117.  
  118. struct deferred_finish {
  119.     cairo_list_t link;
  120.     operand_t operand;
  121. };
  122.  
  123. struct _cairo_script_context {
  124.     cairo_device_t base;
  125.  
  126.     int active;
  127.     int attach_snapshots;
  128.  
  129.     cairo_bool_t owns_stream;
  130.     cairo_output_stream_t *stream;
  131.     cairo_script_mode_t mode;
  132.  
  133.     struct _bitmap {
  134.         unsigned long min;
  135.         unsigned long count;
  136.         unsigned int map[64];
  137.         struct _bitmap *next;
  138.     } surface_id, font_id;
  139.  
  140.     cairo_list_t operands;
  141.     cairo_list_t deferred;
  142.  
  143.     cairo_list_t fonts;
  144.     cairo_list_t defines;
  145. };
  146.  
  147. struct _cairo_script_font {
  148.     cairo_scaled_font_private_t base;
  149.  
  150.     cairo_bool_t has_sfnt;
  151.     unsigned long id;
  152.     unsigned long subset_glyph_index;
  153.     cairo_list_t link;
  154.     cairo_scaled_font_t *parent;
  155. };
  156.  
  157. struct _cairo_script_implicit_context {
  158.     cairo_operator_t current_operator;
  159.     cairo_fill_rule_t current_fill_rule;
  160.     double current_tolerance;
  161.     cairo_antialias_t current_antialias;
  162.     cairo_stroke_style_t current_style;
  163.     cairo_pattern_union_t current_source;
  164.     cairo_matrix_t current_ctm;
  165.     cairo_matrix_t current_stroke_matrix;
  166.     cairo_matrix_t current_font_matrix;
  167.     cairo_font_options_t current_font_options;
  168.     cairo_scaled_font_t *current_scaled_font;
  169.     cairo_path_fixed_t current_path;
  170.     cairo_bool_t has_clip;
  171. };
  172.  
  173. struct _cairo_script_surface {
  174.     cairo_surface_t base;
  175.  
  176.     cairo_surface_wrapper_t wrapper;
  177.  
  178.     cairo_surface_clipper_t clipper;
  179.  
  180.     operand_t operand;
  181.     cairo_bool_t emitted;
  182.     cairo_bool_t defined;
  183.     cairo_bool_t active;
  184.  
  185.     double width, height;
  186.  
  187.     /* implicit flattened context */
  188.     cairo_script_implicit_context_t cr;
  189. };
  190.  
  191. static const cairo_surface_backend_t _cairo_script_surface_backend;
  192.  
  193. static cairo_script_surface_t *
  194. _cairo_script_surface_create_internal (cairo_script_context_t *ctx,
  195.                                        cairo_content_t content,
  196.                                        cairo_rectangle_t *extents,
  197.                                        cairo_surface_t *passthrough);
  198.  
  199. static void
  200. _cairo_script_scaled_font_fini (cairo_scaled_font_private_t *abstract_private,
  201.                                 cairo_scaled_font_t *scaled_font);
  202.  
  203. static void
  204. _cairo_script_implicit_context_init (cairo_script_implicit_context_t *cr);
  205.  
  206. static void
  207. _cairo_script_implicit_context_reset (cairo_script_implicit_context_t *cr);
  208.  
  209. static void
  210. _bitmap_release_id (struct _bitmap *b, unsigned long token)
  211. {
  212.     struct _bitmap **prev = NULL;
  213.  
  214.     do {
  215.         if (token < b->min + sizeof (b->map) * CHAR_BIT) {
  216.             unsigned int bit, elem;
  217.  
  218.             token -= b->min;
  219.             elem = token / (sizeof (b->map[0]) * CHAR_BIT);
  220.             bit  = token % (sizeof (b->map[0]) * CHAR_BIT);
  221.             b->map[elem] &= ~(1 << bit);
  222.             if (! --b->count && prev) {
  223.                 *prev = b->next;
  224.                 free (b);
  225.             }
  226.             return;
  227.         }
  228.         prev = &b->next;
  229.         b = b->next;
  230.     } while (b != NULL);
  231. }
  232.  
  233. static cairo_status_t
  234. _bitmap_next_id (struct _bitmap *b,
  235.                  unsigned long *id)
  236. {
  237.     struct _bitmap *bb, **prev = NULL;
  238.     unsigned long min = 0;
  239.  
  240.     do {
  241.         if (b->min != min)
  242.             break;
  243.  
  244.         if (b->count < sizeof (b->map) * CHAR_BIT) {
  245.             unsigned int n, m, bit;
  246.             for (n = 0; n < ARRAY_LENGTH (b->map); n++) {
  247.                 if (b->map[n] == (unsigned int) -1)
  248.                     continue;
  249.  
  250.                 for (m=0, bit=1; m<sizeof (b->map[0])*CHAR_BIT; m++, bit<<=1) {
  251.                     if ((b->map[n] & bit) == 0) {
  252.                         b->map[n] |= bit;
  253.                         b->count++;
  254.                         *id = n * sizeof (b->map[0])*CHAR_BIT + m + b->min;
  255.                         return CAIRO_STATUS_SUCCESS;
  256.                     }
  257.                 }
  258.             }
  259.         }
  260.         min += sizeof (b->map) * CHAR_BIT;
  261.  
  262.         prev = &b->next;
  263.         b = b->next;
  264.     } while (b != NULL);
  265.  
  266.     bb = malloc (sizeof (struct _bitmap));
  267.     if (unlikely (bb == NULL))
  268.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  269.  
  270.     *prev = bb;
  271.     bb->next = b;
  272.     bb->min = min;
  273.     bb->count = 1;
  274.     bb->map[0] = 0x1;
  275.     memset (bb->map + 1, 0, sizeof (bb->map) - sizeof (bb->map[0]));
  276.     *id = min;
  277.  
  278.     return CAIRO_STATUS_SUCCESS;
  279. }
  280.  
  281. static void
  282. _bitmap_fini (struct _bitmap *b)
  283. {
  284.     while (b != NULL) {
  285.         struct _bitmap *next = b->next;
  286.         free (b);
  287.         b = next;
  288.     }
  289. }
  290.  
  291. static const char *
  292. _direction_to_string (cairo_bool_t backward)
  293. {
  294.     static const char *names[] = {
  295.         "FORWARD",
  296.         "BACKWARD"
  297.     };
  298.     assert (backward < ARRAY_LENGTH (names));
  299.     return names[backward];
  300. }
  301.  
  302. static const char *
  303. _operator_to_string (cairo_operator_t op)
  304. {
  305.     static const char *names[] = {
  306.         "CLEAR",        /* CAIRO_OPERATOR_CLEAR */
  307.  
  308.         "SOURCE",       /* CAIRO_OPERATOR_SOURCE */
  309.         "OVER",         /* CAIRO_OPERATOR_OVER */
  310.         "IN",           /* CAIRO_OPERATOR_IN */
  311.         "OUT",          /* CAIRO_OPERATOR_OUT */
  312.         "ATOP",         /* CAIRO_OPERATOR_ATOP */
  313.  
  314.         "DEST",         /* CAIRO_OPERATOR_DEST */
  315.         "DEST_OVER",    /* CAIRO_OPERATOR_DEST_OVER */
  316.         "DEST_IN",      /* CAIRO_OPERATOR_DEST_IN */
  317.         "DEST_OUT",     /* CAIRO_OPERATOR_DEST_OUT */
  318.         "DEST_ATOP",    /* CAIRO_OPERATOR_DEST_ATOP */
  319.  
  320.         "XOR",          /* CAIRO_OPERATOR_XOR */
  321.         "ADD",          /* CAIRO_OPERATOR_ADD */
  322.         "SATURATE",     /* CAIRO_OPERATOR_SATURATE */
  323.  
  324.         "MULTIPLY",     /* CAIRO_OPERATOR_MULTIPLY */
  325.         "SCREEN",       /* CAIRO_OPERATOR_SCREEN */
  326.         "OVERLAY",      /* CAIRO_OPERATOR_OVERLAY */
  327.         "DARKEN",       /* CAIRO_OPERATOR_DARKEN */
  328.         "LIGHTEN",      /* CAIRO_OPERATOR_LIGHTEN */
  329.         "DODGE",        /* CAIRO_OPERATOR_COLOR_DODGE */
  330.         "BURN",         /* CAIRO_OPERATOR_COLOR_BURN */
  331.         "HARD_LIGHT",   /* CAIRO_OPERATOR_HARD_LIGHT */
  332.         "SOFT_LIGHT",   /* CAIRO_OPERATOR_SOFT_LIGHT */
  333.         "DIFFERENCE",   /* CAIRO_OPERATOR_DIFFERENCE */
  334.         "EXCLUSION",    /* CAIRO_OPERATOR_EXCLUSION */
  335.         "HSL_HUE",      /* CAIRO_OPERATOR_HSL_HUE */
  336.         "HSL_SATURATION", /* CAIRO_OPERATOR_HSL_SATURATION */
  337.         "HSL_COLOR",    /* CAIRO_OPERATOR_HSL_COLOR */
  338.         "HSL_LUMINOSITY" /* CAIRO_OPERATOR_HSL_LUMINOSITY */
  339.     };
  340.     assert (op < ARRAY_LENGTH (names));
  341.     return names[op];
  342. }
  343.  
  344. static const char *
  345. _extend_to_string (cairo_extend_t extend)
  346. {
  347.     static const char *names[] = {
  348.         "EXTEND_NONE",          /* CAIRO_EXTEND_NONE */
  349.         "EXTEND_REPEAT",        /* CAIRO_EXTEND_REPEAT */
  350.         "EXTEND_REFLECT",       /* CAIRO_EXTEND_REFLECT */
  351.         "EXTEND_PAD"            /* CAIRO_EXTEND_PAD */
  352.     };
  353.     assert (extend < ARRAY_LENGTH (names));
  354.     return names[extend];
  355. }
  356.  
  357. static const char *
  358. _filter_to_string (cairo_filter_t filter)
  359. {
  360.     static const char *names[] = {
  361.         "FILTER_FAST",          /* CAIRO_FILTER_FAST */
  362.         "FILTER_GOOD",          /* CAIRO_FILTER_GOOD */
  363.         "FILTER_BEST",          /* CAIRO_FILTER_BEST */
  364.         "FILTER_NEAREST",       /* CAIRO_FILTER_NEAREST */
  365.         "FILTER_BILINEAR",      /* CAIRO_FILTER_BILINEAR */
  366.         "FILTER_GAUSSIAN",      /* CAIRO_FILTER_GAUSSIAN */
  367.     };
  368.     assert (filter < ARRAY_LENGTH (names));
  369.     return names[filter];
  370. }
  371.  
  372. static const char *
  373. _fill_rule_to_string (cairo_fill_rule_t rule)
  374. {
  375.     static const char *names[] = {
  376.         "WINDING",      /* CAIRO_FILL_RULE_WINDING */
  377.         "EVEN_ODD"      /* CAIRO_FILL_RILE_EVEN_ODD */
  378.     };
  379.     assert (rule < ARRAY_LENGTH (names));
  380.     return names[rule];
  381. }
  382.  
  383. static const char *
  384. _antialias_to_string (cairo_antialias_t antialias)
  385. {
  386.     static const char *names[] = {
  387.         "ANTIALIAS_DEFAULT",    /* CAIRO_ANTIALIAS_DEFAULT */
  388.         "ANTIALIAS_NONE",       /* CAIRO_ANTIALIAS_NONE */
  389.         "ANTIALIAS_GRAY",       /* CAIRO_ANTIALIAS_GRAY */
  390.         "ANTIALIAS_SUBPIXEL",   /* CAIRO_ANTIALIAS_SUBPIXEL */
  391.         "ANTIALIAS_FAST",       /* CAIRO_ANTIALIAS_FAST */
  392.         "ANTIALIAS_GOOD",       /* CAIRO_ANTIALIAS_GOOD */
  393.         "ANTIALIAS_BEST"        /* CAIRO_ANTIALIAS_BEST */
  394.     };
  395.     assert (antialias < ARRAY_LENGTH (names));
  396.     return names[antialias];
  397. }
  398.  
  399. static const char *
  400. _line_cap_to_string (cairo_line_cap_t line_cap)
  401. {
  402.     static const char *names[] = {
  403.         "LINE_CAP_BUTT",        /* CAIRO_LINE_CAP_BUTT */
  404.         "LINE_CAP_ROUND",       /* CAIRO_LINE_CAP_ROUND */
  405.         "LINE_CAP_SQUARE"       /* CAIRO_LINE_CAP_SQUARE */
  406.     };
  407.     assert (line_cap < ARRAY_LENGTH (names));
  408.     return names[line_cap];
  409. }
  410.  
  411. static const char *
  412. _line_join_to_string (cairo_line_join_t line_join)
  413. {
  414.     static const char *names[] = {
  415.         "LINE_JOIN_MITER",      /* CAIRO_LINE_JOIN_MITER */
  416.         "LINE_JOIN_ROUND",      /* CAIRO_LINE_JOIN_ROUND */
  417.         "LINE_JOIN_BEVEL",      /* CAIRO_LINE_JOIN_BEVEL */
  418.     };
  419.     assert (line_join < ARRAY_LENGTH (names));
  420.     return names[line_join];
  421. }
  422.  
  423. static inline cairo_script_context_t *
  424. to_context (cairo_script_surface_t *surface)
  425. {
  426.     return (cairo_script_context_t *) surface->base.device;
  427. }
  428.  
  429. static cairo_bool_t
  430. target_is_active (cairo_script_surface_t *surface)
  431. {
  432.     return cairo_list_is_first (&surface->operand.link,
  433.                                 &to_context (surface)->operands);
  434. }
  435.  
  436. static void
  437. target_push (cairo_script_surface_t *surface)
  438. {
  439.     cairo_list_move (&surface->operand.link, &to_context (surface)->operands);
  440. }
  441.  
  442. static int
  443. target_depth (cairo_script_surface_t *surface)
  444. {
  445.     cairo_list_t *link;
  446.     int depth = 0;
  447.  
  448.     cairo_list_foreach (link, &to_context (surface)->operands) {
  449.         if (link == &surface->operand.link)
  450.             break;
  451.         depth++;
  452.     }
  453.  
  454.     return depth;
  455. }
  456.  
  457. static void
  458. _get_target (cairo_script_surface_t *surface)
  459. {
  460.     cairo_script_context_t *ctx = to_context (surface);
  461.  
  462.     if (target_is_active (surface)) {
  463.         _cairo_output_stream_puts (ctx->stream, "dup ");
  464.         return;
  465.     }
  466.  
  467.     if (surface->defined) {
  468.         _cairo_output_stream_printf (ctx->stream, "s%u ",
  469.                                      surface->base.unique_id);
  470.     } else {
  471.         int depth = target_depth (surface);
  472.  
  473.         assert (! cairo_list_is_empty (&surface->operand.link));
  474.         assert (! target_is_active (surface));
  475.  
  476.         if (ctx->active) {
  477.             _cairo_output_stream_printf (ctx->stream, "%d index ", depth);
  478.             _cairo_output_stream_puts (ctx->stream, "/target get exch pop ");
  479.         } else {
  480.             if (depth == 1) {
  481.                 _cairo_output_stream_puts (ctx->stream, "exch ");
  482.             } else {
  483.                 _cairo_output_stream_printf (ctx->stream,
  484.                                              "%d -1 roll ", depth);
  485.             }
  486.             target_push (surface);
  487.             _cairo_output_stream_puts (ctx->stream, "dup ");
  488.         }
  489.     }
  490. }
  491.  
  492. static const char *
  493. _content_to_string (cairo_content_t content)
  494. {
  495.     switch (content) {
  496.     case CAIRO_CONTENT_ALPHA: return "ALPHA";
  497.     case CAIRO_CONTENT_COLOR: return "COLOR";
  498.     default:
  499.     case CAIRO_CONTENT_COLOR_ALPHA: return "COLOR_ALPHA";
  500.     }
  501. }
  502.  
  503. static cairo_status_t
  504. _emit_surface (cairo_script_surface_t *surface)
  505. {
  506.     cairo_script_context_t *ctx = to_context (surface);
  507.  
  508.     _cairo_output_stream_printf (ctx->stream,
  509.                                  "<< /content //%s",
  510.                                  _content_to_string (surface->base.content));
  511.     if (surface->width != -1 && surface->height != -1) {
  512.         _cairo_output_stream_printf (ctx->stream,
  513.                                      " /width %f /height %f",
  514.                                      surface->width,
  515.                                      surface->height);
  516.     }
  517.  
  518.     if (surface->base.x_fallback_resolution !=
  519.         CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT ||
  520.         surface->base.y_fallback_resolution !=
  521.         CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT)
  522.     {
  523.         _cairo_output_stream_printf (ctx->stream,
  524.                                      " /fallback-resolution [%f %f]",
  525.                                      surface->base.x_fallback_resolution,
  526.                                      surface->base.y_fallback_resolution);
  527.     }
  528.  
  529.     if (surface->base.device_transform.x0 != 0. ||
  530.         surface->base.device_transform.y0 != 0.)
  531.     {
  532.         /* XXX device offset is encoded into the pattern matrices etc. */
  533.         if (0) {
  534.         _cairo_output_stream_printf (ctx->stream,
  535.                                      " /device-offset [%f %f]",
  536.                                      surface->base.device_transform.x0,
  537.                                      surface->base.device_transform.y0);
  538.         }
  539.     }
  540.  
  541.     _cairo_output_stream_puts (ctx->stream, " >> surface context\n");
  542.     surface->emitted = TRUE;
  543.     return CAIRO_STATUS_SUCCESS;
  544. }
  545.  
  546. static cairo_status_t
  547. _emit_context (cairo_script_surface_t *surface)
  548. {
  549.     cairo_script_context_t *ctx = to_context (surface);
  550.  
  551.     if (target_is_active (surface))
  552.         return CAIRO_STATUS_SUCCESS;
  553.  
  554.     while (! cairo_list_is_empty (&ctx->operands)) {
  555.         operand_t *op;
  556.         cairo_script_surface_t *old;
  557.  
  558.         op = cairo_list_first_entry (&ctx->operands,
  559.                                      operand_t,
  560.                                      link);
  561.         if (op->type == DEFERRED)
  562.             break;
  563.  
  564.         old = cairo_container_of (op, cairo_script_surface_t, operand);
  565.         if (old == surface)
  566.             break;
  567.         if (old->active)
  568.             break;
  569.  
  570.         if (! old->defined) {
  571.             assert (old->emitted);
  572.             _cairo_output_stream_printf (ctx->stream,
  573.                                          "/target get /s%u exch def pop\n",
  574.                                          old->base.unique_id);
  575.             old->defined = TRUE;
  576.         } else {
  577.             _cairo_output_stream_puts (ctx->stream, "pop\n");
  578.         }
  579.  
  580.         cairo_list_del (&old->operand.link);
  581.     }
  582.  
  583.     if (target_is_active (surface))
  584.         return CAIRO_STATUS_SUCCESS;
  585.  
  586.     if (! surface->emitted) {
  587.         cairo_status_t status;
  588.  
  589.         status = _emit_surface (surface);
  590.         if (unlikely (status))
  591.             return status;
  592.     } else if (cairo_list_is_empty (&surface->operand.link)) {
  593.         assert (surface->defined);
  594.         _cairo_output_stream_printf (ctx->stream,
  595.                                      "s%u context\n",
  596.                                      surface->base.unique_id);
  597.         _cairo_script_implicit_context_reset (&surface->cr);
  598.         _cairo_surface_clipper_reset (&surface->clipper);
  599.     } else {
  600.         int depth = target_depth (surface);
  601.         if (depth == 1) {
  602.             _cairo_output_stream_puts (ctx->stream, "exch\n");
  603.         } else {
  604.             _cairo_output_stream_printf (ctx->stream,
  605.                                          "%d -1 roll\n",
  606.                                          depth);
  607.         }
  608.     }
  609.     target_push (surface);
  610.  
  611.     return CAIRO_STATUS_SUCCESS;
  612. }
  613.  
  614. static cairo_status_t
  615. _emit_operator (cairo_script_surface_t *surface,
  616.                 cairo_operator_t op)
  617. {
  618.     assert (target_is_active (surface));
  619.  
  620.     if (surface->cr.current_operator == op)
  621.         return CAIRO_STATUS_SUCCESS;
  622.  
  623.     surface->cr.current_operator = op;
  624.  
  625.     _cairo_output_stream_printf (to_context (surface)->stream,
  626.                                  "//%s set-operator\n",
  627.                                  _operator_to_string (op));
  628.     return CAIRO_STATUS_SUCCESS;
  629. }
  630.  
  631. static cairo_status_t
  632. _emit_fill_rule (cairo_script_surface_t *surface,
  633.                  cairo_fill_rule_t fill_rule)
  634. {
  635.     assert (target_is_active (surface));
  636.  
  637.     if (surface->cr.current_fill_rule == fill_rule)
  638.         return CAIRO_STATUS_SUCCESS;
  639.  
  640.     surface->cr.current_fill_rule = fill_rule;
  641.  
  642.     _cairo_output_stream_printf (to_context (surface)->stream,
  643.                                  "//%s set-fill-rule\n",
  644.                                  _fill_rule_to_string (fill_rule));
  645.     return CAIRO_STATUS_SUCCESS;
  646. }
  647.  
  648. static cairo_status_t
  649. _emit_tolerance (cairo_script_surface_t *surface,
  650.                  double tolerance,
  651.                  cairo_bool_t force)
  652. {
  653.     assert (target_is_active (surface));
  654.  
  655.     if ((! force ||
  656.          fabs (tolerance - CAIRO_GSTATE_TOLERANCE_DEFAULT) < 1e-5) &&
  657.         surface->cr.current_tolerance == tolerance)
  658.     {
  659.         return CAIRO_STATUS_SUCCESS;
  660.     }
  661.  
  662.     surface->cr.current_tolerance = tolerance;
  663.  
  664.     _cairo_output_stream_printf (to_context (surface)->stream,
  665.                                  "%f set-tolerance\n",
  666.                                  tolerance);
  667.     return CAIRO_STATUS_SUCCESS;
  668. }
  669.  
  670. static cairo_status_t
  671. _emit_antialias (cairo_script_surface_t *surface,
  672.                  cairo_antialias_t antialias)
  673. {
  674.     assert (target_is_active (surface));
  675.  
  676.     if (surface->cr.current_antialias == antialias)
  677.         return CAIRO_STATUS_SUCCESS;
  678.  
  679.     surface->cr.current_antialias = antialias;
  680.  
  681.     _cairo_output_stream_printf (to_context (surface)->stream,
  682.                                  "//%s set-antialias\n",
  683.                                  _antialias_to_string (antialias));
  684.  
  685.     return CAIRO_STATUS_SUCCESS;
  686. }
  687.  
  688. static cairo_status_t
  689. _emit_line_width (cairo_script_surface_t *surface,
  690.                  double line_width,
  691.                  cairo_bool_t force)
  692. {
  693.     assert (target_is_active (surface));
  694.  
  695.     if ((! force ||
  696.          fabs (line_width - CAIRO_GSTATE_LINE_WIDTH_DEFAULT) < 1e-5) &&
  697.         surface->cr.current_style.line_width == line_width)
  698.     {
  699.         return CAIRO_STATUS_SUCCESS;
  700.     }
  701.  
  702.     surface->cr.current_style.line_width = line_width;
  703.  
  704.     _cairo_output_stream_printf (to_context (surface)->stream,
  705.                                  "%f set-line-width\n",
  706.                                  line_width);
  707.     return CAIRO_STATUS_SUCCESS;
  708. }
  709.  
  710. static cairo_status_t
  711. _emit_line_cap (cairo_script_surface_t *surface,
  712.                 cairo_line_cap_t line_cap)
  713. {
  714.     assert (target_is_active (surface));
  715.  
  716.     if (surface->cr.current_style.line_cap == line_cap)
  717.         return CAIRO_STATUS_SUCCESS;
  718.  
  719.     surface->cr.current_style.line_cap = line_cap;
  720.  
  721.     _cairo_output_stream_printf (to_context (surface)->stream,
  722.                                  "//%s set-line-cap\n",
  723.                                  _line_cap_to_string (line_cap));
  724.     return CAIRO_STATUS_SUCCESS;
  725. }
  726.  
  727. static cairo_status_t
  728. _emit_line_join (cairo_script_surface_t *surface,
  729.                  cairo_line_join_t line_join)
  730. {
  731.     assert (target_is_active (surface));
  732.  
  733.     if (surface->cr.current_style.line_join == line_join)
  734.         return CAIRO_STATUS_SUCCESS;
  735.  
  736.     surface->cr.current_style.line_join = line_join;
  737.  
  738.     _cairo_output_stream_printf (to_context (surface)->stream,
  739.                                  "//%s set-line-join\n",
  740.                                  _line_join_to_string (line_join));
  741.     return CAIRO_STATUS_SUCCESS;
  742. }
  743.  
  744. static cairo_status_t
  745. _emit_miter_limit (cairo_script_surface_t *surface,
  746.                    double miter_limit,
  747.                    cairo_bool_t force)
  748. {
  749.     assert (target_is_active (surface));
  750.  
  751.     if ((! force ||
  752.          fabs (miter_limit - CAIRO_GSTATE_MITER_LIMIT_DEFAULT) < 1e-5) &&
  753.         surface->cr.current_style.miter_limit == miter_limit)
  754.     {
  755.         return CAIRO_STATUS_SUCCESS;
  756.     }
  757.  
  758.     surface->cr.current_style.miter_limit = miter_limit;
  759.  
  760.     _cairo_output_stream_printf (to_context (surface)->stream,
  761.                                  "%f set-miter-limit\n",
  762.                                  miter_limit);
  763.     return CAIRO_STATUS_SUCCESS;
  764. }
  765.  
  766. static cairo_bool_t
  767. _dashes_equal (const double *a, const double *b, int num_dashes)
  768. {
  769.     while (num_dashes--) {
  770.         if (fabs (*a - *b) > 1e-5)
  771.             return FALSE;
  772.         a++, b++;
  773.     }
  774.  
  775.     return TRUE;
  776. }
  777.  
  778. static cairo_status_t
  779. _emit_dash (cairo_script_surface_t *surface,
  780.             const double *dash,
  781.             unsigned int num_dashes,
  782.             double offset,
  783.             cairo_bool_t force)
  784. {
  785.     unsigned int n;
  786.  
  787.     assert (target_is_active (surface));
  788.  
  789.     if (force &&
  790.         num_dashes == 0 &&
  791.         surface->cr.current_style.num_dashes == 0)
  792.     {
  793.         return CAIRO_STATUS_SUCCESS;
  794.     }
  795.  
  796.     if (! force &&
  797.         (surface->cr.current_style.num_dashes == num_dashes &&
  798.          (num_dashes == 0 ||
  799.           (fabs (surface->cr.current_style.dash_offset - offset) < 1e-5 &&
  800.            _dashes_equal (surface->cr.current_style.dash, dash, num_dashes)))))
  801.     {
  802.         return CAIRO_STATUS_SUCCESS;
  803.     }
  804.  
  805.  
  806.     if (num_dashes) {
  807.         surface->cr.current_style.dash = _cairo_realloc_ab
  808.             (surface->cr.current_style.dash, num_dashes, sizeof (double));
  809.         if (unlikely (surface->cr.current_style.dash == NULL))
  810.             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  811.  
  812.         memcpy (surface->cr.current_style.dash, dash,
  813.                 sizeof (double) * num_dashes);
  814.     } else {
  815.         free (surface->cr.current_style.dash);
  816.         surface->cr.current_style.dash = NULL;
  817.     }
  818.  
  819.     surface->cr.current_style.num_dashes = num_dashes;
  820.     surface->cr.current_style.dash_offset = offset;
  821.  
  822.     _cairo_output_stream_puts (to_context (surface)->stream, "[");
  823.     for (n = 0; n < num_dashes; n++) {
  824.         _cairo_output_stream_printf (to_context (surface)->stream, "%f", dash[n]);
  825.         if (n < num_dashes-1)
  826.             _cairo_output_stream_puts (to_context (surface)->stream, " ");
  827.     }
  828.     _cairo_output_stream_printf (to_context (surface)->stream,
  829.                                  "] %f set-dash\n",
  830.                                  offset);
  831.  
  832.     return CAIRO_STATUS_SUCCESS;
  833. }
  834.  
  835. static cairo_status_t
  836. _emit_stroke_style (cairo_script_surface_t *surface,
  837.                     const cairo_stroke_style_t *style,
  838.                     cairo_bool_t force)
  839. {
  840.     cairo_status_t status;
  841.  
  842.     assert (target_is_active (surface));
  843.  
  844.     status = _emit_line_width (surface, style->line_width, force);
  845.     if (unlikely (status))
  846.         return status;
  847.  
  848.     status = _emit_line_cap (surface, style->line_cap);
  849.     if (unlikely (status))
  850.         return status;
  851.  
  852.     status = _emit_line_join (surface, style->line_join);
  853.     if (unlikely (status))
  854.         return status;
  855.  
  856.     status = _emit_miter_limit (surface, style->miter_limit, force);
  857.     if (unlikely (status))
  858.         return status;
  859.  
  860.     status = _emit_dash (surface,
  861.                          style->dash, style->num_dashes, style->dash_offset,
  862.                          force);
  863.     if (unlikely (status))
  864.         return status;
  865.  
  866.     return CAIRO_STATUS_SUCCESS;
  867. }
  868.  
  869. static const char *
  870. _format_to_string (cairo_format_t format)
  871. {
  872.     switch (format) {
  873.     case CAIRO_FORMAT_ARGB32:  return "ARGB32";
  874.     case CAIRO_FORMAT_RGB30:   return "RGB30";
  875.     case CAIRO_FORMAT_RGB24:   return "RGB24";
  876.     case CAIRO_FORMAT_RGB16_565: return "RGB16_565";
  877.     case CAIRO_FORMAT_A8:      return "A8";
  878.     case CAIRO_FORMAT_A1:      return "A1";
  879.     case CAIRO_FORMAT_INVALID: return "INVALID";
  880.     }
  881.     ASSERT_NOT_REACHED;
  882.     return "INVALID";
  883. }
  884.  
  885. static cairo_status_t
  886. _emit_solid_pattern (cairo_script_surface_t *surface,
  887.                      const cairo_pattern_t *pattern)
  888. {
  889.     cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
  890.     cairo_script_context_t *ctx = to_context (surface);
  891.  
  892.     if (! CAIRO_COLOR_IS_OPAQUE (&solid->color))
  893.     {
  894.         if (! (surface->base.content & CAIRO_CONTENT_COLOR) ||
  895.             ((solid->color.red_short   == 0 || solid->color.red_short   == 0xffff) &&
  896.              (solid->color.green_short == 0 || solid->color.green_short == 0xffff) &&
  897.              (solid->color.blue_short  == 0 || solid->color.blue_short  == 0xffff) ))
  898.         {
  899.             _cairo_output_stream_printf (ctx->stream,
  900.                                          "%f a",
  901.                                          solid->color.alpha);
  902.         }
  903.         else
  904.         {
  905.             _cairo_output_stream_printf (ctx->stream,
  906.                                          "%f %f %f %f rgba",
  907.                                          solid->color.red,
  908.                                          solid->color.green,
  909.                                          solid->color.blue,
  910.                                          solid->color.alpha);
  911.         }
  912.     }
  913.     else
  914.     {
  915.         if (solid->color.red_short == solid->color.green_short &&
  916.             solid->color.red_short == solid->color.blue_short)
  917.         {
  918.             _cairo_output_stream_printf (ctx->stream,
  919.                                          "%f g",
  920.                                          solid->color.red);
  921.         }
  922.         else
  923.         {
  924.             _cairo_output_stream_printf (ctx->stream,
  925.                                          "%f %f %f rgb",
  926.                                          solid->color.red,
  927.                                          solid->color.green,
  928.                                          solid->color.blue);
  929.         }
  930.     }
  931.  
  932.     return CAIRO_STATUS_SUCCESS;
  933. }
  934.  
  935.  
  936. static cairo_status_t
  937. _emit_gradient_color_stops (cairo_gradient_pattern_t *gradient,
  938.                             cairo_output_stream_t *output)
  939. {
  940.     unsigned int n;
  941.  
  942.     for (n = 0; n < gradient->n_stops; n++) {
  943.         _cairo_output_stream_printf (output,
  944.                                      "\n  %f %f %f %f %f add-color-stop",
  945.                                      gradient->stops[n].offset,
  946.                                      gradient->stops[n].color.red,
  947.                                      gradient->stops[n].color.green,
  948.                                      gradient->stops[n].color.blue,
  949.                                      gradient->stops[n].color.alpha);
  950.     }
  951.  
  952.     return CAIRO_STATUS_SUCCESS;
  953. }
  954.  
  955. static cairo_status_t
  956. _emit_linear_pattern (cairo_script_surface_t *surface,
  957.                       const cairo_pattern_t *pattern)
  958. {
  959.     cairo_script_context_t *ctx = to_context (surface);
  960.     cairo_linear_pattern_t *linear;
  961.  
  962.     linear = (cairo_linear_pattern_t *) pattern;
  963.  
  964.     _cairo_output_stream_printf (ctx->stream,
  965.                                  "%f %f %f %f linear",
  966.                                  linear->pd1.x, linear->pd1.y,
  967.                                  linear->pd2.x, linear->pd2.y);
  968.     return _emit_gradient_color_stops (&linear->base, ctx->stream);
  969. }
  970.  
  971. static cairo_status_t
  972. _emit_radial_pattern (cairo_script_surface_t *surface,
  973.                       const cairo_pattern_t *pattern)
  974. {
  975.     cairo_script_context_t *ctx = to_context (surface);
  976.     cairo_radial_pattern_t *radial;
  977.  
  978.     radial = (cairo_radial_pattern_t *) pattern;
  979.  
  980.     _cairo_output_stream_printf (ctx->stream,
  981.                                  "%f %f %f %f %f %f radial",
  982.                                  radial->cd1.center.x,
  983.                                  radial->cd1.center.y,
  984.                                  radial->cd1.radius,
  985.                                  radial->cd2.center.x,
  986.                                  radial->cd2.center.y,
  987.                                  radial->cd2.radius);
  988.     return _emit_gradient_color_stops (&radial->base, ctx->stream);
  989. }
  990.  
  991. static cairo_status_t
  992. _emit_mesh_pattern (cairo_script_surface_t *surface,
  993.                     const cairo_pattern_t *pattern)
  994. {
  995.     cairo_script_context_t *ctx = to_context (surface);
  996.     cairo_pattern_t *mesh;
  997.     cairo_status_t status;
  998.     unsigned int i, n;
  999.  
  1000.     mesh = (cairo_pattern_t *) pattern;
  1001.     status = cairo_mesh_pattern_get_patch_count (mesh, &n);
  1002.     if (unlikely (status))
  1003.         return status;
  1004.  
  1005.     _cairo_output_stream_printf (ctx->stream, "mesh");
  1006.     for (i = 0; i < n; i++) {
  1007.         cairo_path_t *path;
  1008.         cairo_path_data_t *data;
  1009.         int j;
  1010.  
  1011.         _cairo_output_stream_printf (ctx->stream, "\n  begin-patch");
  1012.  
  1013.         path = cairo_mesh_pattern_get_path (mesh, i);
  1014.         if (unlikely (path->status))
  1015.             return path->status;
  1016.  
  1017.         for (j = 0; j < path->num_data; j+=data[0].header.length) {
  1018.             data = &path->data[j];
  1019.             switch (data->header.type) {
  1020.             case CAIRO_PATH_MOVE_TO:
  1021.                 _cairo_output_stream_printf (ctx->stream,
  1022.                                              "\n  %f %f m",
  1023.                                              data[1].point.x, data[1].point.y);
  1024.                 break;
  1025.             case CAIRO_PATH_LINE_TO:
  1026.                 _cairo_output_stream_printf (ctx->stream,
  1027.                                              "\n  %f %f l",
  1028.                                              data[1].point.x, data[1].point.y);
  1029.                 break;
  1030.             case CAIRO_PATH_CURVE_TO:
  1031.                 _cairo_output_stream_printf (ctx->stream,
  1032.                                              "\n  %f %f %f %f %f %f c",
  1033.                                              data[1].point.x, data[1].point.y,
  1034.                                              data[2].point.x, data[2].point.y,
  1035.                                              data[3].point.x, data[3].point.y);
  1036.                 break;
  1037.             case CAIRO_PATH_CLOSE_PATH:
  1038.                 break;
  1039.             }
  1040.         }
  1041.         cairo_path_destroy (path);
  1042.  
  1043.         for (j = 0; j < 4; j++) {
  1044.             double x, y;
  1045.  
  1046.             status = cairo_mesh_pattern_get_control_point (mesh, i, j, &x, &y);
  1047.             if (unlikely (status))
  1048.                 return status;
  1049.             _cairo_output_stream_printf (ctx->stream,
  1050.                                          "\n  %d %f %f set-control-point",
  1051.                                          j, x, y);
  1052.         }
  1053.  
  1054.         for (j = 0; j < 4; j++) {
  1055.             double r, g, b, a;
  1056.  
  1057.             status = cairo_mesh_pattern_get_corner_color_rgba (mesh, i, j, &r, &g, &b, &a);
  1058.             if (unlikely (status))
  1059.                 return status;
  1060.  
  1061.             _cairo_output_stream_printf (ctx->stream,
  1062.                                          "\n  %d %f %f %f %f set-corner-color",
  1063.                                          j, r, g, b, a);
  1064.         }
  1065.  
  1066.         _cairo_output_stream_printf (ctx->stream, "\n  end-patch");
  1067.     }
  1068.  
  1069.     return CAIRO_STATUS_SUCCESS;
  1070. }
  1071.  
  1072. struct script_snapshot {
  1073.     cairo_surface_t base;
  1074. };
  1075.  
  1076. static cairo_status_t
  1077. script_snapshot_finish (void *abstract_surface)
  1078. {
  1079.     return CAIRO_STATUS_SUCCESS;
  1080. }
  1081.  
  1082. static const cairo_surface_backend_t script_snapshot_backend = {
  1083.     CAIRO_SURFACE_TYPE_SCRIPT,
  1084.     script_snapshot_finish,
  1085. };
  1086.  
  1087. static void
  1088. detach_snapshot (cairo_surface_t *abstract_surface)
  1089. {
  1090.     cairo_script_surface_t *surface = (cairo_script_surface_t *)abstract_surface;
  1091.     cairo_script_context_t *ctx = to_context (surface);
  1092.  
  1093.     _cairo_output_stream_printf (ctx->stream,
  1094.                                  "/s%d undef\n",
  1095.                                  surface->base.unique_id);
  1096. }
  1097.  
  1098. static void
  1099. attach_snapshot (cairo_script_context_t *ctx,
  1100.                  cairo_surface_t *source)
  1101. {
  1102.     struct script_snapshot *surface;
  1103.  
  1104.     if (! ctx->attach_snapshots)
  1105.         return;
  1106.  
  1107.     surface = malloc (sizeof (*surface));
  1108.     if (unlikely (surface == NULL))
  1109.         return;
  1110.  
  1111.     _cairo_surface_init (&surface->base,
  1112.                          &script_snapshot_backend,
  1113.                          &ctx->base,
  1114.                          source->content);
  1115.  
  1116.     _cairo_output_stream_printf (ctx->stream,
  1117.                                  "dup /s%d exch def ",
  1118.                                  surface->base.unique_id);
  1119.  
  1120.     _cairo_surface_attach_snapshot (source, &surface->base, detach_snapshot);
  1121.     cairo_surface_destroy (&surface->base);
  1122. }
  1123.  
  1124. static cairo_status_t
  1125. _emit_recording_surface_pattern (cairo_script_surface_t *surface,
  1126.                                  cairo_recording_surface_t *source)
  1127. {
  1128.     cairo_script_implicit_context_t old_cr;
  1129.     cairo_script_context_t *ctx = to_context (surface);
  1130.     cairo_script_surface_t *similar;
  1131.     cairo_surface_t *snapshot;
  1132.     cairo_rectangle_t r, *extents;
  1133.     cairo_status_t status;
  1134.  
  1135.     snapshot = _cairo_surface_has_snapshot (&source->base, &script_snapshot_backend);
  1136.     if (snapshot) {
  1137.         _cairo_output_stream_printf (ctx->stream, "s%d", snapshot->unique_id);
  1138.         return CAIRO_INT_STATUS_SUCCESS;
  1139.     }
  1140.  
  1141.     extents = NULL;
  1142.     if (_cairo_recording_surface_get_bounds (&source->base, &r))
  1143.         extents = &r;
  1144.  
  1145.     similar = _cairo_script_surface_create_internal (ctx,
  1146.                                                      source->base.content,
  1147.                                                      extents,
  1148.                                                      NULL);
  1149.     if (unlikely (similar->base.status))
  1150.         return similar->base.status;
  1151.  
  1152.     similar->base.is_clear = TRUE;
  1153.  
  1154.     _cairo_output_stream_printf (ctx->stream, "//%s ",
  1155.                                  _content_to_string (source->base.content));
  1156.     if (extents) {
  1157.         _cairo_output_stream_printf (ctx->stream, "[%f %f %f %f]",
  1158.                                      extents->x, extents->y,
  1159.                                      extents->width, extents->height);
  1160.     } else
  1161.         _cairo_output_stream_puts (ctx->stream, "[]");
  1162.     _cairo_output_stream_puts (ctx->stream, " record\n");
  1163.  
  1164.     attach_snapshot (ctx, &source->base);
  1165.  
  1166.     _cairo_output_stream_puts (ctx->stream, "dup context\n");
  1167.  
  1168.     target_push (similar);
  1169.     similar->emitted = TRUE;
  1170.  
  1171.  
  1172.     old_cr = surface->cr;
  1173.     _cairo_script_implicit_context_init (&surface->cr);
  1174.     status = _cairo_recording_surface_replay (&source->base, &similar->base);
  1175.     surface->cr = old_cr;
  1176.  
  1177.     if (unlikely (status)) {
  1178.         cairo_surface_destroy (&similar->base);
  1179.         return status;
  1180.     }
  1181.  
  1182.     cairo_list_del (&similar->operand.link);
  1183.     assert (target_is_active (surface));
  1184.  
  1185.     _cairo_output_stream_puts (ctx->stream, "pop ");
  1186.     cairo_surface_destroy (&similar->base);
  1187.  
  1188.     return CAIRO_STATUS_SUCCESS;
  1189. }
  1190.  
  1191. static cairo_status_t
  1192. _emit_script_surface_pattern (cairo_script_surface_t *surface,
  1193.                               cairo_script_surface_t *source)
  1194. {
  1195.     _get_target (source);
  1196.  
  1197.     return CAIRO_STATUS_SUCCESS;
  1198. }
  1199.  
  1200. static cairo_status_t
  1201. _write_image_surface (cairo_output_stream_t *output,
  1202.                       const cairo_image_surface_t *image)
  1203. {
  1204.     int stride, row, width;
  1205.     uint8_t row_stack[CAIRO_STACK_BUFFER_SIZE];
  1206.     uint8_t *rowdata;
  1207.     uint8_t *data;
  1208.  
  1209.     stride = image->stride;
  1210.     width = image->width;
  1211.     data = image->data;
  1212. #if WORDS_BIGENDIAN
  1213.     switch (image->format) {
  1214.     case CAIRO_FORMAT_A1:
  1215.         for (row = image->height; row--; ) {
  1216.             _cairo_output_stream_write (output, data, (width+7)/8);
  1217.             data += stride;
  1218.         }
  1219.         break;
  1220.     case CAIRO_FORMAT_A8:
  1221.         for (row = image->height; row--; ) {
  1222.             _cairo_output_stream_write (output, data, width);
  1223.             data += stride;
  1224.         }
  1225.         break;
  1226.     case CAIRO_FORMAT_RGB16_565:
  1227.         for (row = image->height; row--; ) {
  1228.             _cairo_output_stream_write (output, data, 2*width);
  1229.             data += stride;
  1230.         }
  1231.         break;
  1232.     case CAIRO_FORMAT_RGB24:
  1233.         for (row = image->height; row--; ) {
  1234.             int col;
  1235.             rowdata = data;
  1236.             for (col = width; col--; ) {
  1237.                 _cairo_output_stream_write (output, rowdata, 3);
  1238.                 rowdata+=4;
  1239.             }
  1240.             data += stride;
  1241.         }
  1242.         break;
  1243.     case CAIRO_FORMAT_ARGB32:
  1244.         for (row = image->height; row--; ) {
  1245.             _cairo_output_stream_write (output, data, 4*width);
  1246.             data += stride;
  1247.         }
  1248.         break;
  1249.     case CAIRO_FORMAT_INVALID:
  1250.     default:
  1251.         ASSERT_NOT_REACHED;
  1252.         break;
  1253.     }
  1254. #else
  1255.     if (stride > ARRAY_LENGTH (row_stack)) {
  1256.         rowdata = malloc (stride);
  1257.         if (unlikely (rowdata == NULL))
  1258.             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1259.     } else
  1260.         rowdata = row_stack;
  1261.  
  1262.     switch (image->format) {
  1263.     case CAIRO_FORMAT_A1:
  1264.         for (row = image->height; row--; ) {
  1265.             int col;
  1266.             for (col = 0; col < (width + 7)/8; col++)
  1267.                 rowdata[col] = CAIRO_BITSWAP8 (data[col]);
  1268.             _cairo_output_stream_write (output, rowdata, (width+7)/8);
  1269.             data += stride;
  1270.         }
  1271.         break;
  1272.     case CAIRO_FORMAT_A8:
  1273.         for (row = image->height; row--; ) {
  1274.             _cairo_output_stream_write (output, data, width);
  1275.             data += stride;
  1276.         }
  1277.         break;
  1278.     case CAIRO_FORMAT_RGB16_565:
  1279.         for (row = image->height; row--; ) {
  1280.             uint16_t *src = (uint16_t *) data;
  1281.             uint16_t *dst = (uint16_t *) rowdata;
  1282.             int col;
  1283.             for (col = 0; col < width; col++)
  1284.                 dst[col] = bswap_16 (src[col]);
  1285.             _cairo_output_stream_write (output, rowdata, 2*width);
  1286.             data += stride;
  1287.         }
  1288.         break;
  1289.     case CAIRO_FORMAT_RGB24:
  1290.         for (row = image->height; row--; ) {
  1291.             uint8_t *src = data;
  1292.             int col;
  1293.             for (col = 0; col < width; col++) {
  1294.                 rowdata[3*col+2] = *src++;
  1295.                 rowdata[3*col+1] = *src++;
  1296.                 rowdata[3*col+0] = *src++;
  1297.                 src++;
  1298.             }
  1299.             _cairo_output_stream_write (output, rowdata, 3*width);
  1300.             data += stride;
  1301.         }
  1302.         break;
  1303.     case CAIRO_FORMAT_RGB30:
  1304.     case CAIRO_FORMAT_ARGB32:
  1305.         for (row = image->height; row--; ) {
  1306.             uint32_t *src = (uint32_t *) data;
  1307.             uint32_t *dst = (uint32_t *) rowdata;
  1308.             int col;
  1309.             for (col = 0; col < width; col++)
  1310.                 dst[col] = bswap_32 (src[col]);
  1311.             _cairo_output_stream_write (output, rowdata, 4*width);
  1312.             data += stride;
  1313.         }
  1314.         break;
  1315.     case CAIRO_FORMAT_INVALID:
  1316.     default:
  1317.         ASSERT_NOT_REACHED;
  1318.         break;
  1319.     }
  1320.     if (rowdata != row_stack)
  1321.         free (rowdata);
  1322. #endif
  1323.  
  1324.     return CAIRO_STATUS_SUCCESS;
  1325. }
  1326.  
  1327. static cairo_int_status_t
  1328. _emit_png_surface (cairo_script_surface_t *surface,
  1329.                    cairo_image_surface_t *image)
  1330. {
  1331.     cairo_script_context_t *ctx = to_context (surface);
  1332.     cairo_output_stream_t *base85_stream;
  1333.     cairo_status_t status;
  1334.     const uint8_t *mime_data;
  1335.     unsigned long mime_data_length;
  1336.  
  1337.     cairo_surface_get_mime_data (&image->base, CAIRO_MIME_TYPE_PNG,
  1338.                                  &mime_data, &mime_data_length);
  1339.     if (mime_data == NULL)
  1340.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1341.  
  1342.     _cairo_output_stream_printf (ctx->stream,
  1343.                                  "<< "
  1344.                                  "/width %d "
  1345.                                  "/height %d "
  1346.                                  "/format //%s "
  1347.                                  "/mime-type (image/png) "
  1348.                                  "/source <~",
  1349.                                  image->width, image->height,
  1350.                                  _format_to_string (image->format));
  1351.  
  1352.     base85_stream = _cairo_base85_stream_create (ctx->stream);
  1353.     _cairo_output_stream_write (base85_stream, mime_data, mime_data_length);
  1354.     status = _cairo_output_stream_destroy (base85_stream);
  1355.     if (unlikely (status))
  1356.         return status;
  1357.  
  1358.     _cairo_output_stream_puts (ctx->stream, "~> >> image ");
  1359.     return CAIRO_STATUS_SUCCESS;
  1360. }
  1361.  
  1362. static cairo_int_status_t
  1363. _emit_image_surface (cairo_script_surface_t *surface,
  1364.                      cairo_image_surface_t *image)
  1365. {
  1366.     cairo_script_context_t *ctx = to_context (surface);
  1367.     cairo_output_stream_t *base85_stream;
  1368.     cairo_output_stream_t *zlib_stream;
  1369.     cairo_int_status_t status, status2;
  1370.     cairo_surface_t *snapshot;
  1371.     const uint8_t *mime_data;
  1372.     unsigned long mime_data_length;
  1373.  
  1374.     snapshot = _cairo_surface_has_snapshot (&image->base,
  1375.                                             &script_snapshot_backend);
  1376.     if (snapshot) {
  1377.         _cairo_output_stream_printf (ctx->stream, "s%u ", snapshot->unique_id);
  1378.         return CAIRO_INT_STATUS_SUCCESS;
  1379.     }
  1380.  
  1381.     status = _emit_png_surface (surface, image);
  1382.     if (_cairo_int_status_is_error (status)) {
  1383.         return status;
  1384.     } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
  1385.         cairo_image_surface_t *clone;
  1386.         uint32_t len;
  1387.  
  1388.         if (image->format == CAIRO_FORMAT_INVALID) {
  1389.             clone = _cairo_image_surface_coerce (image);
  1390.         } else {
  1391.             clone = (cairo_image_surface_t *)
  1392.                 cairo_surface_reference (&image->base);
  1393.         }
  1394.  
  1395.         _cairo_output_stream_printf (ctx->stream,
  1396.                                      "<< "
  1397.                                      "/width %d "
  1398.                                      "/height %d "
  1399.                                      "/format //%s "
  1400.                                      "/source ",
  1401.                                      clone->width, clone->height,
  1402.                                      _format_to_string (clone->format));
  1403.  
  1404.         switch (clone->format) {
  1405.         case CAIRO_FORMAT_A1:
  1406.             len = (clone->width + 7)/8;
  1407.             break;
  1408.         case CAIRO_FORMAT_A8:
  1409.             len = clone->width;
  1410.             break;
  1411.         case CAIRO_FORMAT_RGB16_565:
  1412.             len = clone->width * 2;
  1413.             break;
  1414.         case CAIRO_FORMAT_RGB24:
  1415.             len = clone->width * 3;
  1416.             break;
  1417.         case CAIRO_FORMAT_RGB30:
  1418.         case CAIRO_FORMAT_ARGB32:
  1419.             len = clone->width * 4;
  1420.             break;
  1421.         case CAIRO_FORMAT_INVALID:
  1422.         default:
  1423.             ASSERT_NOT_REACHED;
  1424.             len = 0;
  1425.             break;
  1426.         }
  1427.         len *= clone->height;
  1428.  
  1429.         if (len > 24) {
  1430.             _cairo_output_stream_puts (ctx->stream, "<|");
  1431.  
  1432.             base85_stream = _cairo_base85_stream_create (ctx->stream);
  1433.  
  1434.             len = to_be32 (len);
  1435.             _cairo_output_stream_write (base85_stream, &len, sizeof (len));
  1436.  
  1437.             zlib_stream = _cairo_deflate_stream_create (base85_stream);
  1438.             status = _write_image_surface (zlib_stream, clone);
  1439.  
  1440.             status2 = _cairo_output_stream_destroy (zlib_stream);
  1441.             if (status == CAIRO_INT_STATUS_SUCCESS)
  1442.                 status = status2;
  1443.             status2 = _cairo_output_stream_destroy (base85_stream);
  1444.             if (status == CAIRO_INT_STATUS_SUCCESS)
  1445.                 status = status2;
  1446.             if (unlikely (status))
  1447.                 return status;
  1448.         } else {
  1449.             _cairo_output_stream_puts (ctx->stream, "<~");
  1450.  
  1451.             base85_stream = _cairo_base85_stream_create (ctx->stream);
  1452.             status = _write_image_surface (base85_stream, clone);
  1453.             status2 = _cairo_output_stream_destroy (base85_stream);
  1454.             if (status == CAIRO_INT_STATUS_SUCCESS)
  1455.                 status = status2;
  1456.             if (unlikely (status))
  1457.                 return status;
  1458.         }
  1459.         _cairo_output_stream_puts (ctx->stream, "~> >> image ");
  1460.  
  1461.         cairo_surface_destroy (&clone->base);
  1462.     }
  1463.  
  1464.     cairo_surface_get_mime_data (&image->base, CAIRO_MIME_TYPE_JPEG,
  1465.                                  &mime_data, &mime_data_length);
  1466.     if (mime_data != NULL) {
  1467.         _cairo_output_stream_printf (ctx->stream,
  1468.                                      "\n  (%s) <~",
  1469.                                      CAIRO_MIME_TYPE_JPEG);
  1470.  
  1471.         base85_stream = _cairo_base85_stream_create (ctx->stream);
  1472.         _cairo_output_stream_write (base85_stream, mime_data, mime_data_length);
  1473.         status = _cairo_output_stream_destroy (base85_stream);
  1474.         if (unlikely (status))
  1475.             return status;
  1476.  
  1477.         _cairo_output_stream_puts (ctx->stream, "~> set-mime-data\n");
  1478.     }
  1479.  
  1480.     cairo_surface_get_mime_data (&image->base, CAIRO_MIME_TYPE_JP2,
  1481.                                  &mime_data, &mime_data_length);
  1482.     if (mime_data != NULL) {
  1483.         _cairo_output_stream_printf (ctx->stream,
  1484.                                      "\n  (%s) <~",
  1485.                                      CAIRO_MIME_TYPE_JP2);
  1486.  
  1487.         base85_stream = _cairo_base85_stream_create (ctx->stream);
  1488.         _cairo_output_stream_write (base85_stream, mime_data, mime_data_length);
  1489.         status = _cairo_output_stream_destroy (base85_stream);
  1490.         if (unlikely (status))
  1491.             return status;
  1492.  
  1493.         _cairo_output_stream_puts (ctx->stream, "~> set-mime-data\n");
  1494.     }
  1495.  
  1496.     return CAIRO_INT_STATUS_SUCCESS;
  1497. }
  1498.  
  1499. static cairo_int_status_t
  1500. _emit_image_surface_pattern (cairo_script_surface_t *surface,
  1501.                              cairo_surface_t *source)
  1502. {
  1503.     cairo_image_surface_t *image;
  1504.     cairo_status_t status;
  1505.     void *extra;
  1506.  
  1507.     status = _cairo_surface_acquire_source_image (source, &image, &extra);
  1508.     if (likely (status == CAIRO_STATUS_SUCCESS)) {
  1509.         status = _emit_image_surface (surface, image);
  1510.         _cairo_surface_release_source_image (source, image, extra);
  1511.     }
  1512.  
  1513.     return status;
  1514. }
  1515.  
  1516. static cairo_int_status_t
  1517. _emit_subsurface_pattern (cairo_script_surface_t *surface,
  1518.                           cairo_surface_subsurface_t *sub)
  1519. {
  1520.     cairo_surface_t *source = sub->target;
  1521.     cairo_int_status_t status;
  1522.  
  1523.     switch ((int) source->backend->type) {
  1524.     case CAIRO_SURFACE_TYPE_RECORDING:
  1525.         status = _emit_recording_surface_pattern (surface, (cairo_recording_surface_t *) source);
  1526.         break;
  1527.     case CAIRO_SURFACE_TYPE_SCRIPT:
  1528.         status = _emit_script_surface_pattern (surface, (cairo_script_surface_t *) source);
  1529.         break;
  1530.     default:
  1531.         status = _emit_image_surface_pattern (surface, source);
  1532.         break;
  1533.     }
  1534.     if (unlikely (status))
  1535.         return status;
  1536.  
  1537.     _cairo_output_stream_printf (to_context (surface)->stream,
  1538.                                  "%d %d %d %d subsurface ",
  1539.                                  sub->extents.x,
  1540.                                  sub->extents.y,
  1541.                                  sub->extents.width,
  1542.                                  sub->extents.height);
  1543.     return CAIRO_INT_STATUS_SUCCESS;
  1544. }
  1545.  
  1546. static cairo_int_status_t
  1547. _emit_surface_pattern (cairo_script_surface_t *surface,
  1548.                        const cairo_pattern_t *pattern)
  1549. {
  1550.     cairo_script_context_t *ctx = to_context (surface);
  1551.     cairo_surface_pattern_t *surface_pattern;
  1552.     cairo_surface_t *source, *snapshot, *free_me = NULL;
  1553.     cairo_surface_t *take_snapshot = NULL;
  1554.     cairo_int_status_t status;
  1555.  
  1556.     surface_pattern = (cairo_surface_pattern_t *) pattern;
  1557.     source = surface_pattern->surface;
  1558.  
  1559.     if (_cairo_surface_is_snapshot (source)) {
  1560.         snapshot = _cairo_surface_has_snapshot (source, &script_snapshot_backend);
  1561.         if (snapshot) {
  1562.             _cairo_output_stream_printf (ctx->stream,
  1563.                                          "s%d pattern ",
  1564.                                          snapshot->unique_id);
  1565.             return CAIRO_INT_STATUS_SUCCESS;
  1566.         }
  1567.  
  1568.         if (_cairo_surface_snapshot_is_reused (source))
  1569.             take_snapshot = source;
  1570.  
  1571.         free_me = source = _cairo_surface_snapshot_get_target (source);
  1572.     }
  1573.  
  1574.     switch ((int) source->backend->type) {
  1575.     case CAIRO_SURFACE_TYPE_RECORDING:
  1576.         status = _emit_recording_surface_pattern (surface, (cairo_recording_surface_t *) source);
  1577.         break;
  1578.     case CAIRO_SURFACE_TYPE_SCRIPT:
  1579.         status = _emit_script_surface_pattern (surface, (cairo_script_surface_t *) source);
  1580.         break;
  1581.     case CAIRO_SURFACE_TYPE_SUBSURFACE:
  1582.         status = _emit_subsurface_pattern (surface, (cairo_surface_subsurface_t *) source);
  1583.         break;
  1584.     default:
  1585.         status = _emit_image_surface_pattern (surface, source);
  1586.         break;
  1587.     }
  1588.     cairo_surface_destroy (free_me);
  1589.     if (unlikely (status))
  1590.         return status;
  1591.  
  1592.     if (take_snapshot)
  1593.         attach_snapshot (ctx, take_snapshot);
  1594.  
  1595.     _cairo_output_stream_puts (ctx->stream, "pattern");
  1596.     return CAIRO_INT_STATUS_SUCCESS;
  1597. }
  1598.  
  1599. static cairo_int_status_t
  1600. _emit_raster_pattern (cairo_script_surface_t *surface,
  1601.                       const cairo_pattern_t *pattern)
  1602. {
  1603.     cairo_surface_t *source;
  1604.     cairo_int_status_t status;
  1605.  
  1606.     source = _cairo_raster_source_pattern_acquire (pattern, &surface->base, NULL);
  1607.     if (unlikely (source == NULL)) {
  1608.         ASSERT_NOT_REACHED;
  1609.         return CAIRO_INT_STATUS_UNSUPPORTED;
  1610.     }
  1611.     if (unlikely (source->status))
  1612.         return source->status;
  1613.  
  1614.     status = _emit_image_surface_pattern (surface, source);
  1615.     _cairo_raster_source_pattern_release (pattern, source);
  1616.     if (unlikely (status))
  1617.         return status;
  1618.  
  1619.     _cairo_output_stream_puts (to_context(surface)->stream, "pattern");
  1620.     return CAIRO_INT_STATUS_SUCCESS;
  1621. }
  1622.  
  1623. static cairo_int_status_t
  1624. _emit_pattern (cairo_script_surface_t *surface,
  1625.                const cairo_pattern_t *pattern)
  1626. {
  1627.     cairo_script_context_t *ctx = to_context (surface);
  1628.     cairo_int_status_t status;
  1629.     cairo_bool_t is_default_extend;
  1630.     cairo_bool_t need_newline = TRUE;
  1631.  
  1632.     switch (pattern->type) {
  1633.     case CAIRO_PATTERN_TYPE_SOLID:
  1634.         /* solid colors do not need filter/extend/matrix */
  1635.         return _emit_solid_pattern (surface, pattern);
  1636.  
  1637.     case CAIRO_PATTERN_TYPE_LINEAR:
  1638.         status = _emit_linear_pattern (surface, pattern);
  1639.         is_default_extend = pattern->extend == CAIRO_EXTEND_GRADIENT_DEFAULT;
  1640.         break;
  1641.     case CAIRO_PATTERN_TYPE_RADIAL:
  1642.         status = _emit_radial_pattern (surface, pattern);
  1643.         is_default_extend = pattern->extend == CAIRO_EXTEND_GRADIENT_DEFAULT;
  1644.         break;
  1645.     case CAIRO_PATTERN_TYPE_MESH:
  1646.         status = _emit_mesh_pattern (surface, pattern);
  1647.         is_default_extend = TRUE;
  1648.         break;
  1649.     case CAIRO_PATTERN_TYPE_SURFACE:
  1650.         status = _emit_surface_pattern (surface, pattern);
  1651.         is_default_extend = pattern->extend == CAIRO_EXTEND_SURFACE_DEFAULT;
  1652.         break;
  1653.     case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
  1654.         status = _emit_raster_pattern (surface, pattern);
  1655.         is_default_extend = pattern->extend == CAIRO_EXTEND_SURFACE_DEFAULT;
  1656.         break;
  1657.  
  1658.     default:
  1659.         ASSERT_NOT_REACHED;
  1660.         status = CAIRO_INT_STATUS_UNSUPPORTED;
  1661.     }
  1662.     if (unlikely (status))
  1663.         return status;
  1664.  
  1665.     if (! _cairo_matrix_is_identity (&pattern->matrix)) {
  1666.         if (need_newline) {
  1667.             _cairo_output_stream_puts (ctx->stream, "\n ");
  1668.             need_newline = FALSE;
  1669.         }
  1670.  
  1671.         _cairo_output_stream_printf (ctx->stream,
  1672.                                      " [%f %f %f %f %f %f] set-matrix\n ",
  1673.                                      pattern->matrix.xx, pattern->matrix.yx,
  1674.                                      pattern->matrix.xy, pattern->matrix.yy,
  1675.                                      pattern->matrix.x0, pattern->matrix.y0);
  1676.     }
  1677.  
  1678.     /* XXX need to discriminate the user explicitly setting the default */
  1679.     if (pattern->filter != CAIRO_FILTER_DEFAULT) {
  1680.         if (need_newline) {
  1681.             _cairo_output_stream_puts (ctx->stream, "\n ");
  1682.             need_newline = FALSE;
  1683.         }
  1684.  
  1685.         _cairo_output_stream_printf (ctx->stream,
  1686.                                      " //%s set-filter\n ",
  1687.                                      _filter_to_string (pattern->filter));
  1688.     }
  1689.     if (! is_default_extend ){
  1690.         if (need_newline) {
  1691.             _cairo_output_stream_puts (ctx->stream, "\n ");
  1692.             need_newline = FALSE;
  1693.         }
  1694.  
  1695.         _cairo_output_stream_printf (ctx->stream,
  1696.                                      " //%s set-extend\n ",
  1697.                                      _extend_to_string (pattern->extend));
  1698.     }
  1699.  
  1700.     if (need_newline)
  1701.         _cairo_output_stream_puts (ctx->stream, "\n ");
  1702.  
  1703.     return CAIRO_INT_STATUS_SUCCESS;
  1704. }
  1705.  
  1706. static cairo_int_status_t
  1707. _emit_identity (cairo_script_surface_t *surface,
  1708.                 cairo_bool_t *matrix_updated)
  1709. {
  1710.     assert (target_is_active (surface));
  1711.  
  1712.     if (_cairo_matrix_is_identity (&surface->cr.current_ctm))
  1713.         return CAIRO_INT_STATUS_SUCCESS;
  1714.  
  1715.     _cairo_output_stream_puts (to_context (surface)->stream,
  1716.                                "identity set-matrix\n");
  1717.  
  1718.     *matrix_updated = TRUE;
  1719.     cairo_matrix_init_identity (&surface->cr.current_ctm);
  1720.  
  1721.     return CAIRO_INT_STATUS_SUCCESS;
  1722. }
  1723.  
  1724. static cairo_int_status_t
  1725. _emit_source (cairo_script_surface_t *surface,
  1726.               cairo_operator_t op,
  1727.               const cairo_pattern_t *source)
  1728. {
  1729.     cairo_bool_t matrix_updated = FALSE;
  1730.     cairo_int_status_t status;
  1731.  
  1732.     assert (target_is_active (surface));
  1733.  
  1734.     if (op == CAIRO_OPERATOR_CLEAR) {
  1735.         /* the source is ignored, so don't change it */
  1736.         return CAIRO_INT_STATUS_SUCCESS;
  1737.     }
  1738.  
  1739.     if (_cairo_pattern_equal (&surface->cr.current_source.base, source))
  1740.         return CAIRO_INT_STATUS_SUCCESS;
  1741.  
  1742.     _cairo_pattern_fini (&surface->cr.current_source.base);
  1743.     status = _cairo_pattern_init_copy (&surface->cr.current_source.base,
  1744.                                        source);
  1745.     if (unlikely (status))
  1746.         return status;
  1747.  
  1748.     status = _emit_identity (surface, &matrix_updated);
  1749.     if (unlikely (status))
  1750.         return status;
  1751.  
  1752.     status = _emit_pattern (surface, source);
  1753.     if (unlikely (status))
  1754.         return status;
  1755.  
  1756.     assert (target_is_active (surface));
  1757.     _cairo_output_stream_puts (to_context (surface)->stream,
  1758.                                " set-source\n");
  1759.     return CAIRO_INT_STATUS_SUCCESS;
  1760. }
  1761.  
  1762. static cairo_status_t
  1763. _path_move_to (void *closure,
  1764.                const cairo_point_t *point)
  1765. {
  1766.     _cairo_output_stream_printf (closure,
  1767.                                  " %f %f m",
  1768.                                  _cairo_fixed_to_double (point->x),
  1769.                                  _cairo_fixed_to_double (point->y));
  1770.  
  1771.     return CAIRO_STATUS_SUCCESS;
  1772. }
  1773.  
  1774. static cairo_status_t
  1775. _path_line_to (void *closure,
  1776.                const cairo_point_t *point)
  1777. {
  1778.     _cairo_output_stream_printf (closure,
  1779.                                  " %f %f l",
  1780.                                  _cairo_fixed_to_double (point->x),
  1781.                                  _cairo_fixed_to_double (point->y));
  1782.  
  1783.     return CAIRO_STATUS_SUCCESS;
  1784. }
  1785.  
  1786. static cairo_status_t
  1787. _path_curve_to (void *closure,
  1788.                 const cairo_point_t *p1,
  1789.                 const cairo_point_t *p2,
  1790.                 const cairo_point_t *p3)
  1791. {
  1792.     _cairo_output_stream_printf (closure,
  1793.                                  " %f %f %f %f %f %f c",
  1794.                                  _cairo_fixed_to_double (p1->x),
  1795.                                  _cairo_fixed_to_double (p1->y),
  1796.                                  _cairo_fixed_to_double (p2->x),
  1797.                                  _cairo_fixed_to_double (p2->y),
  1798.                                  _cairo_fixed_to_double (p3->x),
  1799.                                  _cairo_fixed_to_double (p3->y));
  1800.  
  1801.     return CAIRO_STATUS_SUCCESS;
  1802. }
  1803.  
  1804. static cairo_status_t
  1805. _path_close (void *closure)
  1806. {
  1807.     _cairo_output_stream_printf (closure,
  1808.                                  " h");
  1809.  
  1810.     return CAIRO_STATUS_SUCCESS;
  1811. }
  1812.  
  1813. static cairo_status_t
  1814. _emit_path_boxes (cairo_script_surface_t *surface,
  1815.                   const cairo_path_fixed_t *path)
  1816. {
  1817.     cairo_script_context_t *ctx = to_context (surface);
  1818.     cairo_path_fixed_iter_t iter;
  1819.     cairo_status_t status;
  1820.     struct _cairo_boxes_chunk *chunk;
  1821.     cairo_boxes_t boxes;
  1822.     cairo_box_t box;
  1823.     int i;
  1824.  
  1825.     _cairo_boxes_init (&boxes);
  1826.     _cairo_path_fixed_iter_init (&iter, path);
  1827.     while (_cairo_path_fixed_iter_is_fill_box (&iter, &box)) {
  1828.         if (box.p1.y == box.p2.y || box.p1.x == box.p2.x)
  1829.             continue;
  1830.  
  1831.         status = _cairo_boxes_add (&boxes, CAIRO_ANTIALIAS_DEFAULT, &box);
  1832.         if (unlikely (status)) {
  1833.             _cairo_boxes_fini (&boxes);
  1834.             return status;
  1835.         }
  1836.     }
  1837.  
  1838.     if (! _cairo_path_fixed_iter_at_end (&iter)) {
  1839.         _cairo_boxes_fini (&boxes);
  1840.         return FALSE;
  1841.     }
  1842.  
  1843.     for (chunk = &boxes.chunks; chunk; chunk = chunk->next) {
  1844.         for (i = 0; i < chunk->count; i++) {
  1845.             const cairo_box_t *b = &chunk->base[i];
  1846.             double x1 = _cairo_fixed_to_double (b->p1.x);
  1847.             double y1 = _cairo_fixed_to_double (b->p1.y);
  1848.             double x2 = _cairo_fixed_to_double (b->p2.x);
  1849.             double y2 = _cairo_fixed_to_double (b->p2.y);
  1850.  
  1851.             _cairo_output_stream_printf (ctx->stream,
  1852.                                          "\n  %f %f %f %f rectangle",
  1853.                                          x1, y1, x2 - x1, y2 - y1);
  1854.         }
  1855.     }
  1856.  
  1857.     _cairo_boxes_fini (&boxes);
  1858.     return status;
  1859. }
  1860.  
  1861. static cairo_status_t
  1862. _emit_path (cairo_script_surface_t *surface,
  1863.             const cairo_path_fixed_t *path,
  1864.             cairo_bool_t is_fill)
  1865. {
  1866.     cairo_script_context_t *ctx = to_context (surface);
  1867.     cairo_box_t box;
  1868.     cairo_int_status_t status;
  1869.  
  1870.     assert (target_is_active (surface));
  1871.     assert (_cairo_matrix_is_identity (&surface->cr.current_ctm));
  1872.  
  1873.     if (_cairo_path_fixed_equal (&surface->cr.current_path, path))
  1874.         return CAIRO_STATUS_SUCCESS;
  1875.  
  1876.     _cairo_path_fixed_fini (&surface->cr.current_path);
  1877.  
  1878.     _cairo_output_stream_puts (ctx->stream, "n");
  1879.  
  1880.     if (path == NULL) {
  1881.         _cairo_path_fixed_init (&surface->cr.current_path);
  1882.         _cairo_output_stream_puts (ctx->stream, "\n");
  1883.         return CAIRO_STATUS_SUCCESS;
  1884.     }
  1885.  
  1886.     status = _cairo_path_fixed_init_copy (&surface->cr.current_path, path);
  1887.     if (unlikely (status))
  1888.         return status;
  1889.  
  1890.     status = CAIRO_INT_STATUS_UNSUPPORTED;
  1891.     if (_cairo_path_fixed_is_rectangle (path, &box)) {
  1892.         double x1 = _cairo_fixed_to_double (box.p1.x);
  1893.         double y1 = _cairo_fixed_to_double (box.p1.y);
  1894.         double x2 = _cairo_fixed_to_double (box.p2.x);
  1895.         double y2 = _cairo_fixed_to_double (box.p2.y);
  1896.  
  1897.         assert (x1 > -9999);
  1898.  
  1899.         _cairo_output_stream_printf (ctx->stream,
  1900.                                      " %f %f %f %f rectangle",
  1901.                                      x1, y1, x2 - x1, y2 - y1);
  1902.         status = CAIRO_INT_STATUS_SUCCESS;
  1903.     } else if (is_fill && _cairo_path_fixed_fill_is_rectilinear (path)) {
  1904.         status = _emit_path_boxes (surface, path);
  1905.     }
  1906.  
  1907.     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
  1908.         status = _cairo_path_fixed_interpret (path,
  1909.                                               _path_move_to,
  1910.                                               _path_line_to,
  1911.                                               _path_curve_to,
  1912.                                               _path_close,
  1913.                                               ctx->stream);
  1914.     }
  1915.  
  1916.     _cairo_output_stream_puts (ctx->stream, "\n");
  1917.  
  1918.     return status;
  1919. }
  1920. static cairo_bool_t
  1921. _scaling_matrix_equal (const cairo_matrix_t *a,
  1922.                        const cairo_matrix_t *b)
  1923. {
  1924.     return fabs (a->xx - b->xx) < 1e-5 &&
  1925.            fabs (a->xy - b->xy) < 1e-5 &&
  1926.            fabs (a->yx - b->yx) < 1e-5 &&
  1927.            fabs (a->yy - b->yy) < 1e-5;
  1928. }
  1929.  
  1930. static cairo_status_t
  1931. _emit_scaling_matrix (cairo_script_surface_t *surface,
  1932.                       const cairo_matrix_t *ctm,
  1933.                       cairo_bool_t *matrix_updated)
  1934. {
  1935.     cairo_script_context_t *ctx = to_context (surface);
  1936.     cairo_bool_t was_identity;
  1937.     assert (target_is_active (surface));
  1938.  
  1939.     if (_scaling_matrix_equal (&surface->cr.current_ctm, ctm))
  1940.         return CAIRO_STATUS_SUCCESS;
  1941.  
  1942.     was_identity = _cairo_matrix_is_identity (&surface->cr.current_ctm);
  1943.  
  1944.     *matrix_updated = TRUE;
  1945.     surface->cr.current_ctm = *ctm;
  1946.     surface->cr.current_ctm.x0 = 0.;
  1947.     surface->cr.current_ctm.y0 = 0.;
  1948.  
  1949.     if (_cairo_matrix_is_identity (&surface->cr.current_ctm)) {
  1950.         _cairo_output_stream_puts (ctx->stream,
  1951.                                    "identity set-matrix\n");
  1952.     } else if (was_identity && fabs (ctm->yx) < 1e-5 && fabs (ctm->xy) < 1e-5) {
  1953.         _cairo_output_stream_printf (ctx->stream,
  1954.                                      "%f %f scale\n",
  1955.                                      ctm->xx, ctm->yy);
  1956.     } else {
  1957.         _cairo_output_stream_printf (ctx->stream,
  1958.                                      "[%f %f %f %f 0 0] set-matrix\n",
  1959.                                      ctm->xx, ctm->yx,
  1960.                                      ctm->xy, ctm->yy);
  1961.     }
  1962.  
  1963.     return CAIRO_STATUS_SUCCESS;
  1964. }
  1965.  
  1966. static cairo_status_t
  1967. _emit_font_matrix (cairo_script_surface_t *surface,
  1968.                    const cairo_matrix_t *font_matrix)
  1969. {
  1970.     cairo_script_context_t *ctx = to_context (surface);
  1971.     assert (target_is_active (surface));
  1972.  
  1973.     if (memcmp (&surface->cr.current_font_matrix,
  1974.                 font_matrix,
  1975.                 sizeof (cairo_matrix_t)) == 0)
  1976.     {
  1977.         return CAIRO_STATUS_SUCCESS;
  1978.     }
  1979.  
  1980.     surface->cr.current_font_matrix = *font_matrix;
  1981.  
  1982.     if (_cairo_matrix_is_identity (font_matrix)) {
  1983.         _cairo_output_stream_puts (ctx->stream,
  1984.                                    "identity set-font-matrix\n");
  1985.     } else {
  1986.         _cairo_output_stream_printf (ctx->stream,
  1987.                                      "[%f %f %f %f %f %f] set-font-matrix\n",
  1988.                                      font_matrix->xx, font_matrix->yx,
  1989.                                      font_matrix->xy, font_matrix->yy,
  1990.                                      font_matrix->x0, font_matrix->y0);
  1991.     }
  1992.  
  1993.     return CAIRO_STATUS_SUCCESS;
  1994. }
  1995.  
  1996. static cairo_surface_t *
  1997. _cairo_script_surface_create_similar (void             *abstract_surface,
  1998.                                       cairo_content_t   content,
  1999.                                       int               width,
  2000.                                       int               height)
  2001. {
  2002.     cairo_script_surface_t *surface, *other = abstract_surface;
  2003.     cairo_surface_t *passthrough = NULL;
  2004.     cairo_script_context_t *ctx;
  2005.     cairo_rectangle_t extents;
  2006.     cairo_status_t status;
  2007.  
  2008.     ctx = to_context (other);
  2009.  
  2010.     status = cairo_device_acquire (&ctx->base);
  2011.     if (unlikely (status))
  2012.         return _cairo_surface_create_in_error (status);
  2013.  
  2014.     if (! other->emitted) {
  2015.         status = _emit_surface (other);
  2016.         if (unlikely (status)) {
  2017.             cairo_device_release (&ctx->base);
  2018.             return _cairo_surface_create_in_error (status);
  2019.         }
  2020.  
  2021.         target_push (other);
  2022.     }
  2023.  
  2024.     if (_cairo_surface_wrapper_is_active (&other->wrapper)) {
  2025.         passthrough =
  2026.             _cairo_surface_wrapper_create_similar (&other->wrapper,
  2027.                                                    content, width, height);
  2028.         if (unlikely (passthrough->status)) {
  2029.             cairo_device_release (&ctx->base);
  2030.             return passthrough;
  2031.         }
  2032.     }
  2033.  
  2034.     extents.x = extents.y = 0;
  2035.     extents.width = width;
  2036.     extents.height = height;
  2037.     surface = _cairo_script_surface_create_internal (ctx, content,
  2038.                                                      &extents, passthrough);
  2039.     cairo_surface_destroy (passthrough);
  2040.  
  2041.     if (unlikely (surface->base.status)) {
  2042.         cairo_device_release (&ctx->base);
  2043.         return &surface->base;
  2044.     }
  2045.  
  2046.     _get_target (other);
  2047.     _cairo_output_stream_printf (ctx->stream,
  2048.                                  "%u %u //%s similar dup /s%u exch def context\n",
  2049.                                  width, height,
  2050.                                  _content_to_string (content),
  2051.                                  surface->base.unique_id);
  2052.  
  2053.     surface->emitted = TRUE;
  2054.     surface->defined = TRUE;
  2055.     surface->base.is_clear = TRUE;
  2056.     target_push (surface);
  2057.  
  2058.     cairo_device_release (&ctx->base);
  2059.     return &surface->base;
  2060. }
  2061.  
  2062. static cairo_status_t
  2063. _device_flush (void *abstract_device)
  2064. {
  2065.     cairo_script_context_t *ctx = abstract_device;
  2066.  
  2067.     return _cairo_output_stream_flush (ctx->stream);
  2068. }
  2069.  
  2070. static void
  2071. _device_destroy (void *abstract_device)
  2072. {
  2073.     cairo_script_context_t *ctx = abstract_device;
  2074.     cairo_status_t status;
  2075.  
  2076.     while (! cairo_list_is_empty (&ctx->fonts)) {
  2077.         cairo_script_font_t *font;
  2078.  
  2079.         font = cairo_list_first_entry (&ctx->fonts, cairo_script_font_t, link);
  2080.         cairo_list_del (&font->base.link);
  2081.         cairo_list_del (&font->link);
  2082.         free (font);
  2083.     }
  2084.  
  2085.     _bitmap_fini (ctx->surface_id.next);
  2086.     _bitmap_fini (ctx->font_id.next);
  2087.  
  2088.     if (ctx->owns_stream)
  2089.         status = _cairo_output_stream_destroy (ctx->stream);
  2090.  
  2091.     free (ctx);
  2092. }
  2093.  
  2094. static cairo_surface_t *
  2095. _cairo_script_surface_source (void                    *abstract_surface,
  2096.                               cairo_rectangle_int_t     *extents)
  2097. {
  2098.     cairo_script_surface_t *surface = abstract_surface;
  2099.  
  2100.     if (extents) {
  2101.         extents->x = extents->y = 0;
  2102.         extents->width  = surface->width;
  2103.         extents->height = surface->height;
  2104.     }
  2105.  
  2106.     return &surface->base;
  2107. }
  2108.  
  2109. static cairo_status_t
  2110. _cairo_script_surface_acquire_source_image (void                    *abstract_surface,
  2111.                                             cairo_image_surface_t  **image_out,
  2112.                                             void                   **image_extra)
  2113. {
  2114.     cairo_script_surface_t *surface = abstract_surface;
  2115.  
  2116.     if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
  2117.         return _cairo_surface_wrapper_acquire_source_image (&surface->wrapper,
  2118.                                                             image_out,
  2119.                                                             image_extra);
  2120.     }
  2121.  
  2122.     return CAIRO_INT_STATUS_UNSUPPORTED;
  2123. }
  2124.  
  2125. static void
  2126. _cairo_script_surface_release_source_image (void                   *abstract_surface,
  2127.                                            cairo_image_surface_t  *image,
  2128.                                            void                   *image_extra)
  2129. {
  2130.     cairo_script_surface_t *surface = abstract_surface;
  2131.  
  2132.     assert (_cairo_surface_wrapper_is_active (&surface->wrapper));
  2133.     _cairo_surface_wrapper_release_source_image (&surface->wrapper,
  2134.                                                  image,
  2135.                                                  image_extra);
  2136. }
  2137.  
  2138. static cairo_status_t
  2139. _cairo_script_surface_finish (void *abstract_surface)
  2140. {
  2141.     cairo_script_surface_t *surface = abstract_surface;
  2142.     cairo_script_context_t *ctx = to_context (surface);
  2143.     cairo_status_t status = CAIRO_STATUS_SUCCESS, status2;
  2144.  
  2145.     _cairo_surface_wrapper_fini (&surface->wrapper);
  2146.  
  2147.     free (surface->cr.current_style.dash);
  2148.     surface->cr.current_style.dash = NULL;
  2149.  
  2150.     _cairo_pattern_fini (&surface->cr.current_source.base);
  2151.     _cairo_path_fixed_fini (&surface->cr.current_path);
  2152.     _cairo_surface_clipper_reset (&surface->clipper);
  2153.  
  2154.     status = cairo_device_acquire (&ctx->base);
  2155.     if (unlikely (status))
  2156.         return status;
  2157.  
  2158.     if (surface->emitted) {
  2159.         assert (! surface->active);
  2160.  
  2161.         if (! cairo_list_is_empty (&surface->operand.link)) {
  2162.             if (! ctx->active) {
  2163.                 if (target_is_active (surface)) {
  2164.                     _cairo_output_stream_printf (ctx->stream,
  2165.                                                  "pop\n");
  2166.                 } else {
  2167.                     int depth = target_depth (surface);
  2168.                     if (depth == 1) {
  2169.                         _cairo_output_stream_printf (ctx->stream,
  2170.                                                      "exch pop\n");
  2171.                     } else {
  2172.                         _cairo_output_stream_printf (ctx->stream,
  2173.                                                      "%d -1 roll pop\n",
  2174.                                                      depth);
  2175.                     }
  2176.                 }
  2177.                 cairo_list_del (&surface->operand.link);
  2178.             } else {
  2179.                 struct deferred_finish *link = malloc (sizeof (*link));
  2180.                 if (link == NULL) {
  2181.                     status2 = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  2182.                     if (status == CAIRO_STATUS_SUCCESS)
  2183.                         status = status2;
  2184.                     cairo_list_del (&surface->operand.link);
  2185.                 } else {
  2186.                     link->operand.type = DEFERRED;
  2187.                     cairo_list_swap (&link->operand.link,
  2188.                                      &surface->operand.link);
  2189.                     cairo_list_add (&link->link, &ctx->deferred);
  2190.                 }
  2191.             }
  2192.         }
  2193.  
  2194.         if (surface->defined) {
  2195.             _cairo_output_stream_printf (ctx->stream,
  2196.                                          "/s%u undef\n",
  2197.                                          surface->base.unique_id);
  2198.         }
  2199.     }
  2200.  
  2201.     if (status == CAIRO_STATUS_SUCCESS)
  2202.         status = _cairo_output_stream_flush (to_context (surface)->stream);
  2203.  
  2204.     cairo_device_release (&ctx->base);
  2205.  
  2206.     return status;
  2207. }
  2208.  
  2209. static cairo_int_status_t
  2210. _cairo_script_surface_copy_page (void *abstract_surface)
  2211. {
  2212.     cairo_script_surface_t *surface = abstract_surface;
  2213.     cairo_status_t status;
  2214.  
  2215.     status = cairo_device_acquire (surface->base.device);
  2216.     if (unlikely (status))
  2217.         return status;
  2218.  
  2219.     status = _emit_context (surface);
  2220.     if (unlikely (status))
  2221.         goto BAIL;
  2222.  
  2223.     _cairo_output_stream_puts (to_context (surface)->stream, "copy-page\n");
  2224.  
  2225. BAIL:
  2226.     cairo_device_release (surface->base.device);
  2227.     return status;
  2228. }
  2229.  
  2230. static cairo_int_status_t
  2231. _cairo_script_surface_show_page (void *abstract_surface)
  2232. {
  2233.     cairo_script_surface_t *surface = abstract_surface;
  2234.     cairo_status_t status;
  2235.  
  2236.     status = cairo_device_acquire (surface->base.device);
  2237.     if (unlikely (status))
  2238.         return status;
  2239.  
  2240.     status = _emit_context (surface);
  2241.     if (unlikely (status))
  2242.         goto BAIL;
  2243.  
  2244.     _cairo_output_stream_puts (to_context (surface)->stream, "show-page\n");
  2245.  
  2246. BAIL:
  2247.     cairo_device_release (surface->base.device);
  2248.     return status;
  2249. }
  2250.  
  2251. static cairo_status_t
  2252. _cairo_script_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
  2253.                                                    cairo_path_fixed_t   *path,
  2254.                                                    cairo_fill_rule_t     fill_rule,
  2255.                                                    double                tolerance,
  2256.                                                    cairo_antialias_t     antialias)
  2257. {
  2258.     cairo_script_surface_t *surface = cairo_container_of (clipper,
  2259.                                                           cairo_script_surface_t,
  2260.                                                           clipper);
  2261.     cairo_script_context_t *ctx = to_context (surface);
  2262.     cairo_bool_t matrix_updated = FALSE;
  2263.     cairo_status_t status;
  2264.     cairo_box_t box;
  2265.  
  2266.     status = _emit_context (surface);
  2267.     if (unlikely (status))
  2268.         return status;
  2269.  
  2270.     if (path == NULL) {
  2271.         if (surface->cr.has_clip) {
  2272.             _cairo_output_stream_puts (ctx->stream, "reset-clip\n");
  2273.             surface->cr.has_clip = FALSE;
  2274.         }
  2275.         return CAIRO_STATUS_SUCCESS;
  2276.     }
  2277.  
  2278.     /* skip the trivial clip covering the surface extents */
  2279.     if (surface->width >= 0 && surface->height >= 0 &&
  2280.         _cairo_path_fixed_is_box (path, &box))
  2281.     {
  2282.         if (box.p1.x <= 0 && box.p1.y <= 0 &&
  2283.             box.p2.x >= _cairo_fixed_from_double (surface->width) &&
  2284.             box.p2.y >= _cairo_fixed_from_double (surface->height))
  2285.         {
  2286.             return CAIRO_STATUS_SUCCESS;
  2287.         }
  2288.     }
  2289.  
  2290.     status = _emit_identity (surface, &matrix_updated);
  2291.     if (unlikely (status))
  2292.         return status;
  2293.  
  2294.     status = _emit_fill_rule (surface, fill_rule);
  2295.     if (unlikely (status))
  2296.         return status;
  2297.  
  2298.     if (path->has_curve_to) {
  2299.         status = _emit_tolerance (surface, tolerance, matrix_updated);
  2300.         if (unlikely (status))
  2301.             return status;
  2302.     }
  2303.  
  2304.     if (! _cairo_path_fixed_fill_maybe_region (path)) {
  2305.         status = _emit_antialias (surface, antialias);
  2306.         if (unlikely (status))
  2307.             return status;
  2308.     }
  2309.  
  2310.     status = _emit_path (surface, path, TRUE);
  2311.     if (unlikely (status))
  2312.         return status;
  2313.  
  2314.     _cairo_output_stream_puts (ctx->stream, "clip+\n");
  2315.     surface->cr.has_clip = TRUE;
  2316.  
  2317.     return CAIRO_STATUS_SUCCESS;
  2318. }
  2319.  
  2320. static cairo_status_t
  2321. active (cairo_script_surface_t *surface)
  2322. {
  2323.     cairo_status_t status;
  2324.  
  2325.     status = cairo_device_acquire (surface->base.device);
  2326.     if (unlikely (status))
  2327.         return status;
  2328.  
  2329.     if (surface->active++ == 0)
  2330.         to_context (surface)->active++;
  2331.  
  2332.     return CAIRO_STATUS_SUCCESS;
  2333. }
  2334.  
  2335. static void
  2336. inactive (cairo_script_surface_t *surface)
  2337. {
  2338.     cairo_script_context_t *ctx = to_context (surface);
  2339.     cairo_list_t sorted;
  2340.  
  2341.     assert (surface->active > 0);
  2342.     if (--surface->active)
  2343.         goto DONE;
  2344.  
  2345.     assert (ctx->active > 0);
  2346.     if (--ctx->active)
  2347.         goto DONE;
  2348.  
  2349.     cairo_list_init (&sorted);
  2350.     while (! cairo_list_is_empty (&ctx->deferred)) {
  2351.         struct deferred_finish *df;
  2352.         cairo_list_t *operand;
  2353.         int depth;
  2354.  
  2355.         df = cairo_list_first_entry (&ctx->deferred,
  2356.                                      struct deferred_finish,
  2357.                                      link);
  2358.  
  2359.         depth = 0;
  2360.         cairo_list_foreach (operand, &ctx->operands) {
  2361.             if (operand == &df->operand.link)
  2362.                 break;
  2363.             depth++;
  2364.         }
  2365.  
  2366.         df->operand.type = depth;
  2367.  
  2368.         if (cairo_list_is_empty (&sorted)) {
  2369.             cairo_list_move (&df->link, &sorted);
  2370.         } else {
  2371.             struct deferred_finish *pos;
  2372.  
  2373.             cairo_list_foreach_entry (pos, struct deferred_finish,
  2374.                                       &sorted,
  2375.                                       link)
  2376.             {
  2377.                 if (df->operand.type < pos->operand.type)
  2378.                     break;
  2379.             }
  2380.             cairo_list_move_tail (&df->link, &pos->link);
  2381.         }
  2382.     }
  2383.  
  2384.     while (! cairo_list_is_empty (&sorted)) {
  2385.         struct deferred_finish *df;
  2386.         cairo_list_t *operand;
  2387.         int depth;
  2388.  
  2389.         df = cairo_list_first_entry (&sorted,
  2390.                                      struct deferred_finish,
  2391.                                      link);
  2392.  
  2393.         depth = 0;
  2394.         cairo_list_foreach (operand, &ctx->operands) {
  2395.             if (operand == &df->operand.link)
  2396.                 break;
  2397.             depth++;
  2398.         }
  2399.  
  2400.         if (depth == 0) {
  2401.             _cairo_output_stream_printf (ctx->stream,
  2402.                                          "pop\n");
  2403.         } else if (depth == 1) {
  2404.             _cairo_output_stream_printf (ctx->stream,
  2405.                                          "exch pop\n");
  2406.         } else {
  2407.             _cairo_output_stream_printf (ctx->stream,
  2408.                                          "%d -1 roll pop\n",
  2409.                                          depth);
  2410.         }
  2411.  
  2412.         cairo_list_del (&df->operand.link);
  2413.         cairo_list_del (&df->link);
  2414.         free (df);
  2415.     }
  2416.  
  2417. DONE:
  2418.     cairo_device_release (surface->base.device);
  2419. }
  2420.  
  2421. static cairo_int_status_t
  2422. _cairo_script_surface_paint (void                       *abstract_surface,
  2423.                              cairo_operator_t            op,
  2424.                              const cairo_pattern_t      *source,
  2425.                              const cairo_clip_t         *clip)
  2426. {
  2427.     cairo_script_surface_t *surface = abstract_surface;
  2428.     cairo_status_t status;
  2429.  
  2430.     status = active (surface);
  2431.     if (unlikely (status))
  2432.         return status;
  2433.  
  2434.     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
  2435.     if (unlikely (status))
  2436.         goto BAIL;
  2437.  
  2438.     status = _emit_context (surface);
  2439.     if (unlikely (status))
  2440.         goto BAIL;
  2441.  
  2442.     status = _emit_source (surface, op, source);
  2443.     if (unlikely (status))
  2444.         goto BAIL;
  2445.  
  2446.     status = _emit_operator (surface, op);
  2447.     if (unlikely (status))
  2448.         goto BAIL;
  2449.  
  2450.     _cairo_output_stream_puts (to_context (surface)->stream,
  2451.                                "paint\n");
  2452.  
  2453.     inactive (surface);
  2454.  
  2455.     if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
  2456.         return _cairo_surface_wrapper_paint (&surface->wrapper,
  2457.                                              op, source, clip);
  2458.     }
  2459.  
  2460.     return CAIRO_STATUS_SUCCESS;
  2461.  
  2462. BAIL:
  2463.     inactive (surface);
  2464.     return status;
  2465. }
  2466.  
  2467. static cairo_int_status_t
  2468. _cairo_script_surface_mask (void                        *abstract_surface,
  2469.                             cairo_operator_t             op,
  2470.                             const cairo_pattern_t       *source,
  2471.                             const cairo_pattern_t       *mask,
  2472.                             const cairo_clip_t          *clip)
  2473. {
  2474.     cairo_script_surface_t *surface = abstract_surface;
  2475.     cairo_status_t status;
  2476.  
  2477.     status = active (surface);
  2478.     if (unlikely (status))
  2479.         return status;
  2480.  
  2481.     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
  2482.     if (unlikely (status))
  2483.         goto BAIL;
  2484.  
  2485.     status = _emit_context (surface);
  2486.     if (unlikely (status))
  2487.         goto BAIL;
  2488.  
  2489.     status = _emit_source (surface, op, source);
  2490.     if (unlikely (status))
  2491.         goto BAIL;
  2492.  
  2493.     status = _emit_operator (surface, op);
  2494.     if (unlikely (status))
  2495.         goto BAIL;
  2496.  
  2497.     if (_cairo_pattern_equal (source, mask)) {
  2498.         _cairo_output_stream_puts (to_context (surface)->stream, "/source get");
  2499.     } else {
  2500.         status = _emit_pattern (surface, mask);
  2501.         if (unlikely (status))
  2502.             goto BAIL;
  2503.     }
  2504.  
  2505.     assert (surface->cr.current_operator == op);
  2506.  
  2507.     _cairo_output_stream_puts (to_context (surface)->stream,
  2508.                                " mask\n");
  2509.  
  2510.     inactive (surface);
  2511.  
  2512.     if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
  2513.         return _cairo_surface_wrapper_mask (&surface->wrapper,
  2514.                                             op, source, mask, clip);
  2515.     }
  2516.  
  2517.     return CAIRO_STATUS_SUCCESS;
  2518.  
  2519. BAIL:
  2520.     inactive (surface);
  2521.     return status;
  2522. }
  2523.  
  2524. static cairo_int_status_t
  2525. _cairo_script_surface_stroke (void                              *abstract_surface,
  2526.                               cairo_operator_t                   op,
  2527.                               const cairo_pattern_t             *source,
  2528.                               const cairo_path_fixed_t          *path,
  2529.                               const cairo_stroke_style_t        *style,
  2530.                               const cairo_matrix_t              *ctm,
  2531.                               const cairo_matrix_t              *ctm_inverse,
  2532.                               double                             tolerance,
  2533.                               cairo_antialias_t                  antialias,
  2534.                               const cairo_clip_t                *clip)
  2535. {
  2536.     cairo_script_surface_t *surface = abstract_surface;
  2537.     cairo_bool_t matrix_updated = FALSE;
  2538.     cairo_status_t status;
  2539.  
  2540.     status = active (surface);
  2541.     if (unlikely (status))
  2542.         return status;
  2543.  
  2544.     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
  2545.     if (unlikely (status))
  2546.         goto BAIL;
  2547.  
  2548.     status = _emit_context (surface);
  2549.     if (unlikely (status))
  2550.         goto BAIL;
  2551.  
  2552.     status = _emit_identity (surface, &matrix_updated);
  2553.     if (unlikely (status))
  2554.         goto BAIL;
  2555.  
  2556.     status = _emit_path (surface, path, FALSE);
  2557.     if (unlikely (status))
  2558.         goto BAIL;
  2559.  
  2560.     status = _emit_source (surface, op, source);
  2561.     if (unlikely (status))
  2562.         goto BAIL;
  2563.  
  2564.     status = _emit_scaling_matrix (surface, ctm, &matrix_updated);
  2565.     if (unlikely (status))
  2566.         goto BAIL;
  2567.  
  2568.     status = _emit_operator (surface, op);
  2569.     if (unlikely (status))
  2570.         goto BAIL;
  2571.  
  2572.     if (_scaling_matrix_equal (&surface->cr.current_ctm,
  2573.                                &surface->cr.current_stroke_matrix))
  2574.     {
  2575.         matrix_updated = FALSE;
  2576.     }
  2577.     else
  2578.     {
  2579.         matrix_updated = TRUE;
  2580.         surface->cr.current_stroke_matrix = surface->cr.current_ctm;
  2581.     }
  2582.  
  2583.     status = _emit_stroke_style (surface, style, matrix_updated);
  2584.     if (unlikely (status))
  2585.         goto BAIL;
  2586.  
  2587.     status = _emit_tolerance (surface, tolerance, matrix_updated);
  2588.     if (unlikely (status))
  2589.         goto BAIL;
  2590.  
  2591.     status = _emit_antialias (surface, antialias);
  2592.     if (unlikely (status))
  2593.         goto BAIL;
  2594.  
  2595.     _cairo_output_stream_puts (to_context (surface)->stream, "stroke+\n");
  2596.  
  2597.     inactive (surface);
  2598.  
  2599.     if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
  2600.         return _cairo_surface_wrapper_stroke (&surface->wrapper,
  2601.                                               op, source, path,
  2602.                                               style,
  2603.                                               ctm, ctm_inverse,
  2604.                                               tolerance, antialias,
  2605.                                               clip);
  2606.     }
  2607.  
  2608.     return CAIRO_STATUS_SUCCESS;
  2609.  
  2610. BAIL:
  2611.     inactive (surface);
  2612.     return status;
  2613. }
  2614.  
  2615. static cairo_int_status_t
  2616. _cairo_script_surface_fill (void                        *abstract_surface,
  2617.                             cairo_operator_t             op,
  2618.                             const cairo_pattern_t       *source,
  2619.                             const cairo_path_fixed_t    *path,
  2620.                             cairo_fill_rule_t            fill_rule,
  2621.                             double                       tolerance,
  2622.                             cairo_antialias_t            antialias,
  2623.                             const cairo_clip_t          *clip)
  2624. {
  2625.     cairo_script_surface_t *surface = abstract_surface;
  2626.     cairo_bool_t matrix_updated = FALSE;
  2627.     cairo_status_t status;
  2628.     cairo_box_t box;
  2629.  
  2630.     status = active (surface);
  2631.     if (unlikely (status))
  2632.         return status;
  2633.  
  2634.     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
  2635.     if (unlikely (status))
  2636.         goto BAIL;
  2637.  
  2638.     status = _emit_context (surface);
  2639.     if (unlikely (status))
  2640.         goto BAIL;
  2641.  
  2642.     status = _emit_identity (surface, &matrix_updated);
  2643.     if (unlikely (status))
  2644.         goto BAIL;
  2645.  
  2646.     status = _emit_source (surface, op, source);
  2647.     if (unlikely (status))
  2648.         goto BAIL;
  2649.  
  2650.     if (! _cairo_path_fixed_is_box (path, &box)) {
  2651.         status = _emit_fill_rule (surface, fill_rule);
  2652.         if (unlikely (status))
  2653.             goto BAIL;
  2654.     }
  2655.  
  2656.     if (path->has_curve_to) {
  2657.         status = _emit_tolerance (surface, tolerance, matrix_updated);
  2658.         if (unlikely (status))
  2659.             goto BAIL;
  2660.     }
  2661.  
  2662.     if (! _cairo_path_fixed_fill_maybe_region (path)) {
  2663.         status = _emit_antialias (surface, antialias);
  2664.         if (unlikely (status))
  2665.             goto BAIL;
  2666.     }
  2667.  
  2668.     status = _emit_path (surface, path, TRUE);
  2669.     if (unlikely (status))
  2670.         goto BAIL;
  2671.  
  2672.     status = _emit_operator (surface, op);
  2673.     if (unlikely (status))
  2674.         goto BAIL;
  2675.  
  2676.     _cairo_output_stream_puts (to_context (surface)->stream, "fill+\n");
  2677.  
  2678.     inactive (surface);
  2679.  
  2680.     if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
  2681.         return _cairo_surface_wrapper_fill (&surface->wrapper,
  2682.                                             op, source, path,
  2683.                                             fill_rule,
  2684.                                             tolerance,
  2685.                                             antialias,
  2686.                                             clip);
  2687.     }
  2688.  
  2689.     return CAIRO_STATUS_SUCCESS;
  2690.  
  2691. BAIL:
  2692.     inactive (surface);
  2693.     return status;
  2694. }
  2695.  
  2696. static cairo_surface_t *
  2697. _cairo_script_surface_snapshot (void *abstract_surface)
  2698. {
  2699.     cairo_script_surface_t *surface = abstract_surface;
  2700.  
  2701.     if (_cairo_surface_wrapper_is_active (&surface->wrapper))
  2702.         return _cairo_surface_wrapper_snapshot (&surface->wrapper);
  2703.  
  2704.     return NULL;
  2705. }
  2706.  
  2707. static cairo_bool_t
  2708. _cairo_script_surface_has_show_text_glyphs (void *abstract_surface)
  2709. {
  2710.     return TRUE;
  2711. }
  2712.  
  2713. static const char *
  2714. _subpixel_order_to_string (cairo_subpixel_order_t subpixel_order)
  2715. {
  2716.     static const char *names[] = {
  2717.         "SUBPIXEL_ORDER_DEFAULT",       /* CAIRO_SUBPIXEL_ORDER_DEFAULT */
  2718.         "SUBPIXEL_ORDER_RGB",           /* CAIRO_SUBPIXEL_ORDER_RGB */
  2719.         "SUBPIXEL_ORDER_BGR",           /* CAIRO_SUBPIXEL_ORDER_BGR */
  2720.         "SUBPIXEL_ORDER_VRGB",          /* CAIRO_SUBPIXEL_ORDER_VRGB */
  2721.         "SUBPIXEL_ORDER_VBGR"           /* CAIRO_SUBPIXEL_ORDER_VBGR */
  2722.     };
  2723.     return names[subpixel_order];
  2724. }
  2725. static const char *
  2726. _hint_style_to_string (cairo_hint_style_t hint_style)
  2727. {
  2728.     static const char *names[] = {
  2729.         "HINT_STYLE_DEFAULT",   /* CAIRO_HINT_STYLE_DEFAULT */
  2730.         "HINT_STYLE_NONE",      /* CAIRO_HINT_STYLE_NONE */
  2731.         "HINT_STYLE_SLIGHT",    /* CAIRO_HINT_STYLE_SLIGHT */
  2732.         "HINT_STYLE_MEDIUM",    /* CAIRO_HINT_STYLE_MEDIUM */
  2733.         "HINT_STYLE_FULL"       /* CAIRO_HINT_STYLE_FULL */
  2734.     };
  2735.     return names[hint_style];
  2736. }
  2737. static const char *
  2738. _hint_metrics_to_string (cairo_hint_metrics_t hint_metrics)
  2739. {
  2740.     static const char *names[] = {
  2741.          "HINT_METRICS_DEFAULT",        /* CAIRO_HINT_METRICS_DEFAULT */
  2742.          "HINT_METRICS_OFF",            /* CAIRO_HINT_METRICS_OFF */
  2743.          "HINT_METRICS_ON"              /* CAIRO_HINT_METRICS_ON */
  2744.     };
  2745.     return names[hint_metrics];
  2746. }
  2747.  
  2748. static cairo_status_t
  2749. _emit_font_options (cairo_script_surface_t *surface,
  2750.                     cairo_font_options_t *font_options)
  2751. {
  2752.     cairo_script_context_t *ctx = to_context (surface);
  2753.  
  2754.     if (cairo_font_options_equal (&surface->cr.current_font_options,
  2755.                                   font_options))
  2756.     {
  2757.         return CAIRO_STATUS_SUCCESS;
  2758.     }
  2759.  
  2760.     _cairo_output_stream_printf (ctx->stream, "<<");
  2761.  
  2762.     if (font_options->antialias != surface->cr.current_font_options.antialias) {
  2763.         _cairo_output_stream_printf (ctx->stream,
  2764.                                      " /antialias //%s",
  2765.                                      _antialias_to_string (font_options->antialias));
  2766.     }
  2767.  
  2768.     if (font_options->subpixel_order !=
  2769.         surface->cr.current_font_options.subpixel_order)
  2770.     {
  2771.         _cairo_output_stream_printf (ctx->stream,
  2772.                                      " /subpixel-order //%s",
  2773.                                      _subpixel_order_to_string (font_options->subpixel_order));
  2774.     }
  2775.  
  2776.     if (font_options->hint_style !=
  2777.         surface->cr.current_font_options.hint_style)
  2778.     {
  2779.         _cairo_output_stream_printf (ctx->stream,
  2780.                                      " /hint-style //%s",
  2781.                                      _hint_style_to_string (font_options->hint_style));
  2782.     }
  2783.  
  2784.     if (font_options->hint_metrics !=
  2785.         surface->cr.current_font_options.hint_metrics)
  2786.     {
  2787.         _cairo_output_stream_printf (ctx->stream,
  2788.                                      " /hint-metrics //%s",
  2789.                                      _hint_metrics_to_string (font_options->hint_metrics));
  2790.     }
  2791.  
  2792.     _cairo_output_stream_printf (ctx->stream,
  2793.                                  " >> set-font-options\n");
  2794.  
  2795.     surface->cr.current_font_options = *font_options;
  2796.     return CAIRO_STATUS_SUCCESS;
  2797. }
  2798.  
  2799. static void
  2800. _cairo_script_scaled_font_fini (cairo_scaled_font_private_t *abstract_private,
  2801.                                 cairo_scaled_font_t *scaled_font)
  2802. {
  2803.     cairo_script_font_t *priv = (cairo_script_font_t *)abstract_private;
  2804.     cairo_script_context_t *ctx = (cairo_script_context_t *)abstract_private->key;
  2805.     cairo_status_t status;
  2806.  
  2807.     status = cairo_device_acquire (&ctx->base);
  2808.     if (likely (status == CAIRO_STATUS_SUCCESS)) {
  2809.         _cairo_output_stream_printf (ctx->stream,
  2810.                                      "/f%lu undef /sf%lu undef\n",
  2811.                                      priv->id,
  2812.                                      priv->id);
  2813.  
  2814.         _bitmap_release_id (&ctx->font_id, priv->id);
  2815.         cairo_device_release (&ctx->base);
  2816.     }
  2817.  
  2818.     cairo_list_del (&priv->link);
  2819.     cairo_list_del (&priv->base.link);
  2820.     free (priv);
  2821. }
  2822.  
  2823. static cairo_script_font_t *
  2824. _cairo_script_font_get (cairo_script_context_t *ctx, cairo_scaled_font_t *font)
  2825. {
  2826.     return (cairo_script_font_t *) _cairo_scaled_font_find_private (font, ctx);
  2827. }
  2828.  
  2829. static long unsigned
  2830. _cairo_script_font_id (cairo_script_context_t *ctx, cairo_scaled_font_t *font)
  2831. {
  2832.     return _cairo_script_font_get (ctx, font)->id;
  2833. }
  2834.  
  2835. static cairo_status_t
  2836. _emit_type42_font (cairo_script_surface_t *surface,
  2837.                    cairo_scaled_font_t *scaled_font)
  2838. {
  2839.     cairo_script_context_t *ctx = to_context (surface);
  2840.     const cairo_scaled_font_backend_t *backend;
  2841.     cairo_output_stream_t *base85_stream;
  2842.     cairo_output_stream_t *zlib_stream;
  2843.     cairo_status_t status, status2;
  2844.     unsigned long size;
  2845.     unsigned int load_flags;
  2846.     uint32_t len;
  2847.     uint8_t *buf;
  2848.  
  2849.     backend = scaled_font->backend;
  2850.     if (backend->load_truetype_table == NULL)
  2851.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2852.  
  2853.     size = 0;
  2854.     status = backend->load_truetype_table (scaled_font, 0, 0, NULL, &size);
  2855.     if (unlikely (status))
  2856.         return status;
  2857.  
  2858.     buf = malloc (size);
  2859.     if (unlikely (buf == NULL))
  2860.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  2861.  
  2862.     status = backend->load_truetype_table (scaled_font, 0, 0, buf, &size);
  2863.     if (unlikely (status)) {
  2864.         free (buf);
  2865.         return status;
  2866.     }
  2867.  
  2868. #if CAIRO_HAS_FT_FONT
  2869.     load_flags = _cairo_ft_scaled_font_get_load_flags (scaled_font);
  2870. #else
  2871.     load_flags = 0;
  2872. #endif
  2873.     _cairo_output_stream_printf (ctx->stream,
  2874.                                  "<< "
  2875.                                  "/type 42 "
  2876.                                  "/index 0 "
  2877.                                  "/flags %d "
  2878.                                  "/source <|",
  2879.                                  load_flags);
  2880.  
  2881.     base85_stream = _cairo_base85_stream_create (ctx->stream);
  2882.     len = to_be32 (size);
  2883.     _cairo_output_stream_write (base85_stream, &len, sizeof (len));
  2884.  
  2885.     zlib_stream = _cairo_deflate_stream_create (base85_stream);
  2886.  
  2887.     _cairo_output_stream_write (zlib_stream, buf, size);
  2888.     free (buf);
  2889.  
  2890.     status2 = _cairo_output_stream_destroy (zlib_stream);
  2891.     if (status == CAIRO_STATUS_SUCCESS)
  2892.         status = status2;
  2893.  
  2894.     status2 = _cairo_output_stream_destroy (base85_stream);
  2895.     if (status == CAIRO_STATUS_SUCCESS)
  2896.         status = status2;
  2897.  
  2898.     _cairo_output_stream_printf (ctx->stream,
  2899.                                  "~> >> font dup /f%lu exch def set-font-face",
  2900.                                  _cairo_script_font_id (ctx, scaled_font));
  2901.  
  2902.     return status;
  2903. }
  2904.  
  2905. static cairo_status_t
  2906. _emit_scaled_font_init (cairo_script_surface_t *surface,
  2907.                         cairo_scaled_font_t *scaled_font,
  2908.                         cairo_script_font_t **font_out)
  2909. {
  2910.     cairo_script_context_t *ctx = to_context (surface);
  2911.     cairo_script_font_t *font_private;
  2912.     cairo_int_status_t status;
  2913.  
  2914.     font_private = malloc (sizeof (cairo_script_font_t));
  2915.     if (unlikely (font_private == NULL))
  2916.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  2917.  
  2918.     _cairo_scaled_font_attach_private (scaled_font, &font_private->base, ctx,
  2919.                                        _cairo_script_scaled_font_fini);
  2920.  
  2921.     font_private->parent = scaled_font;
  2922.     font_private->subset_glyph_index = 0;
  2923.     font_private->has_sfnt = TRUE;
  2924.  
  2925.     cairo_list_add (&font_private->link, &ctx->fonts);
  2926.  
  2927.     status = _bitmap_next_id (&ctx->font_id,
  2928.                               &font_private->id);
  2929.     if (unlikely (status)) {
  2930.         free (font_private);
  2931.         return status;
  2932.     }
  2933.  
  2934.     status = _emit_context (surface);
  2935.     if (unlikely (status)) {
  2936.         free (font_private);
  2937.         return status;
  2938.     }
  2939.  
  2940.     status = _emit_type42_font (surface, scaled_font);
  2941.     if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
  2942.         *font_out = font_private;
  2943.         return status;
  2944.     }
  2945.  
  2946.     font_private->has_sfnt = FALSE;
  2947.     _cairo_output_stream_printf (ctx->stream,
  2948.                                  "dict\n"
  2949.                                  "  /type 3 set\n"
  2950.                                  "  /metrics [%f %f %f %f %f] set\n"
  2951.                                  "  /glyphs array set\n"
  2952.                                  "  font dup /f%lu exch def set-font-face",
  2953.                                  scaled_font->fs_extents.ascent,
  2954.                                  scaled_font->fs_extents.descent,
  2955.                                  scaled_font->fs_extents.height,
  2956.                                  scaled_font->fs_extents.max_x_advance,
  2957.                                  scaled_font->fs_extents.max_y_advance,
  2958.                                  font_private->id);
  2959.  
  2960.     *font_out = font_private;
  2961.     return CAIRO_STATUS_SUCCESS;
  2962. }
  2963.  
  2964. static cairo_status_t
  2965. _emit_scaled_font (cairo_script_surface_t *surface,
  2966.                    cairo_scaled_font_t *scaled_font)
  2967. {
  2968.     cairo_script_context_t *ctx = to_context (surface);
  2969.     cairo_matrix_t matrix;
  2970.     cairo_font_options_t options;
  2971.     cairo_bool_t matrix_updated = FALSE;
  2972.     cairo_status_t status;
  2973.     cairo_script_font_t *font_private;
  2974.  
  2975.     cairo_scaled_font_get_ctm (scaled_font, &matrix);
  2976.     status = _emit_scaling_matrix (surface, &matrix, &matrix_updated);
  2977.     if (unlikely (status))
  2978.         return status;
  2979.  
  2980.     if (! matrix_updated && surface->cr.current_scaled_font == scaled_font)
  2981.         return CAIRO_STATUS_SUCCESS;
  2982.  
  2983.     surface->cr.current_scaled_font = scaled_font;
  2984.  
  2985.     font_private = _cairo_script_font_get (ctx, scaled_font);
  2986.     if (font_private == NULL) {
  2987.         cairo_scaled_font_get_font_matrix (scaled_font, &matrix);
  2988.         status = _emit_font_matrix (surface, &matrix);
  2989.         if (unlikely (status))
  2990.             return status;
  2991.  
  2992.         cairo_scaled_font_get_font_options (scaled_font, &options);
  2993.         status = _emit_font_options (surface, &options);
  2994.         if (unlikely (status))
  2995.             return status;
  2996.  
  2997.         status = _emit_scaled_font_init (surface, scaled_font, &font_private);
  2998.         if (unlikely (status))
  2999.             return status;
  3000.  
  3001.         assert (target_is_active (surface));
  3002.         _cairo_output_stream_printf (ctx->stream,
  3003.                                      " /scaled-font get /sf%lu exch def\n",
  3004.                                      font_private->id);
  3005.     } else {
  3006.         _cairo_output_stream_printf (ctx->stream,
  3007.                                      "sf%lu set-scaled-font\n",
  3008.                                      font_private->id);
  3009.     }
  3010.  
  3011.     return CAIRO_STATUS_SUCCESS;
  3012. }
  3013.  
  3014. static cairo_status_t
  3015. _emit_scaled_glyph_vector (cairo_script_surface_t *surface,
  3016.                            cairo_scaled_font_t *scaled_font,
  3017.                            cairo_script_font_t *font_private,
  3018.                            cairo_scaled_glyph_t *scaled_glyph)
  3019. {
  3020.     cairo_script_context_t *ctx = to_context (surface);
  3021.     cairo_script_implicit_context_t old_cr;
  3022.     cairo_status_t status;
  3023.     unsigned long index;
  3024.  
  3025.     index = ++font_private->subset_glyph_index;
  3026.     scaled_glyph->dev_private_key = ctx;
  3027.     scaled_glyph->dev_private = (void *) index;
  3028.  
  3029.     _cairo_output_stream_printf (ctx->stream,
  3030.                                  "%lu <<\n"
  3031.                                  "  /metrics [%f %f %f %f %f %f]\n"
  3032.                                  "  /render {\n",
  3033.                                  index,
  3034.                                  scaled_glyph->fs_metrics.x_bearing,
  3035.                                  scaled_glyph->fs_metrics.y_bearing,
  3036.                                  scaled_glyph->fs_metrics.width,
  3037.                                  scaled_glyph->fs_metrics.height,
  3038.                                  scaled_glyph->fs_metrics.x_advance,
  3039.                                  scaled_glyph->fs_metrics.y_advance);
  3040.  
  3041.     if (! _cairo_matrix_is_identity (&scaled_font->scale_inverse)) {
  3042.         _cairo_output_stream_printf (ctx->stream,
  3043.                                      "[%f %f %f %f %f %f] transform\n",
  3044.                                      scaled_font->scale_inverse.xx,
  3045.                                      scaled_font->scale_inverse.yx,
  3046.                                      scaled_font->scale_inverse.xy,
  3047.                                      scaled_font->scale_inverse.yy,
  3048.                                      scaled_font->scale_inverse.x0,
  3049.                                      scaled_font->scale_inverse.y0);
  3050.     }
  3051.  
  3052.     old_cr = surface->cr;
  3053.     _cairo_script_implicit_context_init (&surface->cr);
  3054.     status = _cairo_recording_surface_replay (scaled_glyph->recording_surface,
  3055.                                               &surface->base);
  3056.     surface->cr = old_cr;
  3057.  
  3058.     _cairo_output_stream_puts (ctx->stream, "} >> set\n");
  3059.  
  3060.     return status;
  3061. }
  3062.  
  3063. static cairo_status_t
  3064. _emit_scaled_glyph_bitmap (cairo_script_surface_t *surface,
  3065.                            cairo_scaled_font_t *scaled_font,
  3066.                            cairo_script_font_t *font_private,
  3067.                            cairo_scaled_glyph_t *scaled_glyph)
  3068. {
  3069.     cairo_script_context_t *ctx = to_context (surface);
  3070.     cairo_status_t status;
  3071.     unsigned long index;
  3072.  
  3073.     index = ++font_private->subset_glyph_index;
  3074.     scaled_glyph->dev_private_key = ctx;
  3075.     scaled_glyph->dev_private = (void *) index;
  3076.  
  3077.     _cairo_output_stream_printf (ctx->stream,
  3078.                                  "%lu <<\n"
  3079.                                  "  /metrics [%f %f %f %f %f %f]\n"
  3080.                                  "  /render {\n"
  3081.                                  "%f %f translate\n",
  3082.                                  index,
  3083.                                  scaled_glyph->fs_metrics.x_bearing,
  3084.                                  scaled_glyph->fs_metrics.y_bearing,
  3085.                                  scaled_glyph->fs_metrics.width,
  3086.                                  scaled_glyph->fs_metrics.height,
  3087.                                  scaled_glyph->fs_metrics.x_advance,
  3088.                                  scaled_glyph->fs_metrics.y_advance,
  3089.                                  scaled_glyph->fs_metrics.x_bearing,
  3090.                                  scaled_glyph->fs_metrics.y_bearing);
  3091.  
  3092.     status = _emit_image_surface (surface, scaled_glyph->surface);
  3093.     if (unlikely (status))
  3094.         return status;
  3095.  
  3096.     _cairo_output_stream_puts (ctx->stream, "pattern ");
  3097.  
  3098.     if (! _cairo_matrix_is_identity (&scaled_font->font_matrix)) {
  3099.         _cairo_output_stream_printf (ctx->stream,
  3100.                                      "\n  [%f %f %f %f %f %f] set-matrix\n",
  3101.                                      scaled_font->font_matrix.xx,
  3102.                                      scaled_font->font_matrix.yx,
  3103.                                      scaled_font->font_matrix.xy,
  3104.                                      scaled_font->font_matrix.yy,
  3105.                                      scaled_font->font_matrix.x0,
  3106.                                      scaled_font->font_matrix.y0);
  3107.     }
  3108.     _cairo_output_stream_puts (ctx->stream,
  3109.                                  "mask\n} >> set\n");
  3110.  
  3111.     return CAIRO_STATUS_SUCCESS;
  3112. }
  3113.  
  3114. static cairo_status_t
  3115. _emit_scaled_glyph_prologue (cairo_script_surface_t *surface,
  3116.                              cairo_scaled_font_t *scaled_font)
  3117. {
  3118.     cairo_script_context_t *ctx = to_context (surface);
  3119.  
  3120.     _cairo_output_stream_printf (ctx->stream, "f%lu /glyphs get\n",
  3121.                                  _cairo_script_font_id (ctx, scaled_font));
  3122.  
  3123.     return CAIRO_STATUS_SUCCESS;
  3124. }
  3125.  
  3126. static cairo_status_t
  3127. _emit_scaled_glyphs (cairo_script_surface_t *surface,
  3128.                      cairo_scaled_font_t *scaled_font,
  3129.                      cairo_glyph_t *glyphs,
  3130.                      unsigned int num_glyphs)
  3131. {
  3132.     cairo_script_context_t *ctx = to_context (surface);
  3133.     cairo_script_font_t *font_private;
  3134.     cairo_status_t status;
  3135.     unsigned int n;
  3136.     cairo_bool_t have_glyph_prologue = FALSE;
  3137.  
  3138.     if (num_glyphs == 0)
  3139.         return CAIRO_STATUS_SUCCESS;
  3140.  
  3141.     font_private = _cairo_script_font_get (ctx, scaled_font);
  3142.     if (font_private->has_sfnt)
  3143.         return CAIRO_STATUS_SUCCESS;
  3144.  
  3145.     _cairo_scaled_font_freeze_cache (scaled_font);
  3146.     for (n = 0; n < num_glyphs; n++) {
  3147.         cairo_scaled_glyph_t *scaled_glyph;
  3148.  
  3149.         status = _cairo_scaled_glyph_lookup (scaled_font,
  3150.                                              glyphs[n].index,
  3151.                                              CAIRO_SCALED_GLYPH_INFO_METRICS,
  3152.                                              &scaled_glyph);
  3153.         if (unlikely (status))
  3154.             break;
  3155.  
  3156.         if (scaled_glyph->dev_private_key == ctx)
  3157.             continue;
  3158.  
  3159.         status = _cairo_scaled_glyph_lookup (scaled_font,
  3160.                                              glyphs[n].index,
  3161.                                              CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
  3162.                                              &scaled_glyph);
  3163.         if (_cairo_status_is_error (status))
  3164.             break;
  3165.  
  3166.         if (status == CAIRO_STATUS_SUCCESS) {
  3167.             if (! have_glyph_prologue) {
  3168.                 status = _emit_scaled_glyph_prologue (surface, scaled_font);
  3169.                 if (unlikely (status))
  3170.                     break;
  3171.  
  3172.                 have_glyph_prologue = TRUE;
  3173.             }
  3174.  
  3175.             status = _emit_scaled_glyph_vector (surface,
  3176.                                                 scaled_font, font_private,
  3177.                                                 scaled_glyph);
  3178.             if (unlikely (status))
  3179.                 break;
  3180.  
  3181.             continue;
  3182.         }
  3183.  
  3184.         status = _cairo_scaled_glyph_lookup (scaled_font,
  3185.                                              glyphs[n].index,
  3186.                                              CAIRO_SCALED_GLYPH_INFO_SURFACE,
  3187.                                              &scaled_glyph);
  3188.         if (_cairo_status_is_error (status))
  3189.             break;
  3190.  
  3191.         if (status == CAIRO_STATUS_SUCCESS) {
  3192.             if (! have_glyph_prologue) {
  3193.                 status = _emit_scaled_glyph_prologue (surface, scaled_font);
  3194.                 if (unlikely (status))
  3195.                     break;
  3196.  
  3197.                 have_glyph_prologue = TRUE;
  3198.             }
  3199.  
  3200.             status = _emit_scaled_glyph_bitmap (surface,
  3201.                                                 scaled_font,
  3202.                                                 font_private,
  3203.                                                 scaled_glyph);
  3204.             if (unlikely (status))
  3205.                 break;
  3206.  
  3207.             continue;
  3208.         }
  3209.     }
  3210.     _cairo_scaled_font_thaw_cache (scaled_font);
  3211.  
  3212.     if (have_glyph_prologue) {
  3213.         _cairo_output_stream_puts (to_context (surface)->stream, "pop pop\n");
  3214.     }
  3215.  
  3216.     return status;
  3217. }
  3218.  
  3219. static void
  3220. to_octal (int value, char *buf, size_t size)
  3221. {
  3222.     do {
  3223.         buf[--size] = '0' + (value & 7);
  3224.         value >>= 3;
  3225.     } while (size);
  3226. }
  3227.  
  3228. static void
  3229. _emit_string_literal (cairo_script_surface_t *surface,
  3230.                       const char *utf8, int len)
  3231. {
  3232.     cairo_script_context_t *ctx = to_context (surface);
  3233.     char c;
  3234.     const char *end;
  3235.  
  3236.     _cairo_output_stream_puts (ctx->stream, "(");
  3237.  
  3238.     if (utf8 == NULL) {
  3239.         end = utf8;
  3240.     } else {
  3241.         if (len < 0)
  3242.             len = strlen (utf8);
  3243.         end = utf8 + len;
  3244.     }
  3245.  
  3246.     while (utf8 < end) {
  3247.         switch ((c = *utf8++)) {
  3248.         case '\n':
  3249.             c = 'n';
  3250.             goto ESCAPED_CHAR;
  3251.         case '\r':
  3252.             c = 'r';
  3253.             goto ESCAPED_CHAR;
  3254.         case '\t':
  3255.             c = 't';
  3256.             goto ESCAPED_CHAR;
  3257.         case '\b':
  3258.             c = 'b';
  3259.             goto ESCAPED_CHAR;
  3260.         case '\f':
  3261.             c = 'f';
  3262.             goto ESCAPED_CHAR;
  3263.         case '\\':
  3264.         case '(':
  3265.         case ')':
  3266. ESCAPED_CHAR:
  3267.             _cairo_output_stream_printf (ctx->stream, "\\%c", c);
  3268.             break;
  3269.         default:
  3270.             if (isprint (c) || isspace (c)) {
  3271.                 _cairo_output_stream_printf (ctx->stream, "%c", c);
  3272.             } else {
  3273.                 char buf[4] = { '\\' };
  3274.  
  3275.                 to_octal (c, buf+1, 3);
  3276.                 _cairo_output_stream_write (ctx->stream, buf, 4);
  3277.             }
  3278.             break;
  3279.         }
  3280.     }
  3281.     _cairo_output_stream_puts (ctx->stream, ")");
  3282. }
  3283.  
  3284. static cairo_int_status_t
  3285. _cairo_script_surface_show_text_glyphs (void                        *abstract_surface,
  3286.                                         cairo_operator_t             op,
  3287.                                         const cairo_pattern_t       *source,
  3288.                                         const char                  *utf8,
  3289.                                         int                          utf8_len,
  3290.                                         cairo_glyph_t               *glyphs,
  3291.                                         int                          num_glyphs,
  3292.                                         const cairo_text_cluster_t  *clusters,
  3293.                                         int                          num_clusters,
  3294.                                         cairo_text_cluster_flags_t   backward,
  3295.                                         cairo_scaled_font_t         *scaled_font,
  3296.                                         const cairo_clip_t          *clip)
  3297. {
  3298.     cairo_script_surface_t *surface = abstract_surface;
  3299.     cairo_script_context_t *ctx = to_context (surface);
  3300.     cairo_script_font_t *font_private;
  3301.     cairo_scaled_glyph_t *scaled_glyph;
  3302.     cairo_matrix_t matrix;
  3303.     cairo_status_t status;
  3304.     double x, y, ix, iy;
  3305.     int n;
  3306.     cairo_output_stream_t *base85_stream = NULL;
  3307.  
  3308.     status = active (surface);
  3309.     if (unlikely (status))
  3310.         return status;
  3311.  
  3312.     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
  3313.     if (unlikely (status))
  3314.         goto BAIL;
  3315.  
  3316.     status = _emit_context (surface);
  3317.     if (unlikely (status))
  3318.         goto BAIL;
  3319.  
  3320.     status = _emit_source (surface, op, source);
  3321.     if (unlikely (status))
  3322.         goto BAIL;
  3323.  
  3324.     status = _emit_scaled_font (surface, scaled_font);
  3325.     if (unlikely (status))
  3326.         goto BAIL;
  3327.  
  3328.     status = _emit_operator (surface, op);
  3329.     if (unlikely (status))
  3330.         goto BAIL;
  3331.  
  3332.     status = _emit_scaled_glyphs (surface, scaled_font, glyphs, num_glyphs);
  3333.     if (unlikely (status))
  3334.         goto BAIL;
  3335.  
  3336.     /* (utf8) [cx cy [glyphs]] [clusters] backward show_text_glyphs */
  3337.     /* [cx cy [glyphs]] show_glyphs */
  3338.  
  3339.     if (utf8 != NULL && clusters != NULL) {
  3340.         _emit_string_literal (surface, utf8, utf8_len);
  3341.         _cairo_output_stream_puts (ctx->stream, " ");
  3342.     }
  3343.  
  3344.     matrix = surface->cr.current_ctm;
  3345.     status = cairo_matrix_invert (&matrix);
  3346.     assert (status == CAIRO_STATUS_SUCCESS);
  3347.  
  3348.     ix = x = glyphs[0].x;
  3349.     iy = y = glyphs[0].y;
  3350.     cairo_matrix_transform_point (&matrix, &ix, &iy);
  3351.     ix -= scaled_font->font_matrix.x0;
  3352.     iy -= scaled_font->font_matrix.y0;
  3353.  
  3354.     _cairo_scaled_font_freeze_cache (scaled_font);
  3355.     font_private = _cairo_script_font_get (ctx, scaled_font);
  3356.  
  3357.     _cairo_output_stream_printf (ctx->stream,
  3358.                                  "[%f %f ",
  3359.                                  ix, iy);
  3360.  
  3361.     for (n = 0; n < num_glyphs; n++) {
  3362.         if (font_private->has_sfnt) {
  3363.             if (glyphs[n].index > 256)
  3364.                 break;
  3365.         } else {
  3366.             status = _cairo_scaled_glyph_lookup (scaled_font,
  3367.                                                  glyphs[n].index,
  3368.                                                  CAIRO_SCALED_GLYPH_INFO_METRICS,
  3369.                                                  &scaled_glyph);
  3370.             if (unlikely (status)) {
  3371.                 _cairo_scaled_font_thaw_cache (scaled_font);
  3372.                 goto BAIL;
  3373.             }
  3374.  
  3375.             if ((long unsigned) scaled_glyph->dev_private > 256)
  3376.                 break;
  3377.         }
  3378.     }
  3379.  
  3380.     if (n == num_glyphs) {
  3381.         _cairo_output_stream_puts (ctx->stream, "<~");
  3382.         base85_stream = _cairo_base85_stream_create (ctx->stream);
  3383.     } else
  3384.         _cairo_output_stream_puts (ctx->stream, "[");
  3385.  
  3386.     for (n = 0; n < num_glyphs; n++) {
  3387.         double dx, dy;
  3388.  
  3389.         status = _cairo_scaled_glyph_lookup (scaled_font,
  3390.                                              glyphs[n].index,
  3391.                                              CAIRO_SCALED_GLYPH_INFO_METRICS,
  3392.                                              &scaled_glyph);
  3393.         if (unlikely (status)) {
  3394.             _cairo_scaled_font_thaw_cache (scaled_font);
  3395.             goto BAIL;
  3396.         }
  3397.  
  3398.         if (fabs (glyphs[n].x - x) > 1e-5 || fabs (glyphs[n].y - y) > 1e-5) {
  3399.             if (fabs (glyphs[n].y - y) < 1e-5) {
  3400.                 if (base85_stream != NULL) {
  3401.                     status = _cairo_output_stream_destroy (base85_stream);
  3402.                     if (unlikely (status)) {
  3403.                         base85_stream = NULL;
  3404.                         break;
  3405.                     }
  3406.  
  3407.                     _cairo_output_stream_printf (ctx->stream,
  3408.                                                  "~> %f <~", glyphs[n].x - x);
  3409.                     base85_stream = _cairo_base85_stream_create (ctx->stream);
  3410.                 } else {
  3411.                     _cairo_output_stream_printf (ctx->stream,
  3412.                                                  " ] %f [ ", glyphs[n].x - x);
  3413.                 }
  3414.  
  3415.                 x = glyphs[n].x;
  3416.             } else {
  3417.                 ix = x = glyphs[n].x;
  3418.                 iy = y = glyphs[n].y;
  3419.                 cairo_matrix_transform_point (&matrix, &ix, &iy);
  3420.                 ix -= scaled_font->font_matrix.x0;
  3421.                 iy -= scaled_font->font_matrix.y0;
  3422.                 if (base85_stream != NULL) {
  3423.                     status = _cairo_output_stream_destroy (base85_stream);
  3424.                     if (unlikely (status)) {
  3425.                         base85_stream = NULL;
  3426.                         break;
  3427.                     }
  3428.  
  3429.                     _cairo_output_stream_printf (ctx->stream,
  3430.                                                  "~> %f %f <~",
  3431.                                                  ix, iy);
  3432.                     base85_stream = _cairo_base85_stream_create (ctx->stream);
  3433.                 } else {
  3434.                     _cairo_output_stream_printf (ctx->stream,
  3435.                                                  " ] %f %f [ ",
  3436.                                                  ix, iy);
  3437.                 }
  3438.             }
  3439.         }
  3440.         if (base85_stream != NULL) {
  3441.             uint8_t c;
  3442.  
  3443.             if (font_private->has_sfnt)
  3444.                 c = glyphs[n].index;
  3445.             else
  3446.                 c = (uint8_t) (long unsigned) scaled_glyph->dev_private;
  3447.  
  3448.             _cairo_output_stream_write (base85_stream, &c, 1);
  3449.         } else {
  3450.             if (font_private->has_sfnt)
  3451.                 _cairo_output_stream_printf (ctx->stream, " %lu",
  3452.                                              glyphs[n].index);
  3453.             else
  3454.                 _cairo_output_stream_printf (ctx->stream, " %lu",
  3455.                                              (long unsigned) scaled_glyph->dev_private);
  3456.         }
  3457.  
  3458.         dx = scaled_glyph->metrics.x_advance;
  3459.         dy = scaled_glyph->metrics.y_advance;
  3460.         cairo_matrix_transform_distance (&scaled_font->ctm, &dx, &dy);
  3461.         x += dx;
  3462.         y += dy;
  3463.     }
  3464.     _cairo_scaled_font_thaw_cache (scaled_font);
  3465.  
  3466.     if (base85_stream != NULL) {
  3467.         cairo_status_t status2;
  3468.  
  3469.         status2 = _cairo_output_stream_destroy (base85_stream);
  3470.         if (status == CAIRO_STATUS_SUCCESS)
  3471.             status = status2;
  3472.  
  3473.         _cairo_output_stream_printf (ctx->stream, "~>");
  3474.     } else {
  3475.         _cairo_output_stream_puts (ctx->stream, " ]");
  3476.     }
  3477.     if (unlikely (status))
  3478.         return status;
  3479.  
  3480.     if (utf8 != NULL && clusters != NULL) {
  3481.         for (n = 0; n < num_clusters; n++) {
  3482.             if (clusters[n].num_bytes > UCHAR_MAX ||
  3483.                 clusters[n].num_glyphs > UCHAR_MAX)
  3484.             {
  3485.                 break;
  3486.             }
  3487.         }
  3488.  
  3489.         if (n < num_clusters) {
  3490.             _cairo_output_stream_puts (ctx->stream, "] [ ");
  3491.             for (n = 0; n < num_clusters; n++) {
  3492.                 _cairo_output_stream_printf (ctx->stream,
  3493.                                              "%d %d ",
  3494.                                              clusters[n].num_bytes,
  3495.                                              clusters[n].num_glyphs);
  3496.             }
  3497.             _cairo_output_stream_puts (ctx->stream, "]");
  3498.         }
  3499.         else
  3500.         {
  3501.             _cairo_output_stream_puts (ctx->stream, "] <~");
  3502.             base85_stream = _cairo_base85_stream_create (ctx->stream);
  3503.             for (n = 0; n < num_clusters; n++) {
  3504.                 uint8_t c[2];
  3505.                 c[0] = clusters[n].num_bytes;
  3506.                 c[1] = clusters[n].num_glyphs;
  3507.                 _cairo_output_stream_write (base85_stream, c, 2);
  3508.             }
  3509.             status = _cairo_output_stream_destroy (base85_stream);
  3510.             if (unlikely (status))
  3511.                 goto BAIL;
  3512.  
  3513.             _cairo_output_stream_puts (ctx->stream, "~>");
  3514.         }
  3515.  
  3516.         _cairo_output_stream_printf (ctx->stream,
  3517.                                      " //%s show-text-glyphs\n",
  3518.                                      _direction_to_string (backward));
  3519.     } else {
  3520.         _cairo_output_stream_puts (ctx->stream,
  3521.                                    "] show-glyphs\n");
  3522.     }
  3523.  
  3524.     inactive (surface);
  3525.  
  3526.     if (_cairo_surface_wrapper_is_active (&surface->wrapper)){
  3527.         return _cairo_surface_wrapper_show_text_glyphs (&surface->wrapper,
  3528.                                                         op, source,
  3529.                                                         utf8, utf8_len,
  3530.                                                         glyphs, num_glyphs,
  3531.                                                         clusters, num_clusters,
  3532.                                                         backward,
  3533.                                                         scaled_font,
  3534.                                                         clip);
  3535.     }
  3536.  
  3537.     return CAIRO_STATUS_SUCCESS;
  3538.  
  3539. BAIL:
  3540.     inactive (surface);
  3541.     return status;
  3542. }
  3543.  
  3544. static cairo_bool_t
  3545. _cairo_script_surface_get_extents (void *abstract_surface,
  3546.                                    cairo_rectangle_int_t *rectangle)
  3547. {
  3548.     cairo_script_surface_t *surface = abstract_surface;
  3549.  
  3550.     if (_cairo_surface_wrapper_is_active (&surface->wrapper)) {
  3551.         return _cairo_surface_wrapper_get_extents (&surface->wrapper,
  3552.                                                    rectangle);
  3553.     }
  3554.  
  3555.     if (surface->width < 0 || surface->height < 0)
  3556.         return FALSE;
  3557.  
  3558.     rectangle->x = 0;
  3559.     rectangle->y = 0;
  3560.     rectangle->width = surface->width;
  3561.     rectangle->height = surface->height;
  3562.  
  3563.     return TRUE;
  3564. }
  3565.  
  3566. static const cairo_surface_backend_t
  3567. _cairo_script_surface_backend = {
  3568.     CAIRO_SURFACE_TYPE_SCRIPT,
  3569.     _cairo_script_surface_finish,
  3570.  
  3571.     _cairo_default_context_create,
  3572.  
  3573.     _cairo_script_surface_create_similar,
  3574.     NULL, /* create similar image */
  3575.     NULL, /* map to image */
  3576.     NULL, /* unmap image */
  3577.  
  3578.     _cairo_script_surface_source,
  3579.     _cairo_script_surface_acquire_source_image,
  3580.     _cairo_script_surface_release_source_image,
  3581.     _cairo_script_surface_snapshot,
  3582.  
  3583.     _cairo_script_surface_copy_page,
  3584.     _cairo_script_surface_show_page,
  3585.  
  3586.     _cairo_script_surface_get_extents,
  3587.     NULL, /* get_font_options */
  3588.  
  3589.     NULL, /* flush */
  3590.     NULL, /* mark_dirty_rectangle */
  3591.  
  3592.     _cairo_script_surface_paint,
  3593.     _cairo_script_surface_mask,
  3594.     _cairo_script_surface_stroke,
  3595.     _cairo_script_surface_fill,
  3596.     NULL, /* fill/stroke */
  3597.     NULL, /* glyphs */
  3598.     _cairo_script_surface_has_show_text_glyphs,
  3599.     _cairo_script_surface_show_text_glyphs
  3600. };
  3601.  
  3602. static void
  3603. _cairo_script_implicit_context_init (cairo_script_implicit_context_t *cr)
  3604. {
  3605.     cr->current_operator = CAIRO_GSTATE_OPERATOR_DEFAULT;
  3606.     cr->current_fill_rule = CAIRO_GSTATE_FILL_RULE_DEFAULT;
  3607.     cr->current_tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
  3608.     cr->current_antialias = CAIRO_ANTIALIAS_DEFAULT;
  3609.     _cairo_stroke_style_init (&cr->current_style);
  3610.     _cairo_pattern_init_solid (&cr->current_source.solid,
  3611.                                CAIRO_COLOR_BLACK);
  3612.     _cairo_path_fixed_init (&cr->current_path);
  3613.     cairo_matrix_init_identity (&cr->current_ctm);
  3614.     cairo_matrix_init_identity (&cr->current_stroke_matrix);
  3615.     cairo_matrix_init_identity (&cr->current_font_matrix);
  3616.     _cairo_font_options_init_default (&cr->current_font_options);
  3617.     cr->current_scaled_font = NULL;
  3618.     cr->has_clip = FALSE;
  3619. }
  3620.  
  3621. static void
  3622. _cairo_script_implicit_context_reset (cairo_script_implicit_context_t *cr)
  3623. {
  3624.     free (cr->current_style.dash);
  3625.     cr->current_style.dash = NULL;
  3626.  
  3627.     _cairo_pattern_fini (&cr->current_source.base);
  3628.     _cairo_path_fixed_fini (&cr->current_path);
  3629.  
  3630.     _cairo_script_implicit_context_init (cr);
  3631. }
  3632.  
  3633. static cairo_script_surface_t *
  3634. _cairo_script_surface_create_internal (cairo_script_context_t *ctx,
  3635.                                        cairo_content_t content,
  3636.                                        cairo_rectangle_t *extents,
  3637.                                        cairo_surface_t *passthrough)
  3638. {
  3639.     cairo_script_surface_t *surface;
  3640.  
  3641.     if (unlikely (ctx == NULL))
  3642.         return (cairo_script_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER));
  3643.  
  3644.     surface = malloc (sizeof (cairo_script_surface_t));
  3645.     if (unlikely (surface == NULL))
  3646.         return (cairo_script_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
  3647.  
  3648.     _cairo_surface_init (&surface->base,
  3649.                          &_cairo_script_surface_backend,
  3650.                          &ctx->base,
  3651.                          content);
  3652.  
  3653.     _cairo_surface_wrapper_init (&surface->wrapper, passthrough);
  3654.  
  3655.     _cairo_surface_clipper_init (&surface->clipper,
  3656.                                  _cairo_script_surface_clipper_intersect_clip_path);
  3657.  
  3658.     surface->width = surface->height = -1;
  3659.     if (extents) {
  3660.         surface->width = extents->width;
  3661.         surface->height = extents->height;
  3662.         cairo_surface_set_device_offset (&surface->base,
  3663.                                          -extents->x, -extents->y);
  3664.     }
  3665.  
  3666.     surface->emitted = FALSE;
  3667.     surface->defined = FALSE;
  3668.     surface->active = FALSE;
  3669.     surface->operand.type = SURFACE;
  3670.     cairo_list_init (&surface->operand.link);
  3671.  
  3672.     _cairo_script_implicit_context_init (&surface->cr);
  3673.  
  3674.     return surface;
  3675. }
  3676.  
  3677. static const cairo_device_backend_t _cairo_script_device_backend = {
  3678.     CAIRO_DEVICE_TYPE_SCRIPT,
  3679.  
  3680.     NULL, NULL, /* lock, unlock */
  3681.  
  3682.     _device_flush,  /* flush */
  3683.     NULL,  /* finish */
  3684.     _device_destroy
  3685. };
  3686.  
  3687. cairo_device_t *
  3688. _cairo_script_context_create_internal (cairo_output_stream_t *stream)
  3689. {
  3690.     cairo_script_context_t *ctx;
  3691.  
  3692.     ctx = malloc (sizeof (cairo_script_context_t));
  3693.     if (unlikely (ctx == NULL))
  3694.         return _cairo_device_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
  3695.  
  3696.     memset (ctx, 0, sizeof (cairo_script_context_t));
  3697.  
  3698.     _cairo_device_init (&ctx->base, &_cairo_script_device_backend);
  3699.  
  3700.     cairo_list_init (&ctx->operands);
  3701.     cairo_list_init (&ctx->deferred);
  3702.     ctx->stream = stream;
  3703.     ctx->mode = CAIRO_SCRIPT_MODE_ASCII;
  3704.  
  3705.     cairo_list_init (&ctx->fonts);
  3706.     cairo_list_init (&ctx->defines);
  3707.  
  3708.     ctx->attach_snapshots = TRUE;
  3709.  
  3710.     return &ctx->base;
  3711. }
  3712.  
  3713. void
  3714. _cairo_script_context_attach_snapshots (cairo_device_t *device,
  3715.                                         cairo_bool_t enable)
  3716. {
  3717.     cairo_script_context_t *ctx;
  3718.  
  3719.     ctx = (cairo_script_context_t *) device;
  3720.     ctx->attach_snapshots = enable;
  3721. }
  3722.  
  3723. static cairo_device_t *
  3724. _cairo_script_context_create (cairo_output_stream_t *stream)
  3725. {
  3726.     cairo_script_context_t *ctx;
  3727.  
  3728.     ctx = (cairo_script_context_t *)
  3729.         _cairo_script_context_create_internal (stream);
  3730.     if (unlikely (ctx->base.status))
  3731.         return &ctx->base;
  3732.  
  3733.     ctx->owns_stream = TRUE;
  3734.     _cairo_output_stream_puts (ctx->stream, "%!CairoScript\n");
  3735.     return &ctx->base;
  3736. }
  3737.  
  3738. /**
  3739.  * cairo_script_create:
  3740.  * @filename: the name (path) of the file to write the script to
  3741.  *
  3742.  * Creates a output device for emitting the script, used when
  3743.  * creating the individual surfaces.
  3744.  *
  3745.  * Return value: a pointer to the newly created device. The caller
  3746.  * owns the surface and should call cairo_device_destroy() when done
  3747.  * with it.
  3748.  *
  3749.  * This function always returns a valid pointer, but it will return a
  3750.  * pointer to a "nil" device if an error such as out of memory
  3751.  * occurs. You can use cairo_device_status() to check for this.
  3752.  *
  3753.  * Since: 1.12
  3754.  **/
  3755. cairo_device_t *
  3756. cairo_script_create (const char *filename)
  3757. {
  3758.     cairo_output_stream_t *stream;
  3759.     cairo_status_t status;
  3760.  
  3761.     stream = _cairo_output_stream_create_for_filename (filename);
  3762.     if ((status = _cairo_output_stream_get_status (stream)))
  3763.         return _cairo_device_create_in_error (status);
  3764.  
  3765.     return _cairo_script_context_create (stream);
  3766. }
  3767.  
  3768. /**
  3769.  * cairo_script_create_for_stream:
  3770.  * @write_func: callback function passed the bytes written to the script
  3771.  * @closure: user data to be passed to the callback
  3772.  *
  3773.  * Creates a output device for emitting the script, used when
  3774.  * creating the individual surfaces.
  3775.  *
  3776.  * Return value: a pointer to the newly created device. The caller
  3777.  * owns the surface and should call cairo_device_destroy() when done
  3778.  * with it.
  3779.  *
  3780.  * This function always returns a valid pointer, but it will return a
  3781.  * pointer to a "nil" device if an error such as out of memory
  3782.  * occurs. You can use cairo_device_status() to check for this.
  3783.  *
  3784.  * Since: 1.12
  3785.  **/
  3786. cairo_device_t *
  3787. cairo_script_create_for_stream (cairo_write_func_t       write_func,
  3788.                                 void                    *closure)
  3789. {
  3790.     cairo_output_stream_t *stream;
  3791.     cairo_status_t status;
  3792.  
  3793.     stream = _cairo_output_stream_create (write_func, NULL, closure);
  3794.     if ((status = _cairo_output_stream_get_status (stream)))
  3795.         return _cairo_device_create_in_error (status);
  3796.  
  3797.     return _cairo_script_context_create (stream);
  3798. }
  3799.  
  3800. /**
  3801.  * cairo_script_write_comment:
  3802.  * @script: the script (output device)
  3803.  * @comment: the string to emit
  3804.  * @len:the length of the sting to write, or -1 to use strlen()
  3805.  *
  3806.  * Emit a string verbatim into the script.
  3807.  *
  3808.  * Since: 1.12
  3809.  **/
  3810. void
  3811. cairo_script_write_comment (cairo_device_t *script,
  3812.                             const char *comment,
  3813.                             int len)
  3814. {
  3815.     cairo_script_context_t *context = (cairo_script_context_t *) script;
  3816.  
  3817.     if (len < 0)
  3818.         len = strlen (comment);
  3819.  
  3820.     _cairo_output_stream_puts (context->stream, "% ");
  3821.     _cairo_output_stream_write (context->stream, comment, len);
  3822.     _cairo_output_stream_puts (context->stream, "\n");
  3823. }
  3824.  
  3825. /**
  3826.  * cairo_script_set_mode:
  3827.  * @script: The script (output device)
  3828.  * @mode: the new mode
  3829.  *
  3830.  * Change the output mode of the script
  3831.  *
  3832.  * Since: 1.12
  3833.  **/
  3834. void
  3835. cairo_script_set_mode (cairo_device_t *script,
  3836.                        cairo_script_mode_t mode)
  3837. {
  3838.     cairo_script_context_t *context = (cairo_script_context_t *) script;
  3839.  
  3840.     context->mode = mode;
  3841. }
  3842.  
  3843. /**
  3844.  * cairo_script_get_mode:
  3845.  * @script: The script (output device) to query
  3846.  *
  3847.  * Queries the script for its current output mode.
  3848.  *
  3849.  * Return value: the current output mode of the script
  3850.  *
  3851.  * Since: 1.12
  3852.  **/
  3853. cairo_script_mode_t
  3854. cairo_script_get_mode (cairo_device_t *script)
  3855. {
  3856.     cairo_script_context_t *context = (cairo_script_context_t *) script;
  3857.  
  3858.     return context->mode;
  3859. }
  3860.  
  3861. /**
  3862.  * cairo_script_surface_create:
  3863.  * @script: the script (output device)
  3864.  * @content: the content of the surface
  3865.  * @width: width in pixels
  3866.  * @height: height in pixels
  3867.  *
  3868.  * Create a new surface that will emit its rendering through @script
  3869.  *
  3870.  * Return value: a pointer to the newly created surface. The caller
  3871.  * owns the surface and should call cairo_surface_destroy() when done
  3872.  * with it.
  3873.  *
  3874.  * This function always returns a valid pointer, but it will return a
  3875.  * pointer to a "nil" surface if an error such as out of memory
  3876.  * occurs. You can use cairo_surface_status() to check for this.
  3877.  *
  3878.  * Since: 1.12
  3879.  **/
  3880. cairo_surface_t *
  3881. cairo_script_surface_create (cairo_device_t *script,
  3882.                              cairo_content_t content,
  3883.                              double width,
  3884.                              double height)
  3885. {
  3886.     cairo_rectangle_t *extents, r;
  3887.  
  3888.     if (unlikely (script->backend->type != CAIRO_DEVICE_TYPE_SCRIPT))
  3889.         return _cairo_surface_create_in_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
  3890.  
  3891.     if (unlikely (script->status))
  3892.         return _cairo_surface_create_in_error (script->status);
  3893.  
  3894.     extents = NULL;
  3895.     if (width > 0 && height > 0) {
  3896.         r.x = r.y = 0;
  3897.         r.width  = width;
  3898.         r.height = height;
  3899.         extents = &r;
  3900.     }
  3901.     return &_cairo_script_surface_create_internal ((cairo_script_context_t *) script,
  3902.                                                    content, extents,
  3903.                                                    NULL)->base;
  3904. }
  3905. slim_hidden_def (cairo_script_surface_create);
  3906.  
  3907. /**
  3908.  * cairo_script_surface_create_for_target:
  3909.  * @script: the script (output device)
  3910.  * @target: a target surface to wrap
  3911.  *
  3912.  * Create a pxoy surface that will render to @target and record
  3913.  * the operations to @device.
  3914.  *
  3915.  * Return value: a pointer to the newly created surface. The caller
  3916.  * owns the surface and should call cairo_surface_destroy() when done
  3917.  * with it.
  3918.  *
  3919.  * This function always returns a valid pointer, but it will return a
  3920.  * pointer to a "nil" surface if an error such as out of memory
  3921.  * occurs. You can use cairo_surface_status() to check for this.
  3922.  *
  3923.  * Since: 1.12
  3924.  **/
  3925. cairo_surface_t *
  3926. cairo_script_surface_create_for_target (cairo_device_t *script,
  3927.                                         cairo_surface_t *target)
  3928. {
  3929.     cairo_rectangle_int_t extents;
  3930.     cairo_rectangle_t rect, *r;
  3931.  
  3932.     if (unlikely (script->backend->type != CAIRO_DEVICE_TYPE_SCRIPT))
  3933.         return _cairo_surface_create_in_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
  3934.  
  3935.     if (unlikely (script->status))
  3936.         return _cairo_surface_create_in_error (script->status);
  3937.  
  3938.     if (unlikely (target->status))
  3939.         return _cairo_surface_create_in_error (target->status);
  3940.  
  3941.     r = NULL;
  3942.     if (_cairo_surface_get_extents (target, &extents)) {
  3943.         rect.x = rect.y = 0;
  3944.         rect.width = extents.width;
  3945.         rect.height = extents.height;
  3946.         r= &rect;
  3947.     }
  3948.     return &_cairo_script_surface_create_internal ((cairo_script_context_t *) script,
  3949.                                                    target->content, r,
  3950.                                                    target)->base;
  3951. }
  3952.  
  3953. /**
  3954.  * cairo_script_from_recording_surface:
  3955.  * @script: the script (output device)
  3956.  * @recording_surface: the recording surface to replay
  3957.  *
  3958.  * Converts the record operations in @recording_surface into a script.
  3959.  *
  3960.  * Return value: #CAIRO_STATUS_SUCCESS on successful completion or an error code.
  3961.  *
  3962.  * Since: 1.12
  3963.  **/
  3964. cairo_status_t
  3965. cairo_script_from_recording_surface (cairo_device_t *script,
  3966.                                      cairo_surface_t *recording_surface)
  3967. {
  3968.     cairo_rectangle_t r, *extents;
  3969.     cairo_surface_t *surface;
  3970.     cairo_status_t status;
  3971.  
  3972.     if (unlikely (script->backend->type != CAIRO_DEVICE_TYPE_SCRIPT))
  3973.         return _cairo_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
  3974.  
  3975.     if (unlikely (script->status))
  3976.         return _cairo_error (script->status);
  3977.  
  3978.     if (unlikely (recording_surface->status))
  3979.         return recording_surface->status;
  3980.  
  3981.     if (unlikely (! _cairo_surface_is_recording (recording_surface)))
  3982.         return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  3983.  
  3984.     extents = NULL;
  3985.     if (_cairo_recording_surface_get_bounds (recording_surface, &r))
  3986.         extents = &r;
  3987.  
  3988.     surface = &_cairo_script_surface_create_internal ((cairo_script_context_t *) script,
  3989.                                                       recording_surface->content,
  3990.                                                       extents,
  3991.                                                       NULL)->base;
  3992.     if (unlikely (surface->status))
  3993.         return surface->status;
  3994.  
  3995.     status = _cairo_recording_surface_replay (recording_surface, surface);
  3996.     cairo_surface_destroy (surface);
  3997.  
  3998.     return status;
  3999. }
  4000.