Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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