beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-output-stream.c
blob369a59bfba889037193004dad76f6c8e0be47ffb
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., 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
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.
32 * Author(s):
33 * Kristian Høgsberg <krh@redhat.com>
36 #define _BSD_SOURCE /* for snprintf() */
37 #include "cairoint.h"
39 #include "cairo-output-stream-private.h"
41 #include "cairo-array-private.h"
42 #include "cairo-error-private.h"
43 #include "cairo-compiler-private.h"
45 #include <stdio.h>
46 #include <errno.h>
48 /* Numbers printed with %f are printed with this number of significant
49 * digits after the decimal.
51 #define SIGNIFICANT_DIGITS_AFTER_DECIMAL 6
53 /* Numbers printed with %g are assumed to only have %CAIRO_FIXED_FRAC_BITS
54 * bits of precision available after the decimal point.
56 * FIXED_POINT_DECIMAL_DIGITS specifies the minimum number of decimal
57 * digits after the decimal point required to preserve the available
58 * precision.
60 * The conversion is:
62 * <programlisting>
63 * FIXED_POINT_DECIMAL_DIGITS = ceil( CAIRO_FIXED_FRAC_BITS * ln(2)/ln(10) )
64 * </programlisting>
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.
69 #define FIXED_POINT_DECIMAL_DIGITS ((int)(CAIRO_FIXED_FRAC_BITS*0.301029996 + 1))
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)
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;
85 cairo_status_t
86 _cairo_output_stream_fini (cairo_output_stream_t *stream)
88 return _cairo_output_stream_close (stream);
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 */
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 */
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;
117 static cairo_status_t
118 closure_write (cairo_output_stream_t *stream,
119 const unsigned char *data, unsigned int length)
121 cairo_output_stream_with_closure_t *stream_with_closure =
122 (cairo_output_stream_with_closure_t *) stream;
124 if (stream_with_closure->write_func == NULL)
125 return CAIRO_STATUS_SUCCESS;
127 return stream_with_closure->write_func (stream_with_closure->closure,
128 data, length);
131 static cairo_status_t
132 closure_close (cairo_output_stream_t *stream)
134 cairo_output_stream_with_closure_t *stream_with_closure =
135 (cairo_output_stream_with_closure_t *) stream;
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;
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)
148 cairo_output_stream_with_closure_t *stream;
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;
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;
162 return &stream->base;
165 cairo_output_stream_t *
166 _cairo_output_stream_create_in_error (cairo_status_t status)
168 cairo_output_stream_t *stream;
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;
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;
182 _cairo_output_stream_init (stream, NULL, NULL, NULL);
183 stream->status = status;
185 return stream;
188 cairo_status_t
189 _cairo_output_stream_flush (cairo_output_stream_t *stream)
191 cairo_status_t status;
193 if (stream->closed)
194 return stream->status;
196 if (stream == &_cairo_output_stream_nil ||
197 stream == &_cairo_output_stream_nil_write_error)
199 return stream->status;
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;
209 return stream->status;
212 cairo_status_t
213 _cairo_output_stream_close (cairo_output_stream_t *stream)
215 cairo_status_t status;
217 if (stream->closed)
218 return stream->status;
220 if (stream == &_cairo_output_stream_nil ||
221 stream == &_cairo_output_stream_nil_write_error)
223 return stream->status;
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;
233 stream->closed = TRUE;
235 return stream->status;
238 cairo_status_t
239 _cairo_output_stream_destroy (cairo_output_stream_t *stream)
241 cairo_status_t status;
243 assert (stream != NULL);
245 if (stream == &_cairo_output_stream_nil ||
246 stream == &_cairo_output_stream_nil_write_error)
248 return stream->status;
251 status = _cairo_output_stream_fini (stream);
252 free (stream);
254 return status;
257 void
258 _cairo_output_stream_write (cairo_output_stream_t *stream,
259 const void *data, size_t length)
261 if (length == 0)
262 return;
264 if (stream->status)
265 return;
267 stream->status = stream->write_func (stream, data, length);
268 stream->position += length;
271 void
272 _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
273 const unsigned char *data,
274 size_t length)
276 const char hex_chars[] = "0123456789abcdef";
277 char buffer[2];
278 unsigned int i, column;
280 if (stream->status)
281 return;
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;
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);
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
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>
302 static void
303 _cairo_dtostr (char *buffer, size_t size, double d, cairo_bool_t limited_precision)
305 const char *decimal_point;
306 int decimal_point_len;
307 char *p;
308 int decimal_len;
309 int num_zeros, decimal_digits;
311 /* Omit the minus sign from negative zero. */
312 if (d == 0.0)
313 d = 0.0;
315 decimal_point = cairo_get_locale_decimal_point ();
316 decimal_point_len = strlen (decimal_point);
318 assert (decimal_point_len != 0);
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.
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.
334 if (fabs (d) >= 0.1) {
335 snprintf (buffer, size, "%f", d);
336 } else {
337 snprintf (buffer, size, "%.18f", d);
338 p = buffer;
340 if (*p == '+' || *p == '-')
341 p++;
343 while (_cairo_isdigit (*p))
344 p++;
346 if (strncmp (p, decimal_point, decimal_point_len) == 0)
347 p += decimal_point_len;
349 num_zeros = 0;
350 while (*p++ == '0')
351 num_zeros++;
353 decimal_digits = num_zeros + SIGNIFICANT_DIGITS_AFTER_DECIMAL;
355 if (decimal_digits < 18)
356 snprintf (buffer, size, "%.*f", decimal_digits, d);
359 p = buffer;
361 if (*p == '+' || *p == '-')
362 p++;
364 while (_cairo_isdigit (*p))
365 p++;
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;
373 /* Remove trailing zeros and decimal point if possible. */
374 for (p = p + decimal_len; *p == '0'; p--)
375 *p = 0;
377 if (*p == '.') {
378 *p = 0;
379 p--;
384 enum {
385 LENGTH_MODIFIER_LONG = 0x100
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.
396 void
397 _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
398 const char *fmt, va_list ap)
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;
408 if (stream->status)
409 return;
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;
419 if (*f != '%') {
420 *p++ = *f++;
421 continue;
424 start = f;
425 f++;
427 if (*f == '0')
428 f++;
430 var_width = FALSE;
431 if (*f == '*') {
432 var_width = TRUE;
433 f++;
436 while (_cairo_isdigit (*f))
437 f++;
439 length_modifier = 0;
440 if (*f == 'l') {
441 length_modifier = LENGTH_MODIFIER_LONG;
442 f++;
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);
451 /* Reuse the format string for this conversion. */
452 memcpy (single_fmt, start, single_fmt_length);
453 single_fmt[single_fmt_length] = '\0';
455 /* Flush contents of buffer before snprintf()'ing into it. */
456 _cairo_output_stream_write (stream, buffer, p - buffer);
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));
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));
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;
510 p = buffer + strlen (buffer);
511 f++;
514 _cairo_output_stream_write (stream, buffer, p - buffer);
517 void
518 _cairo_output_stream_printf (cairo_output_stream_t *stream,
519 const char *fmt, ...)
521 va_list ap;
523 va_start (ap, fmt);
525 _cairo_output_stream_vprintf (stream, fmt, ap);
527 va_end (ap);
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
534 void
535 _cairo_output_stream_print_matrix (cairo_output_stream_t *stream,
536 const cairo_matrix_t *matrix)
538 cairo_matrix_t m;
539 double s, e;
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);
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;
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);
569 long
570 _cairo_output_stream_get_position (cairo_output_stream_t *stream)
572 return stream->position;
575 cairo_status_t
576 _cairo_output_stream_get_status (cairo_output_stream_t *stream)
578 return stream->status;
581 /* Maybe this should be a configure time option, so embedded targets
582 * don't have to pull in stdio. */
585 typedef struct _stdio_stream {
586 cairo_output_stream_t base;
587 FILE *file;
588 } stdio_stream_t;
590 static cairo_status_t
591 stdio_write (cairo_output_stream_t *base,
592 const unsigned char *data, unsigned int length)
594 stdio_stream_t *stream = (stdio_stream_t *) base;
596 if (fwrite (data, 1, length, stream->file) != length)
597 return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
599 return CAIRO_STATUS_SUCCESS;
602 static cairo_status_t
603 stdio_flush (cairo_output_stream_t *base)
605 stdio_stream_t *stream = (stdio_stream_t *) base;
607 fflush (stream->file);
609 if (ferror (stream->file))
610 return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
611 else
612 return CAIRO_STATUS_SUCCESS;
615 static cairo_status_t
616 stdio_close (cairo_output_stream_t *base)
618 cairo_status_t status;
619 stdio_stream_t *stream = (stdio_stream_t *) base;
621 status = stdio_flush (base);
623 fclose (stream->file);
625 return status;
628 cairo_output_stream_t *
629 _cairo_output_stream_create_for_file (FILE *file)
631 stdio_stream_t *stream;
633 if (file == NULL) {
634 _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
635 return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
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;
644 _cairo_output_stream_init (&stream->base,
645 stdio_write, stdio_flush, stdio_flush);
646 stream->file = file;
648 return &stream->base;
651 cairo_output_stream_t *
652 _cairo_output_stream_create_for_filename (const char *filename)
654 stdio_stream_t *stream;
655 FILE *file;
657 if (filename == NULL)
658 return _cairo_null_stream_create ();
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;
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;
679 _cairo_output_stream_init (&stream->base,
680 stdio_write, stdio_flush, stdio_close);
681 stream->file = file;
683 return &stream->base;
687 typedef struct _memory_stream {
688 cairo_output_stream_t base;
689 cairo_array_t array;
690 } memory_stream_t;
692 static cairo_status_t
693 memory_write (cairo_output_stream_t *base,
694 const unsigned char *data, unsigned int length)
696 memory_stream_t *stream = (memory_stream_t *) base;
698 return _cairo_array_append_multiple (&stream->array, data, length);
701 static cairo_status_t
702 memory_close (cairo_output_stream_t *base)
704 memory_stream_t *stream = (memory_stream_t *) base;
706 _cairo_array_fini (&stream->array);
708 return CAIRO_STATUS_SUCCESS;
711 cairo_output_stream_t *
712 _cairo_memory_stream_create (void)
714 memory_stream_t *stream;
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;
722 _cairo_output_stream_init (&stream->base, memory_write, NULL, memory_close);
723 _cairo_array_init (&stream->array, 1);
725 return &stream->base;
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)
733 memory_stream_t *stream;
734 cairo_status_t status;
736 status = abstract_stream->status;
737 if (unlikely (status))
738 return _cairo_output_stream_destroy (abstract_stream);
740 stream = (memory_stream_t *) abstract_stream;
742 *length_out = _cairo_array_num_elements (&stream->array);
743 *data_out = malloc (*length_out);
744 if (unlikely (*data_out == NULL)) {
745 status = _cairo_output_stream_destroy (abstract_stream);
746 assert (status == CAIRO_STATUS_SUCCESS);
747 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
749 memcpy (*data_out, _cairo_array_index (&stream->array, 0), *length_out);
751 return _cairo_output_stream_destroy (abstract_stream);
754 void
755 _cairo_memory_stream_copy (cairo_output_stream_t *base,
756 cairo_output_stream_t *dest)
758 memory_stream_t *stream = (memory_stream_t *) base;
760 if (dest->status)
761 return;
763 if (base->status) {
764 dest->status = base->status;
765 return;
768 _cairo_output_stream_write (dest,
769 _cairo_array_index (&stream->array, 0),
770 _cairo_array_num_elements (&stream->array));
774 _cairo_memory_stream_length (cairo_output_stream_t *base)
776 memory_stream_t *stream = (memory_stream_t *) base;
778 return _cairo_array_num_elements (&stream->array);
781 static cairo_status_t
782 null_write (cairo_output_stream_t *base,
783 const unsigned char *data, unsigned int length)
785 return CAIRO_STATUS_SUCCESS;
788 cairo_output_stream_t *
789 _cairo_null_stream_create (void)
791 cairo_output_stream_t *stream;
793 stream = malloc (sizeof *stream);
794 if (unlikely (stream == NULL)) {
795 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
796 return (cairo_output_stream_t *) &_cairo_output_stream_nil;
799 _cairo_output_stream_init (stream, null_write, NULL, NULL);
801 return stream;