[cairo-commit] cairo/src cairo-output-stream.c, 1.2,
1.3 cairo-pdf-surface.c, 1.33, 1.34 cairoint.h, 1.140, 1.141
Kristian Hogsberg
commit at pdx.freedesktop.org
Fri May 13 14:04:25 PDT 2005
- Previous message: [cairo-commit] cairo ChangeLog,1.581,1.582
- Next message: [cairo-commit] cairo-demo/X11 .cvsignore, 1.1, 1.2 ChangeLog, 1.13,
1.14 Makefile, 1.5, 1.6 cairo-demo-xcb.c, NONE,
1.1 cairo-demo.c, 1.12, 1.13 cairo-knockout.c, 1.14,
1.15 cairo-spline.c, 1.11, 1.12
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Committed by: krh
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv31059/src
Modified Files:
cairo-output-stream.c cairo-pdf-surface.c cairoint.h
Log Message:
2005-05-13 Kristian Høgsberg <krh at redhat.com>
* src/cairo-pdf-surface.c (_cairo_pdf_document_open_stream): Make
this a varg function and use the new
_cairo_output_stream_vprintf() function to format extra dict
contents.
* src/cairo-output-stream.c (_cairo_output_stream_vprintf):
Reimplement the printf logic so we can special case formatting of
doubles to be locale independent and trim trailing zeros.
Index: cairo-output-stream.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-output-stream.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- cairo-output-stream.c 6 Apr 2005 20:01:13 -0000 1.2
+++ cairo-output-stream.c 13 May 2005 21:04:22 -0000 1.3
@@ -34,8 +34,9 @@
* Kristian Høgsberg <krh at redhat.com>
*/
-#include <stdarg.h>
#include <stdio.h>
+#include <locale.h>
+#include <ctype.h>
#include "cairoint.h"
struct _cairo_output_stream {
@@ -77,33 +78,162 @@
_cairo_output_stream_write (cairo_output_stream_t *stream,
const void *data, size_t length)
{
+ if (length == 0)
+ return CAIRO_STATUS_SUCCESS;
+
stream->status = stream->write_data (stream->closure, data, length);
stream->position += length;
return stream->status;
}
+/* Format a double in a locale independent way and trim trailing
+ * zeros. Based on code from Alex Larson <alexl at redhat.com>.
+ * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html
+ */
+
+static int
+dtostr (char *buffer, size_t size, double d)
+{
+ struct lconv *locale_data;
+ const char *decimal_point;
+ int decimal_point_len;
+ char *p;
+ int decimal_len;
+
+ snprintf (buffer, size, "%f", d);
+
+ locale_data = localeconv ();
+ decimal_point = locale_data->decimal_point;
+ decimal_point_len = strlen (decimal_point);
+
+ assert (decimal_point_len != 0);
+ p = buffer;
+
+ if (*p == '+' || *p == '-')
+ p++;
+
+ while (isdigit (*p))
+ p++;
+
+ if (strncmp (p, decimal_point, decimal_point_len) == 0) {
+ *p = '.';
+ decimal_len = strlen (p + decimal_point_len);
+ memmove (p + 1, p + decimal_point_len, decimal_len);
+ p[1 + decimal_len] = 0;
+
+ /* Remove trailing zeros and decimal point if possible. */
+ for (p = p + decimal_len; *p == '0'; p--)
+ *p = 0;
+
+ if (*p == '.') {
+ *p = 0;
+ p--;
+ }
+ }
+
+ return p + 1 - buffer;
+}
+
+
+enum {
+ LENGTH_MODIFIER_LONG = 0x100
+};
+
+/* Here's a limited reimplementation of printf. The reason for doing
+ * this is primarily to special case handling of doubles. We want
+ * locale independent formatting of doubles and we want to trim
+ * trailing zeros. This is handled by dtostr() above, and the code
+ * below handles everything else by calling snprintf() to do the
+ * formatting. This functionality is only for internal use and we
+ * only implement the formats we actually use.
+ */
+
+cairo_status_t
+_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
+ const char *fmt, va_list ap)
+{
+ char buffer[512];
+ char *p;
+ const char *f;
+ int length_modifier;
+
+ f = fmt;
+ p = buffer;
+ while (*f != '\0') {
+ if (p == buffer + sizeof (buffer)) {
+ _cairo_output_stream_write (stream, buffer, sizeof (buffer));
+ p = buffer;
+ }
+
+ if (*f != '%') {
+ *p++ = *f++;
+ continue;
+ }
+
+ f++;
+
+ _cairo_output_stream_write (stream, buffer, p - buffer);
+ p = buffer;
+
+ length_modifier = 0;
+ if (*f == 'l') {
+ length_modifier = LENGTH_MODIFIER_LONG;
+ f++;
+ }
+
+ switch (*f | length_modifier) {
+ case '%':
+ p[0] = *f;
+ p[1] = 0;
+ break;
+ case 'd':
+ snprintf (buffer, sizeof buffer, "%d", va_arg (ap, int));
+ break;
+ case 'd' | LENGTH_MODIFIER_LONG:
+ snprintf (buffer, sizeof buffer, "%ld", va_arg (ap, long int));
+ break;
+ case 'u':
+ snprintf (buffer, sizeof buffer, "%u", va_arg (ap, unsigned int));
+ break;
+ case 'u' | LENGTH_MODIFIER_LONG:
+ snprintf (buffer, sizeof buffer, "%lu", va_arg (ap, long unsigned int));
+ break;
+ case 'o':
+ snprintf (buffer, sizeof buffer, "%o", va_arg (ap, int));
+ break;
+ case 's':
+ snprintf (buffer, sizeof buffer, "%s", va_arg (ap, const char *));
+ break;
+ case 'f':
+ dtostr (buffer, sizeof buffer, va_arg (ap, double));
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ }
+ p = buffer + strlen (buffer);
+ f++;
+ }
+
+ _cairo_output_stream_write (stream, buffer, p - buffer);
+
+ return stream->status;
+}
+
cairo_status_t
_cairo_output_stream_printf (cairo_output_stream_t *stream,
const char *fmt, ...)
{
- unsigned char buffer[512];
- int length;
va_list ap;
+ cairo_status_t status;
va_start (ap, fmt);
- length = vsnprintf ((char *)buffer, sizeof buffer, fmt, ap);
- va_end (ap);
- /* FIXME: This function is only for internal use and callers are
- * required to ensure the length of the output fits in this
- * buffer. If this is not good enough, we have to do the va_copy
- * thing, which requires some autoconf magic to do portably. */
- assert (length < sizeof buffer);
- stream->status = stream->write_data (stream->closure, buffer, length);
- stream->position += length;
+ status = _cairo_output_stream_vprintf (stream, fmt, ap);
- return stream->status;
+ va_end (ap);
+
+ return status;
}
long
Index: cairo-pdf-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-pdf-surface.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- cairo-pdf-surface.c 13 May 2005 16:26:20 -0000 1.33
+++ cairo-pdf-surface.c 13 May 2005 21:04:22 -0000 1.34
@@ -218,7 +218,8 @@
static cairo_pdf_stream_t *
_cairo_pdf_document_open_stream (cairo_pdf_document_t *document,
- const char *extra_entries);
+ const char *fmt,
+ ...);
static cairo_surface_t *
_cairo_pdf_surface_create_for_document (cairo_pdf_document_t *document,
double width,
@@ -1023,10 +1024,12 @@
static cairo_pdf_stream_t *
_cairo_pdf_document_open_stream (cairo_pdf_document_t *document,
- const char *extra_entries)
+ const char *fmt,
+ ...)
{
cairo_output_stream_t *output_stream = document->output_stream;
cairo_pdf_stream_t *stream;
+ va_list ap;
stream = malloc (sizeof (cairo_pdf_stream_t));
if (stream == NULL) {
@@ -1038,13 +1041,19 @@
_cairo_output_stream_printf (output_stream,
"%d 0 obj\r\n"
- "<< /Length %d 0 R\r\n"
- "%s"
- ">>\r\n"
- "stream\r\n",
+ "<< /Length %d 0 R\r\n",
stream->id,
- stream->length_id,
- extra_entries);
+ stream->length_id);
+
+ if (fmt != NULL) {
+ va_start (ap, fmt);
+ _cairo_output_stream_vprintf (output_stream, fmt, ap);
+ va_end (ap);
+ }
+
+ _cairo_output_stream_printf (output_stream,
+ ">>\r\n"
+ "stream\r\n");
stream->start_offset = _cairo_output_stream_get_position (output_stream);
@@ -1107,18 +1116,17 @@
cairo_pdf_document_t *document = surface->document;
cairo_pdf_stream_t *stream;
cairo_output_stream_t *output = document->output_stream;
- char extra[200];
if (document->current_stream == NULL ||
document->current_stream != surface->current_stream) {
_cairo_pdf_document_close_stream (document);
- snprintf (extra, sizeof extra,
- " /Type /XObject\r\n"
- " /Subtype /Form\r\n"
- " /BBox [ 0 0 %f %f ]\r\n",
- surface->width,
- surface->height);
- stream = _cairo_pdf_document_open_stream (document, extra);
+ stream = _cairo_pdf_document_open_stream (document,
+ " /Type /XObject\r\n"
+ " /Subtype /Form\r\n"
+ " /BBox [ 0 0 %f %f ]\r\n",
+ surface->width,
+ surface->height);
+
_cairo_pdf_surface_add_stream (surface, stream);
/* If this is the first stream we open for this surface,
@@ -1153,7 +1161,6 @@
{
cairo_output_stream_t *output = document->output_stream;
cairo_pdf_stream_t *stream;
- char entries[200];
char *rgb, *compressed;
int i, x, y;
unsigned long rgb_size, compressed_size;
@@ -1183,17 +1190,16 @@
_cairo_pdf_document_close_stream (document);
- snprintf (entries, sizeof entries,
- " /Type /XObject\r\n"
- " /Subtype /Image\r\n"
- " /Width %d\r\n"
- " /Height %d\r\n"
- " /ColorSpace /DeviceRGB\r\n"
- " /BitsPerComponent 8\r\n"
- " /Filter /FlateDecode\r\n",
- image->width, image->height);
+ stream = _cairo_pdf_document_open_stream (document,
+ " /Type /XObject\r\n"
+ " /Subtype /Image\r\n"
+ " /Width %d\r\n"
+ " /Height %d\r\n"
+ " /ColorSpace /DeviceRGB\r\n"
+ " /BitsPerComponent 8\r\n"
+ " /Filter /FlateDecode\r\n",
+ image->width, image->height);
- stream = _cairo_pdf_document_open_stream (document, entries);
_cairo_output_stream_write (output, compressed, compressed_size);
_cairo_output_stream_printf (output,
"\r\n");
@@ -1387,7 +1393,6 @@
cairo_image_surface_t *image;
void *image_extra;
cairo_status_t status;
- char entries[250];
unsigned int id, alpha;
cairo_matrix_t pm;
@@ -1411,17 +1416,16 @@
pm = pattern->base.matrix;
cairo_matrix_invert (&pm);
- snprintf (entries, sizeof entries,
- " /BBox [ 0 0 256 256 ]\r\n"
- " /XStep 256\r\n"
- " /YStep 256\r\n"
- " /PatternType 1\r\n"
- " /TilingType 1\r\n"
- " /PaintType 1\r\n"
- " /Resources << /XObject << /res%d %d 0 R >> >>\r\n",
- id, id);
+ stream = _cairo_pdf_document_open_stream (document,
+ " /BBox [ 0 0 256 256 ]\r\n"
+ " /XStep 256\r\n"
+ " /YStep 256\r\n"
+ " /PatternType 1\r\n"
+ " /TilingType 1\r\n"
+ " /PaintType 1\r\n"
+ " /Resources << /XObject << /res%d %d 0 R >> >>\r\n",
+ id, id);
- stream = _cairo_pdf_document_open_stream (document, entries);
_cairo_output_stream_printf (output,
" /res%d Do\r\n",
@@ -2134,6 +2138,7 @@
cairo_pdf_object_t *object;
int num_objects, i;
long offset;
+ char buffer[11];
num_objects = _cairo_array_num_elements (&document->objects);
@@ -2147,8 +2152,9 @@
"0000000000 65535 f\r\n");
for (i = 0; i < num_objects; i++) {
object = _cairo_array_index (&document->objects, i);
+ snprintf (buffer, sizeof buffer, "%010ld", object->offset);
_cairo_output_stream_printf (output,
- "%010ld 00000 n\r\n", object->offset);
+ "%s 00000 n\r\n", buffer);
}
return offset;
Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.140
retrieving revision 1.141
diff -u -d -r1.140 -r1.141
--- cairoint.h 13 May 2005 06:11:55 -0000 1.140
+++ cairoint.h 13 May 2005 21:04:22 -0000 1.141
@@ -53,6 +53,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
#ifdef _MSC_VER
#define _USE_MATH_DEFINES
@@ -1783,6 +1784,10 @@
const void *data, size_t length);
cairo_private cairo_status_t
+_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
+ const char *fmt, va_list ap);
+
+cairo_private cairo_status_t
_cairo_output_stream_printf (cairo_output_stream_t *stream,
const char *fmt, ...);
- Previous message: [cairo-commit] cairo ChangeLog,1.581,1.582
- Next message: [cairo-commit] cairo-demo/X11 .cvsignore, 1.1, 1.2 ChangeLog, 1.13,
1.14 Makefile, 1.5, 1.6 cairo-demo-xcb.c, NONE,
1.1 cairo-demo.c, 1.12, 1.13 cairo-knockout.c, 1.14,
1.15 cairo-spline.c, 1.11, 1.12
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the cairo-commit
mailing list