Fixed texturing in Gallium.
[cairo/gpu.git] / src / cairo-output-stream.c
blob71154339ad4b499e4fce6bc8bab17a350cb707b6
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.
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"
40 #include "cairo-compiler-private.h"
42 #include <stdio.h>
43 #include <locale.h>
44 #include <ctype.h>
45 #include <errno.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
57 * precision.
59 * The conversion is:
61 * <programlisting>
62 * FIXED_POINT_DECIMAL_DIGITS = ceil( CAIRO_FIXED_FRAC_BITS * ln(2)/ln(10) )
63 * </programlisting>
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))
70 void
71 _cairo_output_stream_init (cairo_output_stream_t *stream,
72 cairo_output_stream_write_func_t write_func,
73 cairo_output_stream_flush_func_t flush_func,
74 cairo_output_stream_close_func_t close_func)
76 stream->write_func = write_func;
77 stream->flush_func = flush_func;
78 stream->close_func = close_func;
79 stream->position = 0;
80 stream->status = CAIRO_STATUS_SUCCESS;
81 stream->closed = FALSE;
84 cairo_status_t
85 _cairo_output_stream_fini (cairo_output_stream_t *stream)
87 return _cairo_output_stream_close (stream);
90 const cairo_output_stream_t _cairo_output_stream_nil = {
91 NULL, /* write_func */
92 NULL, /* flush_func */
93 NULL, /* close_func */
94 0, /* position */
95 CAIRO_STATUS_NO_MEMORY,
96 FALSE /* closed */
99 static const cairo_output_stream_t _cairo_output_stream_nil_write_error = {
100 NULL, /* write_func */
101 NULL, /* flush_func */
102 NULL, /* close_func */
103 0, /* position */
104 CAIRO_STATUS_WRITE_ERROR,
105 FALSE /* closed */
108 typedef struct _cairo_output_stream_with_closure {
109 cairo_output_stream_t base;
110 cairo_write_func_t write_func;
111 cairo_close_func_t close_func;
112 void *closure;
113 } cairo_output_stream_with_closure_t;
116 static cairo_status_t
117 closure_write (cairo_output_stream_t *stream,
118 const unsigned char *data, unsigned int length)
120 cairo_output_stream_with_closure_t *stream_with_closure =
121 (cairo_output_stream_with_closure_t *) stream;
123 if (stream_with_closure->write_func == NULL)
124 return CAIRO_STATUS_SUCCESS;
126 return stream_with_closure->write_func (stream_with_closure->closure,
127 data, length);
130 static cairo_status_t
131 closure_close (cairo_output_stream_t *stream)
133 cairo_output_stream_with_closure_t *stream_with_closure =
134 (cairo_output_stream_with_closure_t *) stream;
136 if (stream_with_closure->close_func != NULL)
137 return stream_with_closure->close_func (stream_with_closure->closure);
138 else
139 return CAIRO_STATUS_SUCCESS;
142 cairo_output_stream_t *
143 _cairo_output_stream_create (cairo_write_func_t write_func,
144 cairo_close_func_t close_func,
145 void *closure)
147 cairo_output_stream_with_closure_t *stream;
149 stream = malloc (sizeof (cairo_output_stream_with_closure_t));
150 if (unlikely (stream == NULL)) {
151 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
152 return (cairo_output_stream_t *) &_cairo_output_stream_nil;
155 _cairo_output_stream_init (&stream->base,
156 closure_write, NULL, closure_close);
157 stream->write_func = write_func;
158 stream->close_func = close_func;
159 stream->closure = closure;
161 return &stream->base;
164 cairo_output_stream_t *
165 _cairo_output_stream_create_in_error (cairo_status_t status)
167 cairo_output_stream_t *stream;
169 /* check for the common ones */
170 if (status == CAIRO_STATUS_NO_MEMORY)
171 return (cairo_output_stream_t *) &_cairo_output_stream_nil;
172 if (status == CAIRO_STATUS_WRITE_ERROR)
173 return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
175 stream = malloc (sizeof (cairo_output_stream_t));
176 if (unlikely (stream == NULL)) {
177 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
178 return (cairo_output_stream_t *) &_cairo_output_stream_nil;
181 _cairo_output_stream_init (stream, NULL, NULL, NULL);
182 stream->status = status;
184 return stream;
187 cairo_status_t
188 _cairo_output_stream_flush (cairo_output_stream_t *stream)
190 cairo_status_t status;
192 if (stream->closed)
193 return stream->status;
195 if (stream == &_cairo_output_stream_nil ||
196 stream == &_cairo_output_stream_nil_write_error)
198 return stream->status;
201 if (stream->flush_func) {
202 status = stream->flush_func (stream);
203 /* Don't overwrite a pre-existing status failure. */
204 if (stream->status == CAIRO_STATUS_SUCCESS)
205 stream->status = status;
208 return stream->status;
211 cairo_status_t
212 _cairo_output_stream_close (cairo_output_stream_t *stream)
214 cairo_status_t status;
216 if (stream->closed)
217 return stream->status;
219 if (stream == &_cairo_output_stream_nil ||
220 stream == &_cairo_output_stream_nil_write_error)
222 return stream->status;
225 if (stream->close_func) {
226 status = stream->close_func (stream);
227 /* Don't overwrite a pre-existing status failure. */
228 if (stream->status == CAIRO_STATUS_SUCCESS)
229 stream->status = status;
232 stream->closed = TRUE;
234 return stream->status;
237 cairo_status_t
238 _cairo_output_stream_destroy (cairo_output_stream_t *stream)
240 cairo_status_t status;
242 assert (stream != NULL);
244 if (stream == &_cairo_output_stream_nil ||
245 stream == &_cairo_output_stream_nil_write_error)
247 return stream->status;
250 status = _cairo_output_stream_fini (stream);
251 free (stream);
253 return status;
256 void
257 _cairo_output_stream_write (cairo_output_stream_t *stream,
258 const void *data, size_t length)
260 if (length == 0)
261 return;
263 if (stream->status)
264 return;
266 stream->status = stream->write_func (stream, data, length);
267 stream->position += length;
270 void
271 _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
272 const unsigned char *data,
273 size_t length)
275 const char hex_chars[] = "0123456789abcdef";
276 char buffer[2];
277 unsigned int i, column;
279 if (stream->status)
280 return;
282 for (i = 0, column = 0; i < length; i++, column++) {
283 if (column == 38) {
284 _cairo_output_stream_write (stream, "\n", 1);
285 column = 0;
287 buffer[0] = hex_chars[(data[i] >> 4) & 0x0f];
288 buffer[1] = hex_chars[data[i] & 0x0f];
289 _cairo_output_stream_write (stream, buffer, 2);
293 /* Format a double in a locale independent way and trim trailing
294 * zeros. Based on code from Alex Larson <alexl@redhat.com>.
295 * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html
297 * The code in the patch is copyright Red Hat, Inc under the LGPL, but
298 * has been relicensed under the LGPL/MPL dual license for inclusion
299 * into cairo (see COPYING). -- Kristian Høgsberg <krh@redhat.com>
301 static void
302 _cairo_dtostr (char *buffer, size_t size, double d, cairo_bool_t limited_precision)
304 struct lconv *locale_data;
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 locale_data = localeconv ();
316 decimal_point = locale_data->decimal_point;
317 decimal_point_len = strlen (decimal_point);
319 assert (decimal_point_len != 0);
321 if (limited_precision) {
322 snprintf (buffer, size, "%.*f", FIXED_POINT_DECIMAL_DIGITS, d);
323 } else {
324 /* Using "%f" to print numbers less than 0.1 will result in
325 * reduced precision due to the default 6 digits after the
326 * decimal point.
328 * For numbers is < 0.1, we print with maximum precision and count
329 * the number of zeros between the decimal point and the first
330 * significant digit. We then print the number again with the
331 * number of decimal places that gives us the required number of
332 * significant digits. This ensures the number is correctly
333 * rounded.
335 if (fabs (d) >= 0.1) {
336 snprintf (buffer, size, "%f", d);
337 } else {
338 snprintf (buffer, size, "%.18f", d);
339 p = buffer;
341 if (*p == '+' || *p == '-')
342 p++;
344 while (isdigit (*p))
345 p++;
347 if (strncmp (p, decimal_point, decimal_point_len) == 0)
348 p += decimal_point_len;
350 num_zeros = 0;
351 while (*p++ == '0')
352 num_zeros++;
354 decimal_digits = num_zeros + SIGNIFICANT_DIGITS_AFTER_DECIMAL;
356 if (decimal_digits < 18)
357 snprintf (buffer, size, "%.*f", decimal_digits, d);
360 p = buffer;
362 if (*p == '+' || *p == '-')
363 p++;
365 while (isdigit (*p))
366 p++;
368 if (strncmp (p, decimal_point, decimal_point_len) == 0) {
369 *p = '.';
370 decimal_len = strlen (p + decimal_point_len);
371 memmove (p + 1, p + decimal_point_len, decimal_len);
372 p[1 + decimal_len] = 0;
374 /* Remove trailing zeros and decimal point if possible. */
375 for (p = p + decimal_len; *p == '0'; p--)
376 *p = 0;
378 if (*p == '.') {
379 *p = 0;
380 p--;
385 enum {
386 LENGTH_MODIFIER_LONG = 0x100
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.
397 void
398 _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
399 const char *fmt, va_list ap)
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;
409 if (stream->status)
410 return;
412 f = fmt;
413 p = buffer;
414 while (*f != '\0') {
415 if (p == buffer + sizeof (buffer)) {
416 _cairo_output_stream_write (stream, buffer, sizeof (buffer));
417 p = buffer;
420 if (*f != '%') {
421 *p++ = *f++;
422 continue;
425 start = f;
426 f++;
428 if (*f == '0')
429 f++;
431 var_width = FALSE;
432 if (*f == '*') {
433 var_width = TRUE;
434 f++;
437 while (isdigit (*f))
438 f++;
440 length_modifier = 0;
441 if (*f == 'l') {
442 length_modifier = LENGTH_MODIFIER_LONG;
443 f++;
446 /* The only format strings exist in the cairo implementation
447 * itself. So there's an internal consistency problem if any
448 * of them is larger than our format buffer size. */
449 single_fmt_length = f - start + 1;
450 assert (single_fmt_length + 1 <= SINGLE_FMT_BUFFER_SIZE);
452 /* Reuse the format string for this conversion. */
453 memcpy (single_fmt, start, single_fmt_length);
454 single_fmt[single_fmt_length] = '\0';
456 /* Flush contents of buffer before snprintf()'ing into it. */
457 _cairo_output_stream_write (stream, buffer, p - buffer);
459 /* We group signed and unsigned together in this switch, the
460 * only thing that matters here is the size of the arguments,
461 * since we're just passing the data through to sprintf(). */
462 switch (*f | length_modifier) {
463 case '%':
464 buffer[0] = *f;
465 buffer[1] = 0;
466 break;
467 case 'd':
468 case 'u':
469 case 'o':
470 case 'x':
471 case 'X':
472 if (var_width) {
473 width = va_arg (ap, int);
474 snprintf (buffer, sizeof buffer,
475 single_fmt, width, va_arg (ap, int));
476 } else {
477 snprintf (buffer, sizeof buffer, single_fmt, va_arg (ap, int));
479 break;
480 case 'd' | LENGTH_MODIFIER_LONG:
481 case 'u' | LENGTH_MODIFIER_LONG:
482 case 'o' | LENGTH_MODIFIER_LONG:
483 case 'x' | LENGTH_MODIFIER_LONG:
484 case 'X' | LENGTH_MODIFIER_LONG:
485 if (var_width) {
486 width = va_arg (ap, int);
487 snprintf (buffer, sizeof buffer,
488 single_fmt, width, va_arg (ap, long int));
489 } else {
490 snprintf (buffer, sizeof buffer,
491 single_fmt, va_arg (ap, long int));
493 break;
494 case 's':
495 snprintf (buffer, sizeof buffer,
496 single_fmt, va_arg (ap, const char *));
497 break;
498 case 'f':
499 _cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double), FALSE);
500 break;
501 case 'g':
502 _cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double), TRUE);
503 break;
504 case 'c':
505 buffer[0] = va_arg (ap, int);
506 buffer[1] = 0;
507 break;
508 default:
509 ASSERT_NOT_REACHED;
511 p = buffer + strlen (buffer);
512 f++;
515 _cairo_output_stream_write (stream, buffer, p - buffer);
518 void
519 _cairo_output_stream_printf (cairo_output_stream_t *stream,
520 const char *fmt, ...)
522 va_list ap;
524 va_start (ap, fmt);
526 _cairo_output_stream_vprintf (stream, fmt, ap);
528 va_end (ap);
531 long
532 _cairo_output_stream_get_position (cairo_output_stream_t *stream)
534 return stream->position;
537 cairo_status_t
538 _cairo_output_stream_get_status (cairo_output_stream_t *stream)
540 return stream->status;
543 /* Maybe this should be a configure time option, so embedded targets
544 * don't have to pull in stdio. */
547 typedef struct _stdio_stream {
548 cairo_output_stream_t base;
549 FILE *file;
550 } stdio_stream_t;
552 static cairo_status_t
553 stdio_write (cairo_output_stream_t *base,
554 const unsigned char *data, unsigned int length)
556 stdio_stream_t *stream = (stdio_stream_t *) base;
558 if (fwrite (data, 1, length, stream->file) != length)
559 return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
561 return CAIRO_STATUS_SUCCESS;
564 static cairo_status_t
565 stdio_flush (cairo_output_stream_t *base)
567 stdio_stream_t *stream = (stdio_stream_t *) base;
569 fflush (stream->file);
571 if (ferror (stream->file))
572 return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
573 else
574 return CAIRO_STATUS_SUCCESS;
577 static cairo_status_t
578 stdio_close (cairo_output_stream_t *base)
580 cairo_status_t status;
581 stdio_stream_t *stream = (stdio_stream_t *) base;
583 status = stdio_flush (base);
585 fclose (stream->file);
587 return status;
590 cairo_output_stream_t *
591 _cairo_output_stream_create_for_file (FILE *file)
593 stdio_stream_t *stream;
595 if (file == NULL) {
596 _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
597 return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
600 stream = malloc (sizeof *stream);
601 if (unlikely (stream == NULL)) {
602 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
603 return (cairo_output_stream_t *) &_cairo_output_stream_nil;
606 _cairo_output_stream_init (&stream->base,
607 stdio_write, stdio_flush, stdio_flush);
608 stream->file = file;
610 return &stream->base;
613 cairo_output_stream_t *
614 _cairo_output_stream_create_for_filename (const char *filename)
616 stdio_stream_t *stream;
617 FILE *file;
619 if (filename == NULL)
620 return _cairo_null_stream_create ();
622 file = fopen (filename, "wb");
623 if (file == NULL) {
624 switch (errno) {
625 case ENOMEM:
626 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
627 return (cairo_output_stream_t *) &_cairo_output_stream_nil;
628 default:
629 _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
630 return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
634 stream = malloc (sizeof *stream);
635 if (unlikely (stream == NULL)) {
636 fclose (file);
637 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
638 return (cairo_output_stream_t *) &_cairo_output_stream_nil;
641 _cairo_output_stream_init (&stream->base,
642 stdio_write, stdio_flush, stdio_close);
643 stream->file = file;
645 return &stream->base;
649 typedef struct _memory_stream {
650 cairo_output_stream_t base;
651 cairo_array_t array;
652 } memory_stream_t;
654 static cairo_status_t
655 memory_write (cairo_output_stream_t *base,
656 const unsigned char *data, unsigned int length)
658 memory_stream_t *stream = (memory_stream_t *) base;
660 return _cairo_array_append_multiple (&stream->array, data, length);
663 static cairo_status_t
664 memory_close (cairo_output_stream_t *base)
666 memory_stream_t *stream = (memory_stream_t *) base;
668 _cairo_array_fini (&stream->array);
670 return CAIRO_STATUS_SUCCESS;
673 cairo_output_stream_t *
674 _cairo_memory_stream_create (void)
676 memory_stream_t *stream;
678 stream = malloc (sizeof *stream);
679 if (unlikely (stream == NULL)) {
680 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
681 return (cairo_output_stream_t *) &_cairo_output_stream_nil;
684 _cairo_output_stream_init (&stream->base, memory_write, NULL, memory_close);
685 _cairo_array_init (&stream->array, 1);
687 return &stream->base;
690 cairo_status_t
691 _cairo_memory_stream_destroy (cairo_output_stream_t *abstract_stream,
692 unsigned char **data_out,
693 unsigned int *length_out)
695 memory_stream_t *stream;
696 cairo_status_t status;
698 status = abstract_stream->status;
699 if (unlikely (status))
700 return _cairo_output_stream_destroy (abstract_stream);
702 stream = (memory_stream_t *) abstract_stream;
704 *length_out = _cairo_array_num_elements (&stream->array);
705 *data_out = malloc (*length_out);
706 if (unlikely (*data_out == NULL)) {
707 status = _cairo_output_stream_destroy (abstract_stream);
708 assert (status == CAIRO_STATUS_SUCCESS);
709 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
711 memcpy (*data_out, _cairo_array_index (&stream->array, 0), *length_out);
713 return _cairo_output_stream_destroy (abstract_stream);
716 void
717 _cairo_memory_stream_copy (cairo_output_stream_t *base,
718 cairo_output_stream_t *dest)
720 memory_stream_t *stream = (memory_stream_t *) base;
722 if (dest->status)
723 return;
725 if (base->status) {
726 dest->status = base->status;
727 return;
730 _cairo_output_stream_write (dest,
731 _cairo_array_index (&stream->array, 0),
732 _cairo_array_num_elements (&stream->array));
736 _cairo_memory_stream_length (cairo_output_stream_t *base)
738 memory_stream_t *stream = (memory_stream_t *) base;
740 return _cairo_array_num_elements (&stream->array);
743 static cairo_status_t
744 null_write (cairo_output_stream_t *base,
745 const unsigned char *data, unsigned int length)
747 return CAIRO_STATUS_SUCCESS;
750 cairo_output_stream_t *
751 _cairo_null_stream_create (void)
753 cairo_output_stream_t *stream;
755 stream = malloc (sizeof *stream);
756 if (unlikely (stream == NULL)) {
757 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
758 return (cairo_output_stream_t *) &_cairo_output_stream_nil;
761 _cairo_output_stream_init (stream, null_write, NULL, NULL);
763 return stream;