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