[cairo-commit] 8 commits - configure.ac src/cairo-debug.c src/cairo.h src/cairoint.h src/cairo-jpeg-info.c src/cairo-jpeg-info-private.h src/cairo-misc.c src/cairo-mutex-list-private.h src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-surface.c src/cairo-surface-fallback.c src/cairo-surface-private.h src/cairo-types-private.h test/Makefile.am test/mime-data.c test/mime-data.ref.png test/romedalen.jpg util/cairo-trace
Chris Wilson
ickle at kemper.freedesktop.org
Mon Nov 3 03:47:32 PST 2008
configure.ac | 10 ++
src/cairo-debug.c | 2
src/cairo-jpeg-info-private.h | 6 -
src/cairo-jpeg-info.c | 19 +---
src/cairo-misc.c | 98 ++++++++++++++++++++
src/cairo-mutex-list-private.h | 1
src/cairo-pdf-surface.c | 22 ++--
src/cairo-ps-surface.c | 2
src/cairo-surface-fallback.c | 37 +++++--
src/cairo-surface-private.h | 4
src/cairo-surface.c | 95 +++++++++++++++-----
src/cairo-types-private.h | 7 +
src/cairo.h | 4
src/cairoint.h | 8 +
test/Makefile.am | 3
test/mime-data.c | 111 +++++++++++++++++++++++
test/mime-data.ref.png |binary
test/romedalen.jpg |binary
util/cairo-trace/Makefile.am | 2
util/cairo-trace/lookup-symbol.c | 6 -
util/cairo-trace/trace.c | 184 +++++++++++++++++++++++++++++++++------
21 files changed, 528 insertions(+), 93 deletions(-)
New commits:
commit ca83df55a63eab1821dbc009f65b3b09d61f5b62
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Mon Nov 3 11:46:31 2008 +0000
[trace] Wrap test surfaces.
Wrap the test surfaces to avoid crashes whilst tracing the test suite.
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 7c595f1..b8676c3 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -37,7 +37,7 @@
#include <ctype.h>
#include <cairo.h>
-#ifdef CAIRO_HAS_FT_FONT
+#if CAIRO_HAS_FT_FONT
# include <cairo-ft.h>
#endif
@@ -2755,7 +2755,7 @@ cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
return DLCALL (cairo_pattern_set_extend, pattern, extend);
}
-#ifdef CAIRO_HAS_FT_FONT
+#if CAIRO_HAS_FT_FONT
cairo_font_face_t *
cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
{
@@ -2939,7 +2939,7 @@ FT_Done_Face (FT_Face face)
}
#endif
-#ifdef CAIRO_HAS_PS_SURFACE
+#if CAIRO_HAS_PS_SURFACE
#include<cairo-ps.h>
cairo_surface_t *
@@ -3006,7 +3006,7 @@ cairo_ps_surface_set_size (cairo_surface_t *surface, double width_in_points, dou
#endif
-#ifdef CAIRO_HAS_PDF_SURFACE
+#if CAIRO_HAS_PDF_SURFACE
#include <cairo-pdf.h>
cairo_surface_t *
@@ -3071,7 +3071,7 @@ cairo_pdf_surface_set_size (cairo_surface_t *surface, double width_in_points, do
}
#endif
-#ifdef CAIRO_HAS_SVG_SURFACE
+#if CAIRO_HAS_SVG_SURFACE
#include <cairo-svg.h>
cairo_surface_t *
@@ -3215,7 +3215,7 @@ cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func, void *c
return ret;
}
-#ifdef CAIRO_HAS_XLIB_SURFACE
+#if CAIRO_HAS_XLIB_SURFACE
#include <cairo-xlib.h>
cairo_surface_t *
@@ -3275,7 +3275,7 @@ cairo_xlib_surface_create_for_bitmap (Display *dpy, Pixmap bitmap, Screen *scree
return ret;
}
-#ifdef CAIRO_HAS_XLIB_XRENDER_SURFACE
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
#include <cairo-xlib-xrender.h>
cairo_surface_t *
cairo_xlib_surface_create_with_xrender_format (Display *dpy, Drawable drawable, Screen *screen, XRenderPictFormat *format, int width, int height)
@@ -3309,7 +3309,7 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy, Drawable drawable,
#endif
#endif
-#ifdef CAIRO_HAS_SCRIPT_SURFACE
+#if CAIRO_HAS_SCRIPT_SURFACE
#include <cairo-script.h>
cairo_surface_t *
cairo_script_surface_create (const char *filename,
@@ -3373,3 +3373,103 @@ cairo_script_surface_create_for_stream (cairo_write_func_t write_func,
return ret;
}
#endif
+
+#if CAIRO_HAS_TEST_SURFACES
+#include <test-fallback-surface.h>
+cairo_surface_t *
+_cairo_test_fallback_surface_create (cairo_content_t content,
+ int width,
+ int height)
+{
+ cairo_surface_t *ret;
+ long surface_id;
+
+ ret = DLCALL (_cairo_test_fallback_surface_create, content, width, height);
+ surface_id = _create_surface_id (ret);
+
+ if (_write_lock ()) {
+ fprintf (logfile,
+ "dict\n"
+ " /type (test-fallback) set\n"
+ " /content //%s set\n"
+ " /width %d set\n"
+ " /height %d set\n"
+ " surface dup /s%ld exch def\n",
+ _content_to_string (content),
+ width, height,
+ surface_id);
+ _get_object (SURFACE, ret)->defined = true;
+ _push_operand (SURFACE, ret);
+ _write_unlock ();
+ }
+
+ return ret;
+}
+
+#include <test-paginated-surface.h>
+cairo_surface_t *
+_cairo_test_paginated_surface_create_for_data (unsigned char *data,
+ cairo_content_t content,
+ int width,
+ int height,
+ int stride)
+{
+ cairo_surface_t *ret;
+ long surface_id;
+
+ ret = DLCALL (_cairo_test_paginated_surface_create_for_data,
+ data, content, width, height, stride);
+ surface_id = _create_surface_id (ret);
+
+ if (_write_lock ()) {
+ /* XXX store initial data? */
+ fprintf (logfile,
+ "dict\n"
+ " /type (test-paginated) set\n"
+ " /content //%s set\n"
+ " /width %d set\n"
+ " /height %d set\n"
+ " /stride %d set\n"
+ " surface dup /s%ld exch def\n",
+ _content_to_string (content),
+ width, height, stride,
+ surface_id);
+ _get_object (SURFACE, ret)->defined = true;
+ _push_operand (SURFACE, ret);
+ _write_unlock ();
+ }
+
+ return ret;
+}
+
+#include <test-meta-surface.h>
+cairo_surface_t *
+_cairo_test_meta_surface_create (cairo_content_t content,
+ int width,
+ int height)
+{
+ cairo_surface_t *ret;
+ long surface_id;
+
+ ret = DLCALL (_cairo_test_meta_surface_create, content, width, height);
+ surface_id = _create_surface_id (ret);
+
+ if (_write_lock ()) {
+ fprintf (logfile,
+ "dict\n"
+ " /type (test-meta) set\n"
+ " /content //%s set\n"
+ " /width %d set\n"
+ " /height %d set\n"
+ " surface dup /s%ld exch def\n",
+ _content_to_string (content),
+ width, height,
+ surface_id);
+ _get_object (SURFACE, ret)->defined = true;
+ _push_operand (SURFACE, ret);
+ _write_unlock ();
+ }
+
+ return ret;
+}
+#endif
commit 2c08f3f83b1acd168cd74b300272970658179a0f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Mon Nov 3 11:30:38 2008 +0000
[trace] Autodetect -lbfd during configure
Stop being lazy and detect libbfd during configure.
diff --git a/configure.ac b/configure.ac
index da2f861..97a09b6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -495,6 +495,16 @@ esac
AM_CONDITIONAL(BUILD_TRACE, test "x$have_ld_preload" = "xyes")
+AC_CHECK_LIB(bfd, bfd_openr,
+ [AC_CHECK_HEADER(bfd.h, [have_bfd=yes],
+ [have_bfd="no (requires binutils-dev)"])],
+ [have_bfd="no (requires binutils-dev)"])
+if test "x$have_bfd" = "xyes"; then
+ AC_DEFINE([HAVE_BFD], [1], [Define to 1 if you have binutils-dev installed])
+ BFD_LIBS=-lbfd
+ AC_SUBST(BFD_LIBS)
+fi
+
dnl ===========================================================================
AC_ARG_ENABLE(some-floating-point,
diff --git a/util/cairo-trace/Makefile.am b/util/cairo-trace/Makefile.am
index 13161c6..6d7d748 100644
--- a/util/cairo-trace/Makefile.am
+++ b/util/cairo-trace/Makefile.am
@@ -10,7 +10,7 @@ cairo_trace_la_SOURCES = \
trace.c
cairo_trace_la_CFLAGS = @FREETYPE_CFLAGS@ @CAIRO_CFLAGS@
cairo_trace_la_LDFLAGS = -module -no-undefined
-cairo_trace_la_LIBADD = -ldl -lz -lbfd
+cairo_trace_la_LIBADD = -ldl -lz @BFD_LIBS@
system-install:
grep -sq @libdir@/cairo-trace.so /etc/ld.so.preload || echo @libdir@/cairo-trace.so >> /etc/ld.so.preload
diff --git a/util/cairo-trace/lookup-symbol.c b/util/cairo-trace/lookup-symbol.c
index b5f0fdf..df7e6b0 100644
--- a/util/cairo-trace/lookup-symbol.c
+++ b/util/cairo-trace/lookup-symbol.c
@@ -62,7 +62,7 @@
#include <link.h>
#include <string.h>
-#ifdef HAVE_LIBBFD
+#if HAVE_BFD
#include <bfd.h>
#include <libiberty.h>
@@ -255,7 +255,7 @@ char *
lookup_symbol (char *buf, int buflen, const void *ptr)
{
struct file_match match;
-#ifdef HAVE_LIBBFD
+#if HAVE_BFD
struct symtab symtab;
struct symbol symbol;
#endif
@@ -271,7 +271,7 @@ lookup_symbol (char *buf, int buflen, const void *ptr)
if (match.file == NULL || *match.file == '\0')
match.file = "/proc/self/exe";
-#ifdef HAVE_LIBBFD
+#if HAVE_BFD
if (! _symtab_init (&symtab, match.file))
return buf;
commit 8fc3d0ffebea5622332327cdef9222486cc85581
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Mon Nov 3 11:01:22 2008 +0000
[mime-data] Allow embedding of arbitrary mime-types.
Use the surface user-data array allow to store an arbitrary set of
alternate image representations keyed by an interned string (which
ensures that it has a unique key in the user-visible namespace).
Update the API to mirror that of cairo_surface_set_user_data() [i.e.
return a status indicator] and switch internal users of the mime-data to
the public functions.
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index 61156f0..6dd5787 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -67,6 +67,8 @@ cairo_debug_reset_static_data (void)
_cairo_ft_font_reset_static_data ();
#endif
+ _cairo_intern_string_reset_static_data ();
+
_cairo_scaled_font_reset_static_data ();
_cairo_pattern_reset_static_data ();
diff --git a/src/cairo-jpeg-info-private.h b/src/cairo-jpeg-info-private.h
index 1a376c9..365825c 100644
--- a/src/cairo-jpeg-info-private.h
+++ b/src/cairo-jpeg-info-private.h
@@ -46,9 +46,9 @@ typedef struct _cairo_jpeg_info {
} cairo_jpeg_info_t;
cairo_private cairo_int_status_t
-_cairo_jpeg_get_info (unsigned char *data,
- long length,
- cairo_jpeg_info_t *info);
+_cairo_jpeg_get_info (const unsigned char *data,
+ long length,
+ cairo_jpeg_info_t *info);
#endif /* CAIRO_JPEG_INFO_PRIVATE_H */
diff --git a/src/cairo-jpeg-info.c b/src/cairo-jpeg-info.c
index 75dc0bf..ca85cef 100644
--- a/src/cairo-jpeg-info.c
+++ b/src/cairo-jpeg-info.c
@@ -59,33 +59,32 @@
#define SOF14 0xce
#define SOF15 0xcf
-static unsigned char *
-_skip_segment (unsigned char *p)
+static const unsigned char *
+_skip_segment (const unsigned char *p)
{
int len;
p++;
- len = p[0] << 8;
- len |= p[1];
+ len = (p[0] << 8) | p[1];
return p + len;
}
static void
-_extract_info (cairo_jpeg_info_t *info, unsigned char *p)
+_extract_info (cairo_jpeg_info_t *info, const unsigned char *p)
{
info->width = (p[6] << 8) + p[7];
- info->height = (p[4] << 8) + p[5];;
+ info->height = (p[4] << 8) + p[5];
info->num_components = p[8];
info->bits_per_component = p[3];
}
cairo_int_status_t
-_cairo_jpeg_get_info (unsigned char *data,
- long length,
- cairo_jpeg_info_t *info)
+_cairo_jpeg_get_info (const unsigned char *data,
+ long length,
+ cairo_jpeg_info_t *info)
{
- unsigned char *p = data;
+ const unsigned char *p = data;
while (p + 1 < data + length) {
if (*p != 0xff)
diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index 27050a2..667fa52 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -667,3 +667,101 @@ _cairo_win32_tmpfile (void)
}
#endif /* _WIN32 */
+
+typedef struct _cairo_intern_string {
+ cairo_hash_entry_t hash_entry;
+ int len;
+ char *string;
+} cairo_intern_string_t;
+
+static cairo_hash_table_t *_cairo_intern_string_ht;
+
+static unsigned long
+_intern_string_hash (const char *str, int len)
+{
+ const signed char *p = (const signed char *) str;
+ unsigned int h = *p;
+
+ for (p += 1; --len; p++)
+ h = (h << 5) - h + *p;
+
+ return h;
+}
+
+static cairo_bool_t
+_intern_string_equal (const void *_a, const void *_b)
+{
+ const cairo_intern_string_t *a = _a;
+ const cairo_intern_string_t *b = _b;
+
+ if (a->len != b->len)
+ return FALSE;
+
+ return memcmp (a->string, b->string, a->len) == 0;
+}
+
+cairo_status_t
+_cairo_intern_string (const char **str_inout, int len)
+{
+ char *str = (char *) *str_inout;
+ cairo_intern_string_t tmpl, *istring;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ if (len < 0)
+ len = strlen (str);
+ tmpl.hash_entry.hash = _intern_string_hash (str, len);
+ tmpl.len = len;
+ tmpl.string = (char *) str;
+
+ CAIRO_MUTEX_LOCK (_cairo_intern_string_mutex);
+ if (_cairo_intern_string_ht == NULL)
+ _cairo_intern_string_ht = _cairo_hash_table_create (_intern_string_equal);
+
+ if (! _cairo_hash_table_lookup (_cairo_intern_string_ht,
+ &tmpl.hash_entry,
+ (cairo_hash_entry_t **) &istring))
+ {
+ istring = malloc (sizeof (cairo_intern_string_t) + len + 1);
+ if (istring != NULL) {
+ istring->hash_entry.hash = tmpl.hash_entry.hash;
+ istring->len = tmpl.len;
+ istring->string = (char *) (istring + 1);
+ memcpy (istring->string, str, len);
+ istring->string[len] = '\0';
+
+ status = _cairo_hash_table_insert (_cairo_intern_string_ht,
+ &istring->hash_entry);
+ if (status)
+ free (istring);
+ } else
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ CAIRO_MUTEX_UNLOCK (_cairo_intern_string_mutex);
+
+ if (status == CAIRO_STATUS_SUCCESS)
+ *str_inout = istring->string;
+
+ return status;
+}
+
+static void
+_intern_string_pluck (void *entry, void *closure)
+{
+ _cairo_hash_table_remove (closure, entry);
+ free (entry);
+}
+
+void
+_cairo_intern_string_reset_static_data (void)
+{
+ CAIRO_MUTEX_LOCK (_cairo_intern_string_mutex);
+ if (_cairo_intern_string_ht != NULL) {
+ _cairo_hash_table_foreach (_cairo_intern_string_ht,
+ _intern_string_pluck,
+ _cairo_intern_string_ht);
+ _cairo_hash_table_destroy(_cairo_intern_string_ht);
+ _cairo_intern_string_ht = NULL;
+ }
+ CAIRO_MUTEX_UNLOCK (_cairo_intern_string_mutex);
+}
diff --git a/src/cairo-mutex-list-private.h b/src/cairo-mutex-list-private.h
index 6fdb389..f5f654d 100644
--- a/src/cairo-mutex-list-private.h
+++ b/src/cairo-mutex-list-private.h
@@ -40,6 +40,7 @@ CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock)
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock)
CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex)
+CAIRO_MUTEX_DECLARE (_cairo_intern_string_mutex)
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex)
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex)
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 51eb07e..7bcb057 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1558,15 +1558,17 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
int *width,
int *height)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_status_t status;
+ const unsigned char *mime_data;
+ unsigned int mime_data_length;
cairo_jpeg_info_t info;
- if (source->jpeg_data == NULL)
+ cairo_surface_get_mime_data (&surface->base, CAIRO_MIME_TYPE_JPEG,
+ &mime_data, &mime_data_length);
+ if (mime_data == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
- status = _cairo_jpeg_get_info (source->jpeg_data,
- source->jpeg_data_length,
- &info);
+ status = _cairo_jpeg_get_info (mime_data, mime_data_length, &info);
if (status)
return status;
@@ -1591,9 +1593,7 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
return status;
*res = surface->pdf_stream.self;
- _cairo_output_stream_write (surface->output,
- source->jpeg_data,
- source->jpeg_data_length);
+ _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
status = _cairo_pdf_surface_close_stream (surface);
*width = info.width;
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 6266117..7cfbd65 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -1035,6 +1035,8 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
cairo_status_t status;
cairo_surface_pattern_t pattern;
cairo_image_surface_t *image;
+ const unsigned char *mime_data;
+ unsigned int mime_data_length;
void *image_extra;
status = _cairo_surface_acquire_source_image (surface,
@@ -1075,19 +1077,32 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
snapshot->device_transform = surface->device_transform;
snapshot->device_transform_inverse = surface->device_transform_inverse;
- if (surface->jpeg_destroy &&
- surface->jpeg_data != NULL &&
- surface->jpeg_data_length != 0)
- {
- snapshot->jpeg_data = malloc (surface->jpeg_data_length);
- if (snapshot->jpeg_data == NULL) {
+ /* XXX Need to copy all known image representations...
+ * For now, just copy "image/jpeg", but in future we should construct
+ * an array of known types and iterate.
+ */
+ cairo_surface_get_mime_data (surface, CAIRO_MIME_TYPE_JPEG,
+ &mime_data, &mime_data_length);
+ if (mime_data != NULL) {
+ unsigned char *mime_data_copy;
+
+ mime_data_copy = malloc (mime_data_length);
+ if (mime_data == NULL) {
cairo_surface_destroy (snapshot);
- return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+ }
+ memcpy (mime_data_copy, mime_data, mime_data_length);
+
+ status = cairo_surface_set_mime_data (snapshot,
+ CAIRO_MIME_TYPE_JPEG,
+ mime_data_copy,
+ mime_data_length,
+ free);
+ if (status) {
+ free (mime_data_copy);
+ cairo_surface_destroy (snapshot);
+ return _cairo_surface_create_in_error (status);
}
-
- memcpy (snapshot->jpeg_data, surface->jpeg_data, surface->jpeg_data_length);
- snapshot->jpeg_data_length = surface->jpeg_data_length;
- snapshot->jpeg_destroy = free;
}
snapshot->is_snapshot = TRUE;
diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index 1b5bb04..efd4365 100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
@@ -100,10 +100,6 @@ struct _cairo_surface {
*/
cairo_bool_t has_font_options;
cairo_font_options_t font_options;
-
- unsigned char *jpeg_data;
- unsigned int jpeg_data_length;
- cairo_destroy_func_t jpeg_destroy;
};
#endif /* CAIRO_SURFACE_PRIVATE_H */
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 808fc85..109cbb9 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -220,10 +220,6 @@ _cairo_surface_init (cairo_surface_t *surface,
surface->is_snapshot = FALSE;
surface->has_font_options = FALSE;
-
- surface->jpeg_data = NULL;
- surface->jpeg_data_length = 0;
- surface->jpeg_destroy = NULL;
}
cairo_surface_t *
@@ -444,9 +440,6 @@ cairo_surface_destroy (cairo_surface_t *surface)
_cairo_user_data_array_fini (&surface->user_data);
- if (surface->jpeg_data)
- surface->jpeg_destroy (surface->jpeg_data);
-
free (surface);
}
slim_hidden_def(cairo_surface_destroy);
@@ -615,12 +608,39 @@ cairo_surface_get_mime_data (cairo_surface_t *surface,
const unsigned char **data,
unsigned int *length)
{
- if (strcmp (mime_type, CAIRO_MIME_TYPE_JPEG) == 0) {
- *data = surface->jpeg_data;
- *length = surface->jpeg_data_length;
- } else {
- *data = NULL;
+ cairo_status_t status;
+ cairo_mime_data_t *mime_data;
+
+ *data = NULL;
+ *length = 0;
+ if (surface->status)
+ return;
+
+ status = _cairo_intern_string (&mime_type, -1);
+ if (status) {
+ status = _cairo_surface_set_error (surface, status);
+ return;
}
+
+ mime_data = _cairo_user_data_array_get_data (&surface->user_data,
+ (cairo_user_data_key_t *) mime_type);
+ if (mime_data == NULL)
+ return;
+
+ *data = mime_data->data;
+ *length = mime_data->length;
+}
+slim_hidden_def (cairo_surface_get_mime_data);
+
+static void
+_cairo_mime_data_destroy (void *ptr)
+{
+ cairo_mime_data_t *mime_data = ptr;
+
+ if (mime_data->destroy && mime_data->data)
+ mime_data->destroy (mime_data->data);
+
+ free (mime_data);
}
/**
@@ -638,23 +658,56 @@ cairo_surface_get_mime_data (cairo_surface_t *surface,
* and %NULL for @data.
*
* Since: 1.10
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
+ * slot could not be allocated for the user data.
**/
-void
+cairo_status_t
cairo_surface_set_mime_data (cairo_surface_t *surface,
const char *mime_type,
const unsigned char *data,
unsigned int length,
cairo_destroy_func_t destroy)
{
- if (strcmp (mime_type, CAIRO_MIME_TYPE_JPEG) == 0) {
- if (surface->jpeg_data)
- surface->jpeg_destroy (surface->jpeg_data);
+ cairo_status_t status;
+ cairo_mime_data_t *mime_data;
+
+ if (surface->status)
+ return surface->status;
- surface->jpeg_data = (unsigned char *) data;
- surface->jpeg_data_length = length;
- surface->jpeg_destroy = destroy;
+ status = _cairo_intern_string (&mime_type, -1);
+ if (status)
+ return _cairo_surface_set_error (surface, status);
+
+ mime_data = _cairo_user_data_array_get_data (&surface->user_data,
+ (cairo_user_data_key_t *) mime_type);
+ if (mime_data != NULL) {
+ if (mime_data->destroy && mime_data->data)
+ mime_data->destroy (mime_data->data);
+
+ mime_data->data = (unsigned char *) data;
+ mime_data->length = length;
+ mime_data->destroy = destroy;
+ } else {
+ mime_data = malloc (sizeof (cairo_mime_data_t));
+ if (mime_data == NULL)
+ return _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+ mime_data->data = (unsigned char *) data;
+ mime_data->length = length;
+ mime_data->destroy = destroy;
+
+ status = _cairo_user_data_array_set_data (&surface->user_data,
+ (cairo_user_data_key_t *) mime_type,
+ mime_data,
+ _cairo_mime_data_destroy);
+ if (status)
+ return _cairo_surface_set_error (surface, status);
}
+
+ return CAIRO_STATUS_SUCCESS;
}
+slim_hidden_def (cairo_surface_set_mime_data);
/**
* _cairo_surface_set_font_options:
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 12e1a20..8bcbf9a 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -52,6 +52,7 @@ typedef struct _cairo_gstate cairo_gstate_t;
typedef struct _cairo_hash_entry cairo_hash_entry_t;
typedef struct _cairo_hash_table cairo_hash_table_t;
typedef struct _cairo_image_surface cairo_image_surface_t;
+typedef struct _cairo_mime_data cairo_mime_data_t;
typedef struct _cairo_output_stream cairo_output_stream_t;
typedef struct _cairo_paginated_surface_backend cairo_paginated_surface_backend_t;
typedef struct _cairo_path_fixed cairo_path_fixed_t;
@@ -342,4 +343,10 @@ typedef enum _cairo_image_transparency {
CAIRO_IMAGE_UNKNOWN
} cairo_image_transparency_t;
+struct _cairo_mime_data {
+ unsigned char *data;
+ unsigned int length;
+ cairo_destroy_func_t destroy;
+};
+
#endif /* CAIRO_TYPES_PRIVATE_H */
diff --git a/src/cairo.h b/src/cairo.h
index 32005bb..a1cd0c5 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1951,11 +1951,11 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
cairo_public void
cairo_surface_get_mime_data (cairo_surface_t *surface,
- const char *mime_type,
+ const char *mime_type,
const unsigned char **data,
unsigned int *length);
-cairo_public void
+cairo_public cairo_status_t
cairo_surface_set_mime_data (cairo_surface_t *surface,
const char *mime_type,
const unsigned char *data,
diff --git a/src/cairoint.h b/src/cairoint.h
index 4e9eea4..7fe853c 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1391,6 +1391,12 @@ _cairo_validate_text_clusters (const char *utf8,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags);
+cairo_private cairo_status_t
+_cairo_intern_string (const char **str_inout, int len);
+
+cairo_private void
+_cairo_intern_string_reset_static_data (void);
+
/* cairo-path-fixed.c */
cairo_private void
_cairo_path_fixed_init (cairo_path_fixed_t *path);
@@ -2515,6 +2521,8 @@ slim_hidden_proto (cairo_surface_flush);
slim_hidden_proto (cairo_surface_get_content);
slim_hidden_proto (cairo_surface_get_device_offset);
slim_hidden_proto (cairo_surface_get_font_options);
+slim_hidden_proto (cairo_surface_get_mime_data);
+slim_hidden_proto (cairo_surface_set_mime_data);
slim_hidden_proto (cairo_surface_get_type);
slim_hidden_proto (cairo_surface_has_show_text_glyphs);
slim_hidden_proto (cairo_surface_mark_dirty_rectangle);
diff --git a/test/Makefile.am b/test/Makefile.am
index 21976de..02debdf 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -106,6 +106,7 @@ test_sources = \
mask-transformed-image.c \
mask-transformed-similar.c \
meta-surface-pattern.c \
+ mime-data.c \
miter-precision.c \
move-to-show-surface.c \
new-sub-path.c \
@@ -687,6 +688,7 @@ REFERENCE_IMAGES = \
meta-surface-pattern.svg11.rgb24.ref.png \
meta-surface-pattern.svg12.argb32.ref.png \
meta-surface-pattern.svg12.rgb24.ref.png \
+ mime-data.ref.png \
miter-precision.ref.png \
miter-precision.ps2.ref.png \
miter-precision.ps3.ref.png \
@@ -994,6 +996,7 @@ EXTRA_DIST += \
6x13.pcf \
make-html.pl \
romedalen.png \
+romedalen.jpg \
surface-source.c \
$(REFERENCE_IMAGES)
diff --git a/test/mime-data.c b/test/mime-data.c
new file mode 100644
index 0000000..b364915
--- /dev/null
+++ b/test/mime-data.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+/* Basic test to exercise the new mime-data embedding. */
+
+static cairo_status_t
+read_jpg_file (const cairo_test_context_t *ctx,
+ unsigned char **data_out,
+ unsigned int *length_out)
+{
+ const char jpg_filename[] = "romedalen.jpg";
+ FILE *file;
+ unsigned char *buf;
+ unsigned int len;
+
+ file = fopen (jpg_filename, "rb");
+ if (file == NULL) {
+ char filename[4096];
+
+ /* try again with srcdir */
+ snprintf (filename, sizeof (filename),
+ "%s/%s", ctx->srcdir, jpg_filename);
+ file = fopen (filename, "rb");
+ }
+ if (file == NULL) {
+ switch (errno) {
+ case ENOMEM:
+ return CAIRO_STATUS_NO_MEMORY;
+ default:
+ return CAIRO_STATUS_FILE_NOT_FOUND;
+ }
+ }
+
+ fseek (file, 0, SEEK_END);
+ len = ftell (file);
+ fseek (file, 0, SEEK_SET);
+
+ buf = xmalloc (len);
+ *length_out = fread (buf, 1, len, file);
+ fclose (file);
+ if (*length_out != len) {
+ free (buf);
+ return CAIRO_STATUS_READ_ERROR;
+ }
+
+ *data_out = buf;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ const cairo_test_context_t *ctx = cairo_test_get_context (cr);
+ cairo_surface_t *image;
+ unsigned char *jpg_data;
+ unsigned int jpg_len;
+ cairo_status_t status;
+
+ status = read_jpg_file (ctx, &jpg_data, &jpg_len);
+ if (status) {
+ return cairo_test_status_from_status (ctx, status);
+ }
+
+ image = cairo_test_create_surface_from_png (ctx, "romedalen.png");
+ status = cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_JPEG,
+ jpg_data, jpg_len, free);
+ if (status) {
+ cairo_surface_destroy (image);
+ return cairo_test_status_from_status (ctx, status);
+ }
+
+ cairo_set_source_surface (cr, image, 0, 0);
+ cairo_surface_destroy (image);
+ cairo_paint (cr);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (mime_data,
+ "Check that the mime-data embedding works",
+ "jpeg, api", /* keywords */
+ NULL, /* requirements */
+ 10, 10,
+ NULL, draw)
diff --git a/test/mime-data.ref.png b/test/mime-data.ref.png
new file mode 100644
index 0000000..cc13baf
Binary files /dev/null and b/test/mime-data.ref.png differ
diff --git a/test/romedalen.jpg b/test/romedalen.jpg
new file mode 100644
index 0000000..d655e3d
Binary files /dev/null and b/test/romedalen.jpg differ
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 601bf94..7c595f1 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -2508,7 +2508,7 @@ cairo_surface_show_page (cairo_surface_t *surface)
return DLCALL (cairo_surface_show_page, surface);
}
-void
+cairo_status_t
cairo_surface_set_mime_data (cairo_surface_t *surface,
const char *mime_type,
const unsigned char *data,
commit afef83a1fae028b45cefd6b4698e7b32ad4d6fc7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Mon Nov 3 09:40:35 2008 +0000
Compile tidy.
Fix a few minor compiler warnings.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index d254752..51eb07e 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -4470,7 +4470,7 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
if ( _cairo_surface_is_meta (surface_pattern->surface)) {
- if (cairo_pattern_get_extend (pattern) == CAIRO_EXTEND_PAD)
+ if (pattern->extend == CAIRO_EXTEND_PAD)
return CAIRO_INT_STATUS_UNSUPPORTED;
else
return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index e050ddb..29e9872 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1572,7 +1572,7 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
if ( _cairo_surface_is_meta (surface_pattern->surface)) {
- if (cairo_pattern_get_extend (pattern) == CAIRO_EXTEND_PAD)
+ if (pattern->extend == CAIRO_EXTEND_PAD)
return CAIRO_INT_STATUS_UNSUPPORTED;
else
return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 79366f2..808fc85 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -605,13 +605,13 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
*
* Return mime data previously attached to @surface using the
* specified mime type. If no data has been attached with the given
- * mime type, @data is set NULL.
+ * mime type, @data is set %NULL.
*
* Since: 1.10
**/
void
cairo_surface_get_mime_data (cairo_surface_t *surface,
- const char *mime_type,
+ const char *mime_type,
const unsigned char **data,
unsigned int *length)
{
@@ -650,7 +650,7 @@ cairo_surface_set_mime_data (cairo_surface_t *surface,
if (surface->jpeg_data)
surface->jpeg_destroy (surface->jpeg_data);
- surface->jpeg_data = data;
+ surface->jpeg_data = (unsigned char *) data;
surface->jpeg_data_length = length;
surface->jpeg_destroy = destroy;
}
commit f77723fc88c12ebf6f5bff5a1797649d134ecc5d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sun Nov 2 19:59:53 2008 +0000
[pdf] Missing status check.
Check that stream was successfully opened before attempting to write to
it.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 827c9ea..d254752 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1553,7 +1553,7 @@ CLEANUP:
static cairo_int_status_t
_cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
- cairo_surface_t *source,
+ cairo_surface_t *source,
cairo_pdf_resource_t *res,
int *width,
int *height)
@@ -1587,6 +1587,8 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
info.height,
info.num_components == 1 ? "/DeviceGray" : "/DeviceRGB",
info.bits_per_component);
+ if (status)
+ return status;
*res = surface->pdf_stream.self;
_cairo_output_stream_write (surface->output,
commit 04e3bb932eeac4f403b512087b96a164d082d52c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sun Nov 2 21:51:37 2008 +0000
[trace] Emit set_mime_data().
Wrap the new cairo_surface_set_mime_data() function.
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index a9e4ce3..601bf94 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -912,7 +912,9 @@ _write_zlib_data (struct _data_stream *stream, bool flush)
}
static void
-_write_data (struct _data_stream *stream, void *data, unsigned int length)
+_write_data (struct _data_stream *stream,
+ const void *data,
+ unsigned int length)
{
unsigned int count;
const unsigned char *p = data;
@@ -963,7 +965,7 @@ _write_data_end (struct _data_stream *stream)
}
static void
-_emit_data (void *data, unsigned int length)
+_emit_data (const void *data, unsigned int length)
{
struct _data_stream stream;
@@ -2506,6 +2508,30 @@ cairo_surface_show_page (cairo_surface_t *surface)
return DLCALL (cairo_surface_show_page, surface);
}
+void
+cairo_surface_set_mime_data (cairo_surface_t *surface,
+ const char *mime_type,
+ const unsigned char *data,
+ unsigned int length,
+ cairo_destroy_func_t destroy)
+{
+ if (surface != NULL && _write_lock ()) {
+ _emit_surface (surface);
+ _emit_string_literal (mime_type, -1);
+ fprintf (logfile, " ");
+ _emit_data (data, length);
+ fprintf (logfile, " /deflate filter set_mime_data\n");
+
+ _write_unlock ();
+ }
+
+ return DLCALL (cairo_surface_set_mime_data,
+ surface,
+ mime_type,
+ data, length,
+ destroy);
+}
+
cairo_status_t
cairo_surface_write_to_png (cairo_surface_t *surface, const char *filename)
{
commit 350fa7b98e5045a4fa05f64a1ad7d8167036be34
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Nov 1 13:12:43 2008 +0000
[trace] Fix boundary terminations
Don't increment the terminator!
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 708557b..a9e4ce3 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -2235,7 +2235,7 @@ cairo_show_text_glyphs (cairo_t *cr,
_emit_glyphs (font, glyphs, num_glyphs);
fprintf (logfile, " [");
- for (n = 0; n < num_clusters++; n++) {
+ for (n = 0; n < num_clusters; n++) {
fprintf (logfile, " %d %d",
clusters[n].num_bytes,
clusters[n].num_glyphs);
commit f3cbc5cf4580da83b7edacfd381afee3d571c659
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 31 23:47:16 2008 +0000
[trace] Use utf8 len in show_text_glyphs().
Honour the parameter specifying the length of the utf8 string when
emitting show_text_glyphs.
diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c
index 548eb69..708557b 100644
--- a/util/cairo-trace/trace.c
+++ b/util/cairo-trace/trace.c
@@ -1087,18 +1087,23 @@ _emit_image (cairo_surface_t *image)
}
static void
-_emit_string_literal (const char *utf8)
+_emit_string_literal (const char *utf8, int len)
{
char c;
+ const char *end;
if (utf8 == NULL) {
fprintf (logfile, "()");
return;
}
+ if (len < 0)
+ len = strlen (utf8);
+ end = utf8 + len;
+
fprintf (logfile, "(");
- while ((c = *utf8++)) {
- switch (c) {
+ while (utf8 < end) {
+ switch ((c = *utf8++)) {
case '\n':
case '\r':
case '\\':
@@ -1847,7 +1852,7 @@ cairo_select_font_face (cairo_t *cr, const char *family, cairo_font_slant_t slan
{
if (cr != NULL && _write_lock ()) {
_emit_context (cr);
- _emit_string_literal (family);
+ _emit_string_literal (family, -1);
fprintf (logfile, " //%s //%s select_font_face\n",
_slant_to_string (slant),
_weight_to_string (weight));
@@ -2097,7 +2102,7 @@ cairo_show_text (cairo_t *cr, const char *utf8)
{
if (cr != NULL && _write_lock ()) {
_emit_context (cr);
- _emit_string_literal (utf8);
+ _emit_string_literal (utf8, -1);
fprintf (logfile, " show_text\n");
_write_unlock ();
}
@@ -2226,8 +2231,7 @@ cairo_show_text_glyphs (cairo_t *cr,
_emit_context (cr);
- _emit_string_literal (utf8);
- fprintf (logfile, " %d ", utf8_len);
+ _emit_string_literal (utf8, utf8_len);
_emit_glyphs (font, glyphs, num_glyphs);
fprintf (logfile, " [");
@@ -2254,7 +2258,7 @@ cairo_text_path (cairo_t *cr, const char *utf8)
{
if (cr != NULL && _write_lock ()) {
_emit_context (cr);
- _emit_string_literal (utf8);
+ _emit_string_literal (utf8, -1);
fprintf (logfile, " text_path\n");
_write_unlock ();
}
@@ -2507,7 +2511,7 @@ cairo_surface_write_to_png (cairo_surface_t *surface, const char *filename)
{
if (surface != NULL && _write_lock ()) {
fprintf (logfile, "%% s%ld ", _get_surface_id (surface));
- _emit_string_literal (filename);
+ _emit_string_literal (filename, -1);
fprintf (logfile, " write_to_png\n");
_write_unlock ();
}
@@ -2524,7 +2528,7 @@ cairo_surface_write_to_png_stream (cairo_surface_t *surface,
fprintf (logfile, "%% s%ld ", _get_surface_id (surface));
lookup_symbol (symbol, sizeof (symbol), write_func);
- _emit_string_literal (symbol);
+ _emit_string_literal (symbol, -1);
fprintf (logfile, " write_to_png_stream\n");
_write_unlock ();
}
@@ -2743,7 +2747,7 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
"dict\n"
" /type 42 set\n"
" /pattern ");
- _emit_string_literal ((char *) parsed);
+ _emit_string_literal ((char *) parsed, -1);
fprintf (logfile,
" set\n"
" font\n");
@@ -2926,7 +2930,7 @@ cairo_ps_surface_create (const char *filename, double width_in_points, double he
"dict\n"
" /type (PS) set\n"
" /filename ");
- _emit_string_literal (filename);
+ _emit_string_literal (filename, -1);
fprintf (logfile,
" set\n"
" /width %g set\n"
@@ -2993,7 +2997,7 @@ cairo_pdf_surface_create (const char *filename, double width_in_points, double h
"dict\n"
" /type (PDF) set\n"
" /filename ");
- _emit_string_literal (filename);
+ _emit_string_literal (filename, -1);
fprintf (logfile,
" set\n"
" /width %g set\n"
@@ -3058,7 +3062,7 @@ cairo_svg_surface_create (const char *filename, double width, double height)
"dict\n"
" /type (SVG) set\n"
" /filename ");
- _emit_string_literal (filename);
+ _emit_string_literal (filename, -1);
fprintf (logfile,
" set\n"
" /width %g set\n"
@@ -3129,7 +3133,7 @@ cairo_image_surface_create_from_png (const char *filename)
" /format //%s set\n"
" /filename ",
width, height, format_str);
- _emit_string_literal (filename);
+ _emit_string_literal (filename, -1);
fprintf (logfile,
" set\n"
" /source ");
@@ -3297,7 +3301,7 @@ cairo_script_surface_create (const char *filename,
"dict\n"
" /type (script) set\n"
" /filename ");
- _emit_string_literal (filename);
+ _emit_string_literal (filename, -1);
fprintf (logfile,
" set\n"
" /width %g set\n"
More information about the cairo-commit
mailing list