Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* cairo-output-stream.c: Output stream abstraction
  2.  *
  3.  * Copyright © 2005 Red Hat, Inc
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it either under the terms of the GNU Lesser General Public
  7.  * License version 2.1 as published by the Free Software Foundation
  8.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  9.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  10.  * notice, a recipient may use your version of this file under either
  11.  * the MPL or the LGPL.
  12.  *
  13.  * You should have received a copy of the LGPL along with this library
  14.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  15.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  16.  * You should have received a copy of the MPL along with this library
  17.  * in the file COPYING-MPL-1.1
  18.  *
  19.  * The contents of this file are subject to the Mozilla Public License
  20.  * Version 1.1 (the "License"); you may not use this file except in
  21.  * compliance with the License. You may obtain a copy of the License at
  22.  * http://www.mozilla.org/MPL/
  23.  *
  24.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  25.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  26.  * the specific language governing rights and limitations.
  27.  *
  28.  * The Original Code is the cairo graphics library.
  29.  *
  30.  * The Initial Developer of the Original Code is Red Hat, Inc.
  31.  *
  32.  * Author(s):
  33.  *      Kristian Høgsberg <krh@redhat.com>
  34.  */
  35.  
  36. #define _BSD_SOURCE /* for snprintf() */
  37. #include "cairoint.h"
  38.  
  39. #include "cairo-output-stream-private.h"
  40. #include "cairo-error-private.h"
  41. #include "cairo-compiler-private.h"
  42.  
  43. #include <stdio.h>
  44. #include <locale.h>
  45. #include <errno.h>
  46.  
  47. /* Numbers printed with %f are printed with this number of significant
  48.  * digits after the decimal.
  49.  */
  50. #define SIGNIFICANT_DIGITS_AFTER_DECIMAL 6
  51.  
  52. /* Numbers printed with %g are assumed to only have %CAIRO_FIXED_FRAC_BITS
  53.  * bits of precision available after the decimal point.
  54.  *
  55.  * FIXED_POINT_DECIMAL_DIGITS specifies the minimum number of decimal
  56.  * digits after the decimal point required to preserve the available
  57.  * precision.
  58.  *
  59.  * The conversion is:
  60.  *
  61.  * <programlisting>
  62.  * FIXED_POINT_DECIMAL_DIGITS = ceil( CAIRO_FIXED_FRAC_BITS * ln(2)/ln(10) )
  63.  * </programlisting>
  64.  *
  65.  * We can replace ceil(x) with (int)(x+1) since x will never be an
  66.  * integer for any likely value of %CAIRO_FIXED_FRAC_BITS.
  67.  */
  68. #define FIXED_POINT_DECIMAL_DIGITS ((int)(CAIRO_FIXED_FRAC_BITS*0.301029996 + 1))
  69.  
  70. void
  71. _cairo_output_stream_init (cairo_output_stream_t            *stream,
  72.                            cairo_output_stream_write_func_t  write_func,
  73.                            cairo_output_stream_flush_func_t  flush_func,
  74.                            cairo_output_stream_close_func_t  close_func)
  75. {
  76.     stream->write_func = write_func;
  77.     stream->flush_func = flush_func;
  78.     stream->close_func = close_func;
  79.     stream->position = 0;
  80.     stream->status = CAIRO_STATUS_SUCCESS;
  81.     stream->closed = FALSE;
  82. }
  83.  
  84. cairo_status_t
  85. _cairo_output_stream_fini (cairo_output_stream_t *stream)
  86. {
  87.     return _cairo_output_stream_close (stream);
  88. }
  89.  
  90. const cairo_output_stream_t _cairo_output_stream_nil = {
  91.     NULL, /* write_func */
  92.     NULL, /* flush_func */
  93.     NULL, /* close_func */
  94.     0,    /* position */
  95.     CAIRO_STATUS_NO_MEMORY,
  96.     FALSE /* closed */
  97. };
  98.  
  99. static const cairo_output_stream_t _cairo_output_stream_nil_write_error = {
  100.     NULL, /* write_func */
  101.     NULL, /* flush_func */
  102.     NULL, /* close_func */
  103.     0,    /* position */
  104.     CAIRO_STATUS_WRITE_ERROR,
  105.     FALSE /* closed */
  106. };
  107.  
  108. typedef struct _cairo_output_stream_with_closure {
  109.     cairo_output_stream_t        base;
  110.     cairo_write_func_t           write_func;
  111.     cairo_close_func_t           close_func;
  112.     void                        *closure;
  113. } cairo_output_stream_with_closure_t;
  114.  
  115.  
  116. static cairo_status_t
  117. closure_write (cairo_output_stream_t *stream,
  118.                const unsigned char *data, unsigned int length)
  119. {
  120.     cairo_output_stream_with_closure_t *stream_with_closure =
  121.         (cairo_output_stream_with_closure_t *) stream;
  122.  
  123.     if (stream_with_closure->write_func == NULL)
  124.         return CAIRO_STATUS_SUCCESS;
  125.  
  126.     return stream_with_closure->write_func (stream_with_closure->closure,
  127.                                             data, length);
  128. }
  129.  
  130. static cairo_status_t
  131. closure_close (cairo_output_stream_t *stream)
  132. {
  133.     cairo_output_stream_with_closure_t *stream_with_closure =
  134.         (cairo_output_stream_with_closure_t *) stream;
  135.  
  136.     if (stream_with_closure->close_func != NULL)
  137.         return stream_with_closure->close_func (stream_with_closure->closure);
  138.     else
  139.         return CAIRO_STATUS_SUCCESS;
  140. }
  141.  
  142. cairo_output_stream_t *
  143. _cairo_output_stream_create (cairo_write_func_t         write_func,
  144.                              cairo_close_func_t         close_func,
  145.                              void                       *closure)
  146. {
  147.     cairo_output_stream_with_closure_t *stream;
  148.  
  149.     stream = malloc (sizeof (cairo_output_stream_with_closure_t));
  150.     if (unlikely (stream == NULL)) {
  151.         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
  152.         return (cairo_output_stream_t *) &_cairo_output_stream_nil;
  153.     }
  154.  
  155.     _cairo_output_stream_init (&stream->base,
  156.                                closure_write, NULL, closure_close);
  157.     stream->write_func = write_func;
  158.     stream->close_func = close_func;
  159.     stream->closure = closure;
  160.  
  161.     return &stream->base;
  162. }
  163.  
  164. cairo_output_stream_t *
  165. _cairo_output_stream_create_in_error (cairo_status_t status)
  166. {
  167.     cairo_output_stream_t *stream;
  168.  
  169.     /* check for the common ones */
  170.     if (status == CAIRO_STATUS_NO_MEMORY)
  171.         return (cairo_output_stream_t *) &_cairo_output_stream_nil;
  172.     if (status == CAIRO_STATUS_WRITE_ERROR)
  173.         return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
  174.  
  175.     stream = malloc (sizeof (cairo_output_stream_t));
  176.     if (unlikely (stream == NULL)) {
  177.         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
  178.         return (cairo_output_stream_t *) &_cairo_output_stream_nil;
  179.     }
  180.  
  181.     _cairo_output_stream_init (stream, NULL, NULL, NULL);
  182.     stream->status = status;
  183.  
  184.     return stream;
  185. }
  186.  
  187. cairo_status_t
  188. _cairo_output_stream_flush (cairo_output_stream_t *stream)
  189. {
  190.     cairo_status_t status;
  191.  
  192.     if (stream->closed)
  193.         return stream->status;
  194.  
  195.     if (stream == &_cairo_output_stream_nil ||
  196.         stream == &_cairo_output_stream_nil_write_error)
  197.     {
  198.         return stream->status;
  199.     }
  200.  
  201.     if (stream->flush_func) {
  202.         status = stream->flush_func (stream);
  203.         /* Don't overwrite a pre-existing status failure. */
  204.         if (stream->status == CAIRO_STATUS_SUCCESS)
  205.             stream->status = status;
  206.     }
  207.  
  208.     return stream->status;
  209. }
  210.  
  211. cairo_status_t
  212. _cairo_output_stream_close (cairo_output_stream_t *stream)
  213. {
  214.     cairo_status_t status;
  215.  
  216.     if (stream->closed)
  217.         return stream->status;
  218.  
  219.     if (stream == &_cairo_output_stream_nil ||
  220.         stream == &_cairo_output_stream_nil_write_error)
  221.     {
  222.         return stream->status;
  223.     }
  224.  
  225.     if (stream->close_func) {
  226.         status = stream->close_func (stream);
  227.         /* Don't overwrite a pre-existing status failure. */
  228.         if (stream->status == CAIRO_STATUS_SUCCESS)
  229.             stream->status = status;
  230.     }
  231.  
  232.     stream->closed = TRUE;
  233.  
  234.     return stream->status;
  235. }
  236.  
  237. cairo_status_t
  238. _cairo_output_stream_destroy (cairo_output_stream_t *stream)
  239. {
  240.     cairo_status_t status;
  241.  
  242.     assert (stream != NULL);
  243.  
  244.     if (stream == &_cairo_output_stream_nil ||
  245.         stream == &_cairo_output_stream_nil_write_error)
  246.     {
  247.         return stream->status;
  248.     }
  249.  
  250.     status = _cairo_output_stream_fini (stream);
  251.     free (stream);
  252.  
  253.     return status;
  254. }
  255.  
  256. void
  257. _cairo_output_stream_write (cairo_output_stream_t *stream,
  258.                             const void *data, size_t length)
  259. {
  260.     if (length == 0)
  261.         return;
  262.  
  263.     if (stream->status)
  264.         return;
  265.  
  266.     stream->status = stream->write_func (stream, data, length);
  267.     stream->position += length;
  268. }
  269.  
  270. void
  271. _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
  272.                                        const unsigned char *data,
  273.                                        size_t length)
  274. {
  275.     const char hex_chars[] = "0123456789abcdef";
  276.     char buffer[2];
  277.     unsigned int i, column;
  278.  
  279.     if (stream->status)
  280.         return;
  281.  
  282.     for (i = 0, column = 0; i < length; i++, column++) {
  283.         if (column == 38) {
  284.             _cairo_output_stream_write (stream, "\n", 1);
  285.             column = 0;
  286.         }
  287.         buffer[0] = hex_chars[(data[i] >> 4) & 0x0f];
  288.         buffer[1] = hex_chars[data[i] & 0x0f];
  289.         _cairo_output_stream_write (stream, buffer, 2);
  290.     }
  291. }
  292.  
  293. /* Format a double in a locale independent way and trim trailing
  294.  * zeros.  Based on code from Alex Larson <alexl@redhat.com>.
  295.  * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html
  296.  *
  297.  * The code in the patch is copyright Red Hat, Inc under the LGPL, but
  298.  * has been relicensed under the LGPL/MPL dual license for inclusion
  299.  * into cairo (see COPYING). -- Kristian Høgsberg <krh@redhat.com>
  300.  */
  301. static void
  302. _cairo_dtostr (char *buffer, size_t size, double d, cairo_bool_t limited_precision)
  303. {
  304.     struct lconv *locale_data;
  305.     const char *decimal_point;
  306.     int decimal_point_len;
  307.     char *p;
  308.     int decimal_len;
  309.     int num_zeros, decimal_digits;
  310.  
  311.     /* Omit the minus sign from negative zero. */
  312.     if (d == 0.0)
  313.         d = 0.0;
  314.  
  315.     locale_data = localeconv ();
  316.     decimal_point = locale_data->decimal_point;
  317.     decimal_point_len = strlen (decimal_point);
  318.  
  319.     assert (decimal_point_len != 0);
  320.  
  321.     if (limited_precision) {
  322.         snprintf (buffer, size, "%.*f", FIXED_POINT_DECIMAL_DIGITS, d);
  323.     } else {
  324.         /* Using "%f" to print numbers less than 0.1 will result in
  325.          * reduced precision due to the default 6 digits after the
  326.          * decimal point.
  327.          *
  328.          * For numbers is < 0.1, we print with maximum precision and count
  329.          * the number of zeros between the decimal point and the first
  330.          * significant digit. We then print the number again with the
  331.          * number of decimal places that gives us the required number of
  332.          * significant digits. This ensures the number is correctly
  333.          * rounded.
  334.          */
  335.         if (fabs (d) >= 0.1) {
  336.             snprintf (buffer, size, "%f", d);
  337.         } else {
  338.             snprintf (buffer, size, "%.18f", d);
  339.             p = buffer;
  340.  
  341.             if (*p == '+' || *p == '-')
  342.                 p++;
  343.  
  344.             while (_cairo_isdigit (*p))
  345.                 p++;
  346.  
  347.             if (strncmp (p, decimal_point, decimal_point_len) == 0)
  348.                 p += decimal_point_len;
  349.  
  350.             num_zeros = 0;
  351.             while (*p++ == '0')
  352.                 num_zeros++;
  353.  
  354.             decimal_digits = num_zeros + SIGNIFICANT_DIGITS_AFTER_DECIMAL;
  355.  
  356.             if (decimal_digits < 18)
  357.                 snprintf (buffer, size, "%.*f", decimal_digits, d);
  358.         }
  359.     }
  360.     p = buffer;
  361.  
  362.     if (*p == '+' || *p == '-')
  363.         p++;
  364.  
  365.     while (_cairo_isdigit (*p))
  366.         p++;
  367.  
  368.     if (strncmp (p, decimal_point, decimal_point_len) == 0) {
  369.         *p = '.';
  370.         decimal_len = strlen (p + decimal_point_len);
  371.         memmove (p + 1, p + decimal_point_len, decimal_len);
  372.         p[1 + decimal_len] = 0;
  373.  
  374.         /* Remove trailing zeros and decimal point if possible. */
  375.         for (p = p + decimal_len; *p == '0'; p--)
  376.             *p = 0;
  377.  
  378.         if (*p == '.') {
  379.             *p = 0;
  380.             p--;
  381.         }
  382.     }
  383. }
  384.  
  385. enum {
  386.     LENGTH_MODIFIER_LONG = 0x100
  387. };
  388.  
  389. /* Here's a limited reimplementation of printf.  The reason for doing
  390.  * this is primarily to special case handling of doubles.  We want
  391.  * locale independent formatting of doubles and we want to trim
  392.  * trailing zeros.  This is handled by dtostr() above, and the code
  393.  * below handles everything else by calling snprintf() to do the
  394.  * formatting.  This functionality is only for internal use and we
  395.  * only implement the formats we actually use.
  396.  */
  397. void
  398. _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
  399.                               const char *fmt, va_list ap)
  400. {
  401. #define SINGLE_FMT_BUFFER_SIZE 32
  402.     char buffer[512], single_fmt[SINGLE_FMT_BUFFER_SIZE];
  403.     int single_fmt_length;
  404.     char *p;
  405.     const char *f, *start;
  406.     int length_modifier, width;
  407.     cairo_bool_t var_width;
  408.  
  409.     if (stream->status)
  410.         return;
  411.  
  412.     f = fmt;
  413.     p = buffer;
  414.     while (*f != '\0') {
  415.         if (p == buffer + sizeof (buffer)) {
  416.             _cairo_output_stream_write (stream, buffer, sizeof (buffer));
  417.             p = buffer;
  418.         }
  419.  
  420.         if (*f != '%') {
  421.             *p++ = *f++;
  422.             continue;
  423.         }
  424.  
  425.         start = f;
  426.         f++;
  427.  
  428.         if (*f == '0')
  429.             f++;
  430.  
  431.         var_width = FALSE;
  432.         if (*f == '*') {
  433.             var_width = TRUE;
  434.             f++;
  435.         }
  436.  
  437.         while (_cairo_isdigit (*f))
  438.             f++;
  439.  
  440.         length_modifier = 0;
  441.         if (*f == 'l') {
  442.             length_modifier = LENGTH_MODIFIER_LONG;
  443.             f++;
  444.         }
  445.  
  446.         /* The only format strings exist in the cairo implementation
  447.          * itself. So there's an internal consistency problem if any
  448.          * of them is larger than our format buffer size. */
  449.         single_fmt_length = f - start + 1;
  450.         assert (single_fmt_length + 1 <= SINGLE_FMT_BUFFER_SIZE);
  451.  
  452.         /* Reuse the format string for this conversion. */
  453.         memcpy (single_fmt, start, single_fmt_length);
  454.         single_fmt[single_fmt_length] = '\0';
  455.  
  456.         /* Flush contents of buffer before snprintf()'ing into it. */
  457.         _cairo_output_stream_write (stream, buffer, p - buffer);
  458.  
  459.         /* We group signed and unsigned together in this switch, the
  460.          * only thing that matters here is the size of the arguments,
  461.          * since we're just passing the data through to sprintf(). */
  462.         switch (*f | length_modifier) {
  463.         case '%':
  464.             buffer[0] = *f;
  465.             buffer[1] = 0;
  466.             break;
  467.         case 'd':
  468.         case 'u':
  469.         case 'o':
  470.         case 'x':
  471.         case 'X':
  472.             if (var_width) {
  473.                 width = va_arg (ap, int);
  474.                 snprintf (buffer, sizeof buffer,
  475.                           single_fmt, width, va_arg (ap, int));
  476.             } else {
  477.                 snprintf (buffer, sizeof buffer, single_fmt, va_arg (ap, int));
  478.             }
  479.             break;
  480.         case 'd' | LENGTH_MODIFIER_LONG:
  481.         case 'u' | LENGTH_MODIFIER_LONG:
  482.         case 'o' | LENGTH_MODIFIER_LONG:
  483.         case 'x' | LENGTH_MODIFIER_LONG:
  484.         case 'X' | LENGTH_MODIFIER_LONG:
  485.             if (var_width) {
  486.                 width = va_arg (ap, int);
  487.                 snprintf (buffer, sizeof buffer,
  488.                           single_fmt, width, va_arg (ap, long int));
  489.             } else {
  490.                 snprintf (buffer, sizeof buffer,
  491.                           single_fmt, va_arg (ap, long int));
  492.             }
  493.             break;
  494.         case 's':
  495.             snprintf (buffer, sizeof buffer,
  496.                       single_fmt, va_arg (ap, const char *));
  497.             break;
  498.         case 'f':
  499.             _cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double), FALSE);
  500.             break;
  501.         case 'g':
  502.             _cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double), TRUE);
  503.             break;
  504.         case 'c':
  505.             buffer[0] = va_arg (ap, int);
  506.             buffer[1] = 0;
  507.             break;
  508.         default:
  509.             ASSERT_NOT_REACHED;
  510.         }
  511.         p = buffer + strlen (buffer);
  512.         f++;
  513.     }
  514.  
  515.     _cairo_output_stream_write (stream, buffer, p - buffer);
  516. }
  517.  
  518. void
  519. _cairo_output_stream_printf (cairo_output_stream_t *stream,
  520.                              const char *fmt, ...)
  521. {
  522.     va_list ap;
  523.  
  524.     va_start (ap, fmt);
  525.  
  526.     _cairo_output_stream_vprintf (stream, fmt, ap);
  527.  
  528.     va_end (ap);
  529. }
  530.  
  531. long
  532. _cairo_output_stream_get_position (cairo_output_stream_t *stream)
  533. {
  534.     return stream->position;
  535. }
  536.  
  537. cairo_status_t
  538. _cairo_output_stream_get_status (cairo_output_stream_t *stream)
  539. {
  540.     return stream->status;
  541. }
  542.  
  543. /* Maybe this should be a configure time option, so embedded targets
  544.  * don't have to pull in stdio. */
  545.  
  546.  
  547. typedef struct _stdio_stream {
  548.     cairo_output_stream_t        base;
  549.     FILE                        *file;
  550. } stdio_stream_t;
  551.  
  552. static cairo_status_t
  553. stdio_write (cairo_output_stream_t *base,
  554.              const unsigned char *data, unsigned int length)
  555. {
  556.     stdio_stream_t *stream = (stdio_stream_t *) base;
  557.  
  558.     if (fwrite (data, 1, length, stream->file) != length)
  559.         return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
  560.  
  561.     return CAIRO_STATUS_SUCCESS;
  562. }
  563.  
  564. static cairo_status_t
  565. stdio_flush (cairo_output_stream_t *base)
  566. {
  567.     stdio_stream_t *stream = (stdio_stream_t *) base;
  568.  
  569.     fflush (stream->file);
  570.  
  571.     if (ferror (stream->file))
  572.         return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
  573.     else
  574.         return CAIRO_STATUS_SUCCESS;
  575. }
  576.  
  577. static cairo_status_t
  578. stdio_close (cairo_output_stream_t *base)
  579. {
  580.     cairo_status_t status;
  581.     stdio_stream_t *stream = (stdio_stream_t *) base;
  582.  
  583.     status = stdio_flush (base);
  584.  
  585.     fclose (stream->file);
  586.  
  587.     return status;
  588. }
  589.  
  590. cairo_output_stream_t *
  591. _cairo_output_stream_create_for_file (FILE *file)
  592. {
  593.     stdio_stream_t *stream;
  594.  
  595.     if (file == NULL) {
  596.         _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
  597.         return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
  598.     }
  599.  
  600.     stream = malloc (sizeof *stream);
  601.     if (unlikely (stream == NULL)) {
  602.         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
  603.         return (cairo_output_stream_t *) &_cairo_output_stream_nil;
  604.     }
  605.  
  606.     _cairo_output_stream_init (&stream->base,
  607.                                stdio_write, stdio_flush, stdio_flush);
  608.     stream->file = file;
  609.  
  610.     return &stream->base;
  611. }
  612.  
  613. cairo_output_stream_t *
  614. _cairo_output_stream_create_for_filename (const char *filename)
  615. {
  616.     stdio_stream_t *stream;
  617.     FILE *file;
  618.  
  619.     if (filename == NULL)
  620.         return _cairo_null_stream_create ();
  621.  
  622.     file = fopen (filename, "wb");
  623.     if (file == NULL) {
  624.         switch (errno) {
  625.         case ENOMEM:
  626.             _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
  627.             return (cairo_output_stream_t *) &_cairo_output_stream_nil;
  628.         default:
  629.             _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
  630.             return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
  631.         }
  632.     }
  633.  
  634.     stream = malloc (sizeof *stream);
  635.     if (unlikely (stream == NULL)) {
  636.         fclose (file);
  637.         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
  638.         return (cairo_output_stream_t *) &_cairo_output_stream_nil;
  639.     }
  640.  
  641.     _cairo_output_stream_init (&stream->base,
  642.                                stdio_write, stdio_flush, stdio_close);
  643.     stream->file = file;
  644.  
  645.     return &stream->base;
  646. }
  647.  
  648.  
  649. typedef struct _memory_stream {
  650.     cairo_output_stream_t       base;
  651.     cairo_array_t               array;
  652. } memory_stream_t;
  653.  
  654. static cairo_status_t
  655. memory_write (cairo_output_stream_t *base,
  656.               const unsigned char *data, unsigned int length)
  657. {
  658.     memory_stream_t *stream = (memory_stream_t *) base;
  659.  
  660.     return _cairo_array_append_multiple (&stream->array, data, length);
  661. }
  662.  
  663. static cairo_status_t
  664. memory_close (cairo_output_stream_t *base)
  665. {
  666.     memory_stream_t *stream = (memory_stream_t *) base;
  667.  
  668.     _cairo_array_fini (&stream->array);
  669.  
  670.     return CAIRO_STATUS_SUCCESS;
  671. }
  672.  
  673. cairo_output_stream_t *
  674. _cairo_memory_stream_create (void)
  675. {
  676.     memory_stream_t *stream;
  677.  
  678.     stream = malloc (sizeof *stream);
  679.     if (unlikely (stream == NULL)) {
  680.         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
  681.         return (cairo_output_stream_t *) &_cairo_output_stream_nil;
  682.     }
  683.  
  684.     _cairo_output_stream_init (&stream->base, memory_write, NULL, memory_close);
  685.     _cairo_array_init (&stream->array, 1);
  686.  
  687.     return &stream->base;
  688. }
  689.  
  690. cairo_status_t
  691. _cairo_memory_stream_destroy (cairo_output_stream_t *abstract_stream,
  692.                               unsigned char **data_out,
  693.                               unsigned long *length_out)
  694. {
  695.     memory_stream_t *stream;
  696.     cairo_status_t status;
  697.  
  698.     status = abstract_stream->status;
  699.     if (unlikely (status))
  700.         return _cairo_output_stream_destroy (abstract_stream);
  701.  
  702.     stream = (memory_stream_t *) abstract_stream;
  703.  
  704.     *length_out = _cairo_array_num_elements (&stream->array);
  705.     *data_out = malloc (*length_out);
  706.     if (unlikely (*data_out == NULL)) {
  707.         status = _cairo_output_stream_destroy (abstract_stream);
  708.         assert (status == CAIRO_STATUS_SUCCESS);
  709.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  710.     }
  711.     memcpy (*data_out, _cairo_array_index (&stream->array, 0), *length_out);
  712.  
  713.     return _cairo_output_stream_destroy (abstract_stream);
  714. }
  715.  
  716. void
  717. _cairo_memory_stream_copy (cairo_output_stream_t *base,
  718.                            cairo_output_stream_t *dest)
  719. {
  720.     memory_stream_t *stream = (memory_stream_t *) base;
  721.  
  722.     if (dest->status)
  723.         return;
  724.  
  725.     if (base->status) {
  726.         dest->status = base->status;
  727.         return;
  728.     }
  729.  
  730.     _cairo_output_stream_write (dest,
  731.                                 _cairo_array_index (&stream->array, 0),
  732.                                 _cairo_array_num_elements (&stream->array));
  733. }
  734.  
  735. int
  736. _cairo_memory_stream_length (cairo_output_stream_t *base)
  737. {
  738.     memory_stream_t *stream = (memory_stream_t *) base;
  739.  
  740.     return _cairo_array_num_elements (&stream->array);
  741. }
  742.  
  743. static cairo_status_t
  744. null_write (cairo_output_stream_t *base,
  745.             const unsigned char *data, unsigned int length)
  746. {
  747.     return CAIRO_STATUS_SUCCESS;
  748. }
  749.  
  750. cairo_output_stream_t *
  751. _cairo_null_stream_create (void)
  752. {
  753.     cairo_output_stream_t *stream;
  754.  
  755.     stream = malloc (sizeof *stream);
  756.     if (unlikely (stream == NULL)) {
  757.         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
  758.         return (cairo_output_stream_t *) &_cairo_output_stream_nil;
  759.     }
  760.  
  761.     _cairo_output_stream_init (stream, null_write, NULL, NULL);
  762.  
  763.     return stream;
  764. }
  765.