1
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2
/* cairo-output-stream.c: Output stream abstraction
3
 *
4
 * Copyright © 2005 Red Hat, Inc
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 Red Hat, Inc.
32
 *
33
 * Author(s):
34
 *	Kristian Høgsberg <krh@redhat.com>
35
 */
36

            
37
#define _DEFAULT_SOURCE /* for snprintf() */
38
#include "cairoint.h"
39

            
40
#include "cairo-output-stream-private.h"
41

            
42
#include "cairo-array-private.h"
43
#include "cairo-error-private.h"
44
#include "cairo-compiler-private.h"
45

            
46
#include <stdio.h>
47
#include <errno.h>
48

            
49
/* Numbers printed with %f are printed with this number of significant
50
 * digits after the decimal.
51
 */
52
#define SIGNIFICANT_DIGITS_AFTER_DECIMAL 6
53

            
54
/* Numbers printed with %g are assumed to only have %CAIRO_FIXED_FRAC_BITS
55
 * bits of precision available after the decimal point.
56
 *
57
 * FIXED_POINT_DECIMAL_DIGITS specifies the minimum number of decimal
58
 * digits after the decimal point required to preserve the available
59
 * precision.
60
 *
61
 * The conversion is:
62
 *
63
 * <programlisting>
64
 * FIXED_POINT_DECIMAL_DIGITS = ceil( CAIRO_FIXED_FRAC_BITS * ln(2)/ln(10) )
65
 * </programlisting>
66
 *
67
 * We can replace ceil(x) with (int)(x+1) since x will never be an
68
 * integer for any likely value of %CAIRO_FIXED_FRAC_BITS.
69
 */
70
#define FIXED_POINT_DECIMAL_DIGITS ((int)(CAIRO_FIXED_FRAC_BITS*0.301029996 + 1))
71

            
72
void
73
2583
_cairo_output_stream_init (cairo_output_stream_t            *stream,
74
			   cairo_output_stream_write_func_t  write_func,
75
			   cairo_output_stream_flush_func_t  flush_func,
76
			   cairo_output_stream_close_func_t  close_func)
77
{
78
2583
    stream->write_func = write_func;
79
2583
    stream->flush_func = flush_func;
80
2583
    stream->close_func = close_func;
81
2583
    stream->position = 0;
82
2583
    stream->status = CAIRO_STATUS_SUCCESS;
83
2583
    stream->closed = FALSE;
84
2583
}
85

            
86
cairo_status_t
87
2583
_cairo_output_stream_fini (cairo_output_stream_t *stream)
88
{
89
2583
    return _cairo_output_stream_close (stream);
90
}
91

            
92
const cairo_output_stream_t _cairo_output_stream_nil = {
93
    NULL, /* write_func */
94
    NULL, /* flush_func */
95
    NULL, /* close_func */
96
    0,    /* position */
97
    CAIRO_STATUS_NO_MEMORY,
98
    FALSE /* closed */
99
};
100

            
101
static const cairo_output_stream_t _cairo_output_stream_nil_write_error = {
102
    NULL, /* write_func */
103
    NULL, /* flush_func */
104
    NULL, /* close_func */
105
    0,    /* position */
106
    CAIRO_STATUS_WRITE_ERROR,
107
    FALSE /* closed */
108
};
109

            
110
typedef struct _cairo_output_stream_with_closure {
111
    cairo_output_stream_t	 base;
112
    cairo_write_func_t		 write_func;
113
    cairo_close_func_t		 close_func;
114
    void			*closure;
115
} cairo_output_stream_with_closure_t;
116

            
117

            
118
static cairo_status_t
119
782
closure_write (cairo_output_stream_t *stream,
120
	       const unsigned char *data, unsigned int length)
121
{
122
782
    cairo_output_stream_with_closure_t *stream_with_closure =
123
	(cairo_output_stream_with_closure_t *) stream;
124

            
125
782
    if (stream_with_closure->write_func == NULL)
126
752
	return CAIRO_STATUS_SUCCESS;
127

            
128
30
    return stream_with_closure->write_func (stream_with_closure->closure,
129
					    data, length);
130
}
131

            
132
static cairo_status_t
133
4
closure_close (cairo_output_stream_t *stream)
134
{
135
4
    cairo_output_stream_with_closure_t *stream_with_closure =
136
	(cairo_output_stream_with_closure_t *) stream;
137

            
138
4
    if (stream_with_closure->close_func != NULL)
139
	return stream_with_closure->close_func (stream_with_closure->closure);
140
    else
141
4
	return CAIRO_STATUS_SUCCESS;
142
}
143

            
144
cairo_output_stream_t *
145
4
_cairo_output_stream_create (cairo_write_func_t		write_func,
146
			     cairo_close_func_t		close_func,
147
			     void			*closure)
148
{
149
    cairo_output_stream_with_closure_t *stream;
150

            
151
4
    stream = _cairo_calloc (sizeof (cairo_output_stream_with_closure_t));
152
4
    if (unlikely (stream == NULL)) {
153
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
154
	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
155
    }
156

            
157
4
    _cairo_output_stream_init (&stream->base,
158
			       closure_write, NULL, closure_close);
159
4
    stream->write_func = write_func;
160
4
    stream->close_func = close_func;
161
4
    stream->closure = closure;
162

            
163
4
    return &stream->base;
164
}
165

            
166
cairo_output_stream_t *
167
_cairo_output_stream_create_in_error (cairo_status_t status)
168
{
169
    cairo_output_stream_t *stream;
170

            
171
    /* check for the common ones */
172
    if (status == CAIRO_STATUS_NO_MEMORY)
173
	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
174
    if (status == CAIRO_STATUS_WRITE_ERROR)
175
	return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
176

            
177
    stream = _cairo_calloc (sizeof (cairo_output_stream_t));
178
    if (unlikely (stream == NULL)) {
179
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
180
	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
181
    }
182

            
183
    _cairo_output_stream_init (stream, NULL, NULL, NULL);
184
    stream->status = status;
185

            
186
    return stream;
187
}
188

            
189
cairo_status_t
190
3
_cairo_output_stream_flush (cairo_output_stream_t *stream)
191
{
192
    cairo_status_t status;
193

            
194
3
    if (stream->closed)
195
	return stream->status;
196

            
197
3
    if (stream == &_cairo_output_stream_nil ||
198
	stream == &_cairo_output_stream_nil_write_error)
199
    {
200
	return stream->status;
201
    }
202

            
203
3
    if (stream->flush_func) {
204
	status = stream->flush_func (stream);
205
	/* Don't overwrite a pre-existing status failure. */
206
	if (stream->status == CAIRO_STATUS_SUCCESS)
207
	    stream->status = status;
208
    }
209

            
210
3
    return stream->status;
211
}
212

            
213
cairo_status_t
214
2584
_cairo_output_stream_close (cairo_output_stream_t *stream)
215
{
216
    cairo_status_t status;
217

            
218
2584
    if (stream->closed)
219
1
	return stream->status;
220

            
221
2583
    if (stream == &_cairo_output_stream_nil ||
222
	stream == &_cairo_output_stream_nil_write_error)
223
    {
224
	return stream->status;
225
    }
226

            
227
2583
    if (stream->close_func) {
228
2583
	status = stream->close_func (stream);
229
	/* Don't overwrite a pre-existing status failure. */
230
2583
	if (stream->status == CAIRO_STATUS_SUCCESS)
231
2583
	    stream->status = status;
232
    }
233

            
234
2583
    stream->closed = TRUE;
235

            
236
2583
    return stream->status;
237
}
238

            
239
cairo_status_t
240
2583
_cairo_output_stream_destroy (cairo_output_stream_t *stream)
241
{
242
    cairo_status_t status;
243

            
244
2583
    assert (stream != NULL);
245

            
246
2583
    if (stream == &_cairo_output_stream_nil ||
247
	stream == &_cairo_output_stream_nil_write_error)
248
    {
249
	return stream->status;
250
    }
251

            
252
2583
    status = _cairo_output_stream_fini (stream);
253
2583
    free (stream);
254

            
255
2583
    return status;
256
}
257

            
258
void
259
90463
_cairo_output_stream_write (cairo_output_stream_t *stream,
260
			    const void *data, size_t length)
261
{
262
90463
    if (length == 0 || stream->status)
263
930
	return;
264

            
265
89533
    if (stream->closed) {
266
1
	stream->status = CAIRO_STATUS_WRITE_ERROR;
267
1
	return;
268
    }
269

            
270
89532
    stream->status = stream->write_func (stream, data, length);
271
89532
    stream->position += length;
272
}
273

            
274
void
275
_cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
276
				       const unsigned char *data,
277
				       size_t length)
278
{
279
    const char hex_chars[] = "0123456789abcdef";
280
    char buffer[2];
281
    unsigned int i, column;
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
 * https://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
3254
_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
3254
    if (d == 0.0)
313
719
	d = 0.0;
314

            
315
3254
    decimal_point = _cairo_get_locale_decimal_point ();
316
3254
    decimal_point_len = strlen (decimal_point);
317

            
318
3254
    assert (decimal_point_len != 0);
319

            
320
3254
    if (limited_precision) {
321
908
	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
2346
	if (fabs (d) >= 0.1) {
335
1783
	    snprintf (buffer, size, "%f", d);
336
	} else {
337
563
	    snprintf (buffer, size, "%.18f", d);
338
563
	    p = buffer;
339

            
340
563
	    if (*p == '+' || *p == '-')
341
		p++;
342

            
343
1126
	    while (_cairo_isdigit (*p))
344
563
		p++;
345

            
346
563
	    if (strncmp (p, decimal_point, decimal_point_len) == 0)
347
563
		p += decimal_point_len;
348

            
349
563
	    num_zeros = 0;
350
10697
	    while (*p++ == '0')
351
10134
		num_zeros++;
352

            
353
563
	    decimal_digits = num_zeros + SIGNIFICANT_DIGITS_AFTER_DECIMAL;
354

            
355
563
	    if (decimal_digits < 18)
356
		snprintf (buffer, size, "%.*f", decimal_digits, d);
357
	}
358
    }
359
3254
    p = buffer;
360

            
361
3254
    if (*p == '+' || *p == '-')
362
211
	p++;
363

            
364
11659
    while (_cairo_isdigit (*p))
365
8405
	p++;
366

            
367
3254
    if (strncmp (p, decimal_point, decimal_point_len) == 0) {
368
3254
	*p = '.';
369
3254
	decimal_len = strlen (p + decimal_point_len);
370
3254
	memmove (p + 1, p + decimal_point_len, decimal_len);
371
3254
	p[1 + decimal_len] = 0;
372

            
373
	/* Remove trailing zeros and decimal point if possible. */
374
25714
	for (p = p + decimal_len; *p == '0'; p--)
375
22460
	    *p = 0;
376

            
377
3254
	if (*p == '.') {
378
2873
	    *p = 0;
379
2873
	    p--;
380
	}
381
    }
382
3254
}
383

            
384
enum {
385
    LENGTH_MODIFIER_LONG = 0x100,
386
    LENGTH_MODIFIER_LONG_LONG = 0x200
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
4612
_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
4612
    f = fmt;
410
4612
    p = buffer;
411
90242
    while (*f != '\0') {
412
85630
	if (p == buffer + sizeof (buffer)) {
413
20
	    _cairo_output_stream_write (stream, buffer, sizeof (buffer));
414
20
	    p = buffer;
415
	}
416

            
417
85630
	if (*f != '%') {
418
79889
	    *p++ = *f++;
419
79889
	    continue;
420
	}
421

            
422
5741
	start = f;
423
5741
	f++;
424

            
425
5741
	if (*f == '0')
426
	    f++;
427

            
428
5741
        var_width = FALSE;
429
5741
        if (*f == '*') {
430
            var_width = TRUE;
431
	    f++;
432
        }
433

            
434
5741
	while (_cairo_isdigit (*f))
435
	    f++;
436

            
437
5741
	length_modifier = 0;
438
5741
	if (*f == 'l') {
439
84
	    length_modifier = LENGTH_MODIFIER_LONG;
440
84
	    f++;
441
84
	    if (*f == 'l') {
442
74
		length_modifier = LENGTH_MODIFIER_LONG_LONG;
443
74
		f++;
444
	    }
445
	}
446

            
447
	/* The only format strings exist in the cairo implementation
448
	 * itself. So there's an internal consistency problem if any
449
	 * of them is larger than our format buffer size. */
450
5741
	single_fmt_length = f - start + 1;
451
5741
	assert (single_fmt_length + 1 <= SINGLE_FMT_BUFFER_SIZE);
452

            
453
	/* Reuse the format string for this conversion. */
454
5741
	memcpy (single_fmt, start, single_fmt_length);
455
5741
	single_fmt[single_fmt_length] = '\0';
456

            
457
	/* Flush contents of buffer before snprintf()'ing into it. */
458
5741
	_cairo_output_stream_write (stream, buffer, p - buffer);
459

            
460
	/* We group signed and unsigned together in this switch, the
461
	 * only thing that matters here is the size of the arguments,
462
	 * since we're just passing the data through to sprintf(). */
463
5741
	switch (*f | length_modifier) {
464
747
	case '%':
465
747
	    buffer[0] = *f;
466
747
	    buffer[1] = 0;
467
747
	    break;
468
1195
	case 'd':
469
	case 'u':
470
	case 'o':
471
	case 'x':
472
	case 'X':
473
1195
            if (var_width) {
474
                width = va_arg (ap, int);
475
                snprintf (buffer, sizeof buffer,
476
                          single_fmt, width, va_arg (ap, int));
477
            } else {
478
1195
                snprintf (buffer, sizeof buffer, single_fmt, va_arg (ap, int));
479
            }
480
1195
	    break;
481
10
	case 'd' | LENGTH_MODIFIER_LONG:
482
	case 'u' | LENGTH_MODIFIER_LONG:
483
	case 'o' | LENGTH_MODIFIER_LONG:
484
	case 'x' | LENGTH_MODIFIER_LONG:
485
	case 'X' | LENGTH_MODIFIER_LONG:
486
10
            if (var_width) {
487
                width = va_arg (ap, int);
488
                snprintf (buffer, sizeof buffer,
489
                          single_fmt, width, va_arg (ap, long int));
490
            } else {
491
10
                snprintf (buffer, sizeof buffer,
492
                          single_fmt, va_arg (ap, long int));
493
            }
494
10
	    break;
495
74
	case 'd' | LENGTH_MODIFIER_LONG_LONG:
496
	case 'u' | LENGTH_MODIFIER_LONG_LONG:
497
	case 'o' | LENGTH_MODIFIER_LONG_LONG:
498
	case 'x' | LENGTH_MODIFIER_LONG_LONG:
499
	case 'X' | LENGTH_MODIFIER_LONG_LONG:
500
74
	    if (var_width) {
501
		width = va_arg (ap, int);
502
		snprintf (buffer, sizeof buffer,
503
			  single_fmt, width, va_arg (ap, long long int));
504
	    } else {
505
74
		snprintf (buffer, sizeof buffer,
506
			  single_fmt, va_arg (ap, long long int));
507
	    }
508
74
	    break;
509
441
	case 's': {
510
	    /* Write out strings as they may be larger than the buffer. */
511
441
	    const char *s = va_arg (ap, const char *);
512
441
	    int len = strlen(s);
513
441
	    _cairo_output_stream_write (stream, s, len);
514
441
	    buffer[0] = 0;
515
	    }
516
441
	    break;
517
2346
	case 'f':
518
2346
	    _cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double), FALSE);
519
2346
	    break;
520
908
	case 'g':
521
908
	    _cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double), TRUE);
522
908
	    break;
523
20
	case 'c':
524
20
	    buffer[0] = va_arg (ap, int);
525
20
	    buffer[1] = 0;
526
20
	    break;
527
	default:
528
	    ASSERT_NOT_REACHED;
529
	}
530
5741
	p = buffer + strlen (buffer);
531
5741
	f++;
532
    }
533

            
534
4612
    _cairo_output_stream_write (stream, buffer, p - buffer);
535
4612
}
536

            
537
void
538
2692
_cairo_output_stream_printf (cairo_output_stream_t *stream,
539
			     const char *fmt, ...)
540
{
541
    va_list ap;
542

            
543
2692
    va_start (ap, fmt);
544

            
545
2692
    _cairo_output_stream_vprintf (stream, fmt, ap);
546

            
547
2692
    va_end (ap);
548
2692
}
549

            
550
/* Matrix elements that are smaller than the value of the largest element * MATRIX_ROUNDING_TOLERANCE
551
 * are rounded down to zero. */
552
#define MATRIX_ROUNDING_TOLERANCE 1e-12
553

            
554
void
555
23
_cairo_output_stream_print_matrix (cairo_output_stream_t *stream,
556
				   const cairo_matrix_t  *matrix)
557
{
558
    cairo_matrix_t m;
559
    double s, e;
560

            
561
23
    m = *matrix;
562
23
    s = fabs (m.xx);
563
23
    if (fabs (m.xy) > s)
564
	s = fabs (m.xy);
565
23
    if (fabs (m.yx) > s)
566
	s = fabs (m.yx);
567
23
    if (fabs (m.yy) > s)
568
1
	s = fabs (m.yy);
569

            
570
23
    e = s * MATRIX_ROUNDING_TOLERANCE;
571
23
    if (fabs(m.xx) < e)
572
	m.xx = 0;
573
23
    if (fabs(m.xy) < e)
574
23
	m.xy = 0;
575
23
    if (fabs(m.yx) < e)
576
23
	m.yx = 0;
577
23
    if (fabs(m.yy) < e)
578
	m.yy = 0;
579
23
    if (fabs(m.x0) < e)
580
	m.x0 = 0;
581
23
    if (fabs(m.y0) < e)
582
	m.y0 = 0;
583

            
584
23
    _cairo_output_stream_printf (stream,
585
				 "%f %f %f %f %f %f",
586
				 m.xx, m.yx, m.xy, m.yy, m.x0, m.y0);
587
23
}
588

            
589
long long
590
361
_cairo_output_stream_get_position (cairo_output_stream_t *stream)
591
{
592
361
    return stream->position;
593
}
594

            
595
cairo_status_t
596
11516
_cairo_output_stream_get_status (cairo_output_stream_t *stream)
597
{
598
11516
    return stream->status;
599
}
600

            
601
/* Maybe this should be a configure time option, so embedded targets
602
 * don't have to pull in stdio. */
603

            
604

            
605
typedef struct _stdio_stream {
606
    cairo_output_stream_t	 base;
607
    FILE			*file;
608
} stdio_stream_t;
609

            
610
static cairo_status_t
611
23215
stdio_write (cairo_output_stream_t *base,
612
	     const unsigned char *data, unsigned int length)
613
{
614
23215
    stdio_stream_t *stream = (stdio_stream_t *) base;
615

            
616
23215
    if (fwrite (data, 1, length, stream->file) != length)
617
	return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
618

            
619
23215
    return CAIRO_STATUS_SUCCESS;
620
}
621

            
622
static cairo_status_t
623
17
stdio_flush (cairo_output_stream_t *base)
624
{
625
17
    stdio_stream_t *stream = (stdio_stream_t *) base;
626

            
627
17
    fflush (stream->file);
628

            
629
17
    if (ferror (stream->file))
630
	return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
631
    else
632
17
	return CAIRO_STATUS_SUCCESS;
633
}
634

            
635
static cairo_status_t
636
12
stdio_close (cairo_output_stream_t *base)
637
{
638
    cairo_status_t status;
639
12
    stdio_stream_t *stream = (stdio_stream_t *) base;
640

            
641
12
    status = stdio_flush (base);
642

            
643
12
    fclose (stream->file);
644

            
645
12
    return status;
646
}
647

            
648
cairo_output_stream_t *
649
5
_cairo_output_stream_create_for_file (FILE *file)
650
{
651
    stdio_stream_t *stream;
652

            
653
5
    if (file == NULL) {
654
	_cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
655
	return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
656
    }
657

            
658
5
    stream = _cairo_calloc (sizeof *stream);
659
5
    if (unlikely (stream == NULL)) {
660
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
661
	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
662
    }
663

            
664
5
    _cairo_output_stream_init (&stream->base,
665
			       stdio_write, stdio_flush, stdio_flush);
666
5
    stream->file = file;
667

            
668
5
    return &stream->base;
669
}
670

            
671
cairo_output_stream_t *
672
12
_cairo_output_stream_create_for_filename (const char *filename)
673
{
674
    stdio_stream_t *stream;
675
    FILE *file;
676
    cairo_status_t status;
677

            
678
12
    if (filename == NULL)
679
	return _cairo_null_stream_create ();
680

            
681
12
    status = _cairo_fopen (filename, "wb", &file);
682

            
683
12
    if (status != CAIRO_STATUS_SUCCESS)
684
	return _cairo_output_stream_create_in_error (status);
685

            
686
12
    if (file == NULL) {
687
	switch (errno) {
688
	case ENOMEM:
689
	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
690
	    return (cairo_output_stream_t *) &_cairo_output_stream_nil;
691
	default:
692
	    _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
693
	    return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
694
	}
695
    }
696

            
697
12
    stream = _cairo_calloc (sizeof *stream);
698
12
    if (unlikely (stream == NULL)) {
699
	fclose (file);
700
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
701
	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
702
    }
703

            
704
12
    _cairo_output_stream_init (&stream->base,
705
			       stdio_write, stdio_flush, stdio_close);
706
12
    stream->file = file;
707

            
708
12
    return &stream->base;
709
}
710

            
711

            
712
typedef struct _memory_stream {
713
    cairo_output_stream_t	base;
714
    cairo_array_t		array;
715
} memory_stream_t;
716

            
717
static cairo_status_t
718
55230
memory_write (cairo_output_stream_t *base,
719
	      const unsigned char *data, unsigned int length)
720
{
721
55230
    memory_stream_t *stream = (memory_stream_t *) base;
722

            
723
55230
    return _cairo_array_append_multiple (&stream->array, data, length);
724
}
725

            
726
static cairo_status_t
727
2330
memory_close (cairo_output_stream_t *base)
728
{
729
2330
    memory_stream_t *stream = (memory_stream_t *) base;
730

            
731
2330
    _cairo_array_fini (&stream->array);
732

            
733
2330
    return CAIRO_STATUS_SUCCESS;
734
}
735

            
736
cairo_output_stream_t *
737
2330
_cairo_memory_stream_create (void)
738
{
739
    memory_stream_t *stream;
740

            
741
2330
    stream = _cairo_calloc (sizeof *stream);
742
2330
    if (unlikely (stream == NULL)) {
743
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
744
	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
745
    }
746

            
747
2330
    _cairo_output_stream_init (&stream->base, memory_write, NULL, memory_close);
748
2330
    _cairo_array_init (&stream->array, 1);
749

            
750
2330
    return &stream->base;
751
}
752

            
753
cairo_status_t
754
1766
_cairo_memory_stream_destroy (cairo_output_stream_t *abstract_stream,
755
			      unsigned char **data_out,
756
			      unsigned long *length_out)
757
{
758
    memory_stream_t *stream;
759
    cairo_status_t status;
760

            
761
1766
    status = abstract_stream->status;
762
1766
    if (unlikely (status))
763
	return _cairo_output_stream_destroy (abstract_stream);
764

            
765
1766
    stream = (memory_stream_t *) abstract_stream;
766

            
767
1766
    *length_out = _cairo_array_num_elements (&stream->array);
768
1766
    *data_out = _cairo_calloc (*length_out);
769
1766
    if (unlikely (*data_out == NULL)) {
770
	status = _cairo_output_stream_destroy (abstract_stream);
771
	assert (status == CAIRO_STATUS_SUCCESS);
772
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
773
    }
774
1766
    memcpy (*data_out, _cairo_array_index (&stream->array, 0), *length_out);
775

            
776
1766
    return _cairo_output_stream_destroy (abstract_stream);
777
}
778

            
779
void
780
561
_cairo_memory_stream_copy (cairo_output_stream_t *base,
781
			   cairo_output_stream_t *dest)
782
{
783
561
    memory_stream_t *stream = (memory_stream_t *) base;
784

            
785
561
    if (base->status) {
786
	dest->status = base->status;
787
	return;
788
    }
789

            
790
561
    _cairo_output_stream_write (dest,
791
561
				_cairo_array_index (&stream->array, 0),
792
561
				_cairo_array_num_elements (&stream->array));
793
}
794

            
795
int
796
19
_cairo_memory_stream_length (cairo_output_stream_t *base)
797
{
798
19
    memory_stream_t *stream = (memory_stream_t *) base;
799

            
800
19
    return _cairo_array_num_elements (&stream->array);
801
}
802

            
803
static cairo_status_t
804
null_write (cairo_output_stream_t *base,
805
	    const unsigned char *data, unsigned int length)
806
{
807
    return CAIRO_STATUS_SUCCESS;
808
}
809

            
810
cairo_output_stream_t *
811
_cairo_null_stream_create (void)
812
{
813
    cairo_output_stream_t *stream;
814

            
815
    stream = _cairo_calloc (sizeof *stream);
816
    if (unlikely (stream == NULL)) {
817
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
818
	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
819
    }
820

            
821
    _cairo_output_stream_init (stream, null_write, NULL, NULL);
822

            
823
    return stream;
824
}