1 /* cairo-output-stream.c: Output stream abstraction
3 * Copyright © 2005 Red Hat, Inc
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
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/
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.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is Red Hat, Inc.
33 * Kristian Høgsberg <krh@redhat.com>
36 #define _BSD_SOURCE /* for snprintf() */
39 #include "cairo-output-stream-private.h"
40 #include "cairo-compiler-private.h"
47 /* Numbers printed with %f are printed with this number of significant
48 * digits after the decimal.
50 #define SIGNIFICANT_DIGITS_AFTER_DECIMAL 6
52 /* Numbers printed with %g are assumed to only have %CAIRO_FIXED_FRAC_BITS
53 * bits of precision available after the decimal point.
55 * FIXED_POINT_DECIMAL_DIGITS specifies the minimum number of decimal
56 * digits after the decimal point required to preserve the available
62 * FIXED_POINT_DECIMAL_DIGITS = ceil( CAIRO_FIXED_FRAC_BITS * ln(2)/ln(10) )
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.
68 #define FIXED_POINT_DECIMAL_DIGITS ((int)(CAIRO_FIXED_FRAC_BITS*0.301029996 + 1))
71 _cairo_output_stream_init (cairo_output_stream_t
*stream
,
72 cairo_output_stream_write_func_t write_func
,
73 cairo_output_stream_close_func_t close_func
)
75 stream
->write_func
= write_func
;
76 stream
->close_func
= close_func
;
78 stream
->status
= CAIRO_STATUS_SUCCESS
;
79 stream
->closed
= FALSE
;
83 _cairo_output_stream_fini (cairo_output_stream_t
*stream
)
85 return _cairo_output_stream_close (stream
);
88 const cairo_output_stream_t _cairo_output_stream_nil
= {
89 NULL
, /* write_func */
90 NULL
, /* close_func */
92 CAIRO_STATUS_NO_MEMORY
,
96 static const cairo_output_stream_t _cairo_output_stream_nil_write_error
= {
97 NULL
, /* write_func */
98 NULL
, /* close_func */
100 CAIRO_STATUS_WRITE_ERROR
,
104 typedef struct _cairo_output_stream_with_closure
{
105 cairo_output_stream_t base
;
106 cairo_write_func_t write_func
;
107 cairo_close_func_t close_func
;
109 } cairo_output_stream_with_closure_t
;
112 static cairo_status_t
113 closure_write (cairo_output_stream_t
*stream
,
114 const unsigned char *data
, unsigned int length
)
116 cairo_output_stream_with_closure_t
*stream_with_closure
=
117 (cairo_output_stream_with_closure_t
*) stream
;
119 if (stream_with_closure
->write_func
== NULL
)
120 return CAIRO_STATUS_SUCCESS
;
122 return stream_with_closure
->write_func (stream_with_closure
->closure
,
126 static cairo_status_t
127 closure_close (cairo_output_stream_t
*stream
)
129 cairo_output_stream_with_closure_t
*stream_with_closure
=
130 (cairo_output_stream_with_closure_t
*) stream
;
132 if (stream_with_closure
->close_func
!= NULL
)
133 return stream_with_closure
->close_func (stream_with_closure
->closure
);
135 return CAIRO_STATUS_SUCCESS
;
138 cairo_output_stream_t
*
139 _cairo_output_stream_create (cairo_write_func_t write_func
,
140 cairo_close_func_t close_func
,
143 cairo_output_stream_with_closure_t
*stream
;
145 stream
= malloc (sizeof (cairo_output_stream_with_closure_t
));
146 if (stream
== NULL
) {
147 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
148 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
151 _cairo_output_stream_init (&stream
->base
, closure_write
, closure_close
);
152 stream
->write_func
= write_func
;
153 stream
->close_func
= close_func
;
154 stream
->closure
= closure
;
156 return &stream
->base
;
159 cairo_output_stream_t
*
160 _cairo_output_stream_create_in_error (cairo_status_t status
)
162 cairo_output_stream_t
*stream
;
164 /* check for the common ones */
165 if (status
== CAIRO_STATUS_NO_MEMORY
)
166 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
167 if (status
== CAIRO_STATUS_WRITE_ERROR
)
168 return (cairo_output_stream_t
*) &_cairo_output_stream_nil_write_error
;
170 stream
= malloc (sizeof (cairo_output_stream_t
));
171 if (stream
== NULL
) {
172 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
173 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
176 _cairo_output_stream_init (stream
, NULL
, NULL
);
177 stream
->status
= status
;
183 _cairo_output_stream_close (cairo_output_stream_t
*stream
)
185 cairo_status_t status
;
188 return stream
->status
;
190 if (stream
== &_cairo_output_stream_nil
||
191 stream
== &_cairo_output_stream_nil_write_error
)
193 return stream
->status
;
196 if (stream
->close_func
) {
197 status
= stream
->close_func (stream
);
198 /* Don't overwrite a pre-existing status failure. */
199 if (stream
->status
== CAIRO_STATUS_SUCCESS
)
200 stream
->status
= status
;
203 stream
->closed
= TRUE
;
205 return stream
->status
;
209 _cairo_output_stream_destroy (cairo_output_stream_t
*stream
)
211 cairo_status_t status
;
213 assert (stream
!= NULL
);
215 if (stream
== &_cairo_output_stream_nil
||
216 stream
== &_cairo_output_stream_nil_write_error
)
218 return stream
->status
;
221 status
= _cairo_output_stream_fini (stream
);
228 _cairo_output_stream_write (cairo_output_stream_t
*stream
,
229 const void *data
, size_t length
)
237 stream
->status
= stream
->write_func (stream
, data
, length
);
238 stream
->position
+= length
;
242 _cairo_output_stream_write_hex_string (cairo_output_stream_t
*stream
,
243 const unsigned char *data
,
246 const char hex_chars
[] = "0123456789abcdef";
248 unsigned int i
, column
;
253 for (i
= 0, column
= 0; i
< length
; i
++, column
++) {
255 _cairo_output_stream_write (stream
, "\n", 1);
258 buffer
[0] = hex_chars
[(data
[i
] >> 4) & 0x0f];
259 buffer
[1] = hex_chars
[data
[i
] & 0x0f];
260 _cairo_output_stream_write (stream
, buffer
, 2);
264 /* Format a double in a locale independent way and trim trailing
265 * zeros. Based on code from Alex Larson <alexl@redhat.com>.
266 * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html
268 * The code in the patch is copyright Red Hat, Inc under the LGPL, but
269 * has been relicensed under the LGPL/MPL dual license for inclusion
270 * into cairo (see COPYING). -- Kristian Høgsberg <krh@redhat.com>
273 _cairo_dtostr (char *buffer
, size_t size
, double d
, cairo_bool_t limited_precision
)
275 struct lconv
*locale_data
;
276 const char *decimal_point
;
277 int decimal_point_len
;
280 int num_zeros
, decimal_digits
;
282 /* Omit the minus sign from negative zero. */
286 locale_data
= localeconv ();
287 decimal_point
= locale_data
->decimal_point
;
288 decimal_point_len
= strlen (decimal_point
);
290 assert (decimal_point_len
!= 0);
292 if (limited_precision
) {
293 snprintf (buffer
, size
, "%.*f", FIXED_POINT_DECIMAL_DIGITS
, d
);
295 /* Using "%f" to print numbers less than 0.1 will result in
296 * reduced precision due to the default 6 digits after the
299 * For numbers is < 0.1, we print with maximum precision and count
300 * the number of zeros between the decimal point and the first
301 * significant digit. We then print the number again with the
302 * number of decimal places that gives us the required number of
303 * significant digits. This ensures the number is correctly
306 if (fabs (d
) >= 0.1) {
307 snprintf (buffer
, size
, "%f", d
);
309 snprintf (buffer
, size
, "%.18f", d
);
312 if (*p
== '+' || *p
== '-')
318 if (strncmp (p
, decimal_point
, decimal_point_len
) == 0)
319 p
+= decimal_point_len
;
325 decimal_digits
= num_zeros
+ SIGNIFICANT_DIGITS_AFTER_DECIMAL
;
327 if (decimal_digits
< 18)
328 snprintf (buffer
, size
, "%.*f", decimal_digits
, d
);
333 if (*p
== '+' || *p
== '-')
339 if (strncmp (p
, decimal_point
, decimal_point_len
) == 0) {
341 decimal_len
= strlen (p
+ decimal_point_len
);
342 memmove (p
+ 1, p
+ decimal_point_len
, decimal_len
);
343 p
[1 + decimal_len
] = 0;
345 /* Remove trailing zeros and decimal point if possible. */
346 for (p
= p
+ decimal_len
; *p
== '0'; p
--)
357 LENGTH_MODIFIER_LONG
= 0x100
360 /* Here's a limited reimplementation of printf. The reason for doing
361 * this is primarily to special case handling of doubles. We want
362 * locale independent formatting of doubles and we want to trim
363 * trailing zeros. This is handled by dtostr() above, and the code
364 * below handles everything else by calling snprintf() to do the
365 * formatting. This functionality is only for internal use and we
366 * only implement the formats we actually use.
369 _cairo_output_stream_vprintf (cairo_output_stream_t
*stream
,
370 const char *fmt
, va_list ap
)
372 #define SINGLE_FMT_BUFFER_SIZE 32
373 char buffer
[512], single_fmt
[SINGLE_FMT_BUFFER_SIZE
];
374 int single_fmt_length
;
376 const char *f
, *start
;
377 int length_modifier
, width
;
378 cairo_bool_t var_width
;
386 if (p
== buffer
+ sizeof (buffer
)) {
387 _cairo_output_stream_write (stream
, buffer
, sizeof (buffer
));
413 length_modifier
= LENGTH_MODIFIER_LONG
;
417 /* The only format strings exist in the cairo implementation
418 * itself. So there's an internal consistency problem if any
419 * of them is larger than our format buffer size. */
420 single_fmt_length
= f
- start
+ 1;
421 assert (single_fmt_length
+ 1 <= SINGLE_FMT_BUFFER_SIZE
);
423 /* Reuse the format string for this conversion. */
424 memcpy (single_fmt
, start
, single_fmt_length
);
425 single_fmt
[single_fmt_length
] = '\0';
427 /* Flush contents of buffer before snprintf()'ing into it. */
428 _cairo_output_stream_write (stream
, buffer
, p
- buffer
);
430 /* We group signed and unsigned together in this switch, the
431 * only thing that matters here is the size of the arguments,
432 * since we're just passing the data through to sprintf(). */
433 switch (*f
| length_modifier
) {
444 width
= va_arg (ap
, int);
445 snprintf (buffer
, sizeof buffer
,
446 single_fmt
, width
, va_arg (ap
, int));
448 snprintf (buffer
, sizeof buffer
, single_fmt
, va_arg (ap
, int));
451 case 'd' | LENGTH_MODIFIER_LONG
:
452 case 'u' | LENGTH_MODIFIER_LONG
:
453 case 'o' | LENGTH_MODIFIER_LONG
:
454 case 'x' | LENGTH_MODIFIER_LONG
:
455 case 'X' | LENGTH_MODIFIER_LONG
:
457 width
= va_arg (ap
, int);
458 snprintf (buffer
, sizeof buffer
,
459 single_fmt
, width
, va_arg (ap
, long int));
461 snprintf (buffer
, sizeof buffer
,
462 single_fmt
, va_arg (ap
, long int));
466 snprintf (buffer
, sizeof buffer
,
467 single_fmt
, va_arg (ap
, const char *));
470 _cairo_dtostr (buffer
, sizeof buffer
, va_arg (ap
, double), FALSE
);
473 _cairo_dtostr (buffer
, sizeof buffer
, va_arg (ap
, double), TRUE
);
476 buffer
[0] = va_arg (ap
, int);
482 p
= buffer
+ strlen (buffer
);
486 _cairo_output_stream_write (stream
, buffer
, p
- buffer
);
490 _cairo_output_stream_printf (cairo_output_stream_t
*stream
,
491 const char *fmt
, ...)
497 _cairo_output_stream_vprintf (stream
, fmt
, ap
);
503 _cairo_output_stream_get_position (cairo_output_stream_t
*stream
)
505 return stream
->position
;
509 _cairo_output_stream_get_status (cairo_output_stream_t
*stream
)
511 return stream
->status
;
514 /* Maybe this should be a configure time option, so embedded targets
515 * don't have to pull in stdio. */
518 typedef struct _stdio_stream
{
519 cairo_output_stream_t base
;
523 static cairo_status_t
524 stdio_write (cairo_output_stream_t
*base
,
525 const unsigned char *data
, unsigned int length
)
527 stdio_stream_t
*stream
= (stdio_stream_t
*) base
;
529 if (fwrite (data
, 1, length
, stream
->file
) != length
)
530 return _cairo_error (CAIRO_STATUS_WRITE_ERROR
);
532 return CAIRO_STATUS_SUCCESS
;
535 static cairo_status_t
536 stdio_flush (cairo_output_stream_t
*base
)
538 stdio_stream_t
*stream
= (stdio_stream_t
*) base
;
540 fflush (stream
->file
);
542 if (ferror (stream
->file
))
543 return _cairo_error (CAIRO_STATUS_WRITE_ERROR
);
545 return CAIRO_STATUS_SUCCESS
;
548 static cairo_status_t
549 stdio_close (cairo_output_stream_t
*base
)
551 cairo_status_t status
;
552 stdio_stream_t
*stream
= (stdio_stream_t
*) base
;
554 status
= stdio_flush (base
);
556 fclose (stream
->file
);
561 cairo_output_stream_t
*
562 _cairo_output_stream_create_for_file (FILE *file
)
564 stdio_stream_t
*stream
;
567 _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR
);
568 return (cairo_output_stream_t
*) &_cairo_output_stream_nil_write_error
;
571 stream
= malloc (sizeof *stream
);
572 if (stream
== NULL
) {
573 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
574 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
577 _cairo_output_stream_init (&stream
->base
, stdio_write
, stdio_flush
);
580 return &stream
->base
;
583 cairo_output_stream_t
*
584 _cairo_output_stream_create_for_filename (const char *filename
)
586 stdio_stream_t
*stream
;
589 if (filename
== NULL
)
590 return _cairo_null_stream_create ();
592 file
= fopen (filename
, "wb");
596 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
597 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
599 _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR
);
600 return (cairo_output_stream_t
*) &_cairo_output_stream_nil_write_error
;
604 stream
= malloc (sizeof *stream
);
605 if (stream
== NULL
) {
607 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
608 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
611 _cairo_output_stream_init (&stream
->base
, stdio_write
, stdio_close
);
614 return &stream
->base
;
618 typedef struct _memory_stream
{
619 cairo_output_stream_t base
;
623 static cairo_status_t
624 memory_write (cairo_output_stream_t
*base
,
625 const unsigned char *data
, unsigned int length
)
627 memory_stream_t
*stream
= (memory_stream_t
*) base
;
629 return _cairo_array_append_multiple (&stream
->array
, data
, length
);
632 static cairo_status_t
633 memory_close (cairo_output_stream_t
*base
)
635 memory_stream_t
*stream
= (memory_stream_t
*) base
;
637 _cairo_array_fini (&stream
->array
);
639 return CAIRO_STATUS_SUCCESS
;
642 cairo_output_stream_t
*
643 _cairo_memory_stream_create (void)
645 memory_stream_t
*stream
;
647 stream
= malloc (sizeof *stream
);
648 if (stream
== NULL
) {
649 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
650 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
653 _cairo_output_stream_init (&stream
->base
, memory_write
, memory_close
);
654 _cairo_array_init (&stream
->array
, 1);
656 return &stream
->base
;
660 _cairo_memory_stream_copy (cairo_output_stream_t
*base
,
661 cairo_output_stream_t
*dest
)
663 memory_stream_t
*stream
= (memory_stream_t
*) base
;
669 dest
->status
= base
->status
;
673 _cairo_output_stream_write (dest
,
674 _cairo_array_index (&stream
->array
, 0),
675 _cairo_array_num_elements (&stream
->array
));
679 _cairo_memory_stream_length (cairo_output_stream_t
*base
)
681 memory_stream_t
*stream
= (memory_stream_t
*) base
;
683 return _cairo_array_num_elements (&stream
->array
);
686 static cairo_status_t
687 null_write (cairo_output_stream_t
*base
,
688 const unsigned char *data
, unsigned int length
)
690 return CAIRO_STATUS_SUCCESS
;
693 cairo_output_stream_t
*
694 _cairo_null_stream_create (void)
696 cairo_output_stream_t
*stream
;
698 stream
= malloc (sizeof *stream
);
699 if (stream
== NULL
) {
700 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
701 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
704 _cairo_output_stream_init (stream
, null_write
, NULL
);