[cairo-commit] 2 commits - build/configure.ac.system util/cairo-script

Chris Wilson ickle at kemper.freedesktop.org
Thu Jun 11 14:46:56 PDT 2009


 build/configure.ac.system                  |    3 
 util/cairo-script/cairo-script-file.c      |    5 -
 util/cairo-script/cairo-script-objects.c   |   27 ++++++++
 util/cairo-script/cairo-script-operators.c |   91 +++++++++++++++++++++++------
 util/cairo-script/cairo-script-private.h   |    6 +
 5 files changed, 114 insertions(+), 18 deletions(-)

New commits:
commit 3aaea453b0f0880d6c8825be21e67821732d1635
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 11 22:36:01 2009 +0100

    [script] Store fonts inside mmaped files.
    
    As an aide to tiny swapless systems write the rarely used bytes that
    define type42 fonts into a deleted file and mmap them back into our
    address space.

diff --git a/build/configure.ac.system b/build/configure.ac.system
index 341f5e9..1a01a42 100644
--- a/build/configure.ac.system
+++ b/build/configure.ac.system
@@ -62,6 +62,9 @@ AC_CHECK_HEADERS([fcntl.h unistd.h signal.h sys/stat.h sys/socket.h sys/poll.h s
 dnl check for CPU affinity support
 AC_CHECK_HEADERS([sched.h], [AC_CHECK_FUNCS([sched_getaffinity])])
 
+dnl check for mmap support
+AC_CHECK_HEADERS([sys/mman.h], [AC_CHECK_FUNCS([mmap])])
+
 dnl check for clock_gettime() support
 save_LIBS="$LIBS"
 LIBS="$LIBS $RT_LIBS"
diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c
index f311805..452243c 100644
--- a/util/cairo-script/cairo-script-operators.c
+++ b/util/cairo-script/cairo-script-operators.c
@@ -37,11 +37,16 @@
 #include "cairo-script-private.h"
 
 #include <stdio.h> /* snprintf */
+#include <stdlib.h> /* mkstemp */
 #include <string.h>
 #include <math.h>
 #include <limits.h> /* INT_MAX */
 #include <assert.h>
 
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
 typedef struct _csi_proxy {
     csi_t *ctx;
     void *ptr;
@@ -1541,13 +1546,53 @@ _ft_done_face (void *closure)
 
     ctx->_faces = _csi_list_unlink (ctx->_faces, &data->blob.list);
 
-    if (--data->source->base.ref == 0)
-	csi_string_free (ctx, data->source);
+    if (data->source != NULL) {
+	if (--data->source->base.ref == 0)
+	    csi_string_free (ctx, data->source);
+    } else {
+#ifdef HAVE_MMAP
+	munmap (data->blob.bytes, data->blob.len);
+#endif
+    }
+
     _csi_slab_free (ctx, data, sizeof (*data));
 
     cairo_script_interpreter_destroy (ctx);
 }
 
+#ifdef HAVE_MMAP
+/* manual form of swapping for swapless systems like tiny */
+static void *
+_mmap_bytes (const uint8_t *bytes, size_t num_bytes)
+{
+    char template[] = "/tmp/csi-font.XXXXXX";
+    size_t len;
+    void *ptr;
+    int fd;
+
+    fd = mkstemp (template);
+    if (fd == -1)
+	return MAP_FAILED;
+
+    unlink (template);
+    len = num_bytes;
+    while (len) {
+	int ret = write (fd, bytes, len);
+	if (ret < 0) {
+	    close (fd);
+	    return MAP_FAILED;
+	}
+	len -= ret;
+	bytes += ret;
+    }
+
+    ptr = mmap (NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);
+    close (fd);
+
+    return ptr;
+}
+#endif
+
 static csi_status_t
 _ft_create_for_source (csi_t *ctx,
 		       csi_string_t *source,
@@ -1557,7 +1602,6 @@ _ft_create_for_source (csi_t *ctx,
     csi_blob_t tmpl;
     struct _ft_face_data *data;
     csi_list_t *link;
-    FT_Face face;
     FT_Error err;
     cairo_font_face_t *font_face;
     csi_status_t status;
@@ -1581,27 +1625,42 @@ _ft_create_for_source (csi_t *ctx,
 	    return _csi_error (CSI_STATUS_NO_MEMORY);
     }
 
+    data = _csi_slab_alloc (ctx, sizeof (*data));
+    data->face = NULL;
+    ctx->_faces = _csi_list_prepend (ctx->_faces, &data->blob.list);
+    data->ctx = cairo_script_interpreter_reference (ctx);
+    data->blob.hash = tmpl.hash;
+    data->blob.len = tmpl.len;
+#ifdef HAVE_MMAP
+    data->blob.bytes = _mmap_bytes (tmpl.bytes, tmpl.len);
+    if (data->blob.bytes != MAP_FAILED) {
+	data->source = NULL;
+	if (--source->base.ref == 0)
+	    csi_string_free (ctx, source);
+    } else {
+	data->blob.bytes = tmpl.bytes;
+	data->source = source;
+    }
+#else
+    data->blob.bytes = tmpl.bytes;
+    data->source = source;
+#endif
+
     err = FT_New_Memory_Face (_ft_lib,
-			      (uint8_t *) source->string,
-			      source->len, index,
-			      &face);
+			      data->blob.bytes,
+			      data->blob.len,
+			      index,
+			      &data->face);
     if (_csi_unlikely (err != FT_Err_Ok)) {
+	_ft_done_face (data);
+
 	if (err == FT_Err_Out_Of_Memory)
 	    return _csi_error (CSI_STATUS_NO_MEMORY);
 
 	return _csi_error (CSI_STATUS_INVALID_SCRIPT);
     }
 
-    data = _csi_slab_alloc (ctx, sizeof (*data));
-    ctx->_faces = _csi_list_prepend (ctx->_faces, &data->blob.list);
-    data->ctx = cairo_script_interpreter_reference (ctx);
-    data->blob.hash = tmpl.hash;
-    data->blob.bytes = tmpl.bytes;
-    data->blob.len = tmpl.len;
-    data->face = face;
-    data->source = source;
-
-    font_face = cairo_ft_font_face_create_for_ft_face (face, load_flags);
+    font_face = cairo_ft_font_face_create_for_ft_face (data->face, load_flags);
     status = cairo_font_face_set_user_data (font_face,
 					    &_csi_blob_key,
 					    data, _ft_done_face);
commit 6167f27adfd530bdf091a0e7a3e0141d5db66f00
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 11 22:33:00 2009 +0100

    [script] Fix memleak of duplicated strings from files
    
    csi_string_new() duplicated the bytes which was not what was desired, so
    implement a csi_string_new_for_bytes() to take ownership and prevent the
    leak that was occuring, for example, every time we create a new font face.

diff --git a/util/cairo-script/cairo-script-file.c b/util/cairo-script/cairo-script-file.c
index 9a3ff70..a330d0b 100644
--- a/util/cairo-script/cairo-script-file.c
+++ b/util/cairo-script/cairo-script-file.c
@@ -993,7 +993,7 @@ _csi_file_as_string (csi_t *ctx,
 	    break;
 
 	len += ret;
-	if (len > allocated / 2) {
+	if (len + 1 > allocated / 2) {
 	    char *newbytes;
 	    int newlen;
 
@@ -1011,7 +1011,8 @@ _csi_file_as_string (csi_t *ctx,
 	}
     } while (TRUE);
 
-    status = csi_string_new (ctx, obj, bytes, len);
+    bytes[len] = '\0'; /* better safe than sorry! */
+    status = csi_string_new_from_bytes (ctx, obj, bytes, len);
     if (status) {
 	_csi_free (ctx, bytes);
 	return status;
diff --git a/util/cairo-script/cairo-script-objects.c b/util/cairo-script/cairo-script-objects.c
index 204e4b8..4ff39ec 100644
--- a/util/cairo-script/cairo-script-objects.c
+++ b/util/cairo-script/cairo-script-objects.c
@@ -559,6 +559,33 @@ csi_string_new (csi_t *ctx,
     return CSI_STATUS_SUCCESS;
 }
 
+csi_status_t
+csi_string_new_from_bytes (csi_t *ctx,
+	                   csi_object_t *obj,
+			   char *bytes,
+			   unsigned int len)
+{
+    csi_string_t *string;
+
+    if (_csi_unlikely (len >= INT_MAX))
+	return _csi_error (CSI_STATUS_NO_MEMORY);
+
+    string = _csi_slab_alloc (ctx, sizeof (csi_string_t));
+    if (_csi_unlikely (string == NULL))
+	return _csi_error (CSI_STATUS_NO_MEMORY);
+
+    string->string = bytes;
+    string->len = len;
+
+    string->base.type = CSI_OBJECT_TYPE_STRING;
+    string->base.ref = 1;
+
+    obj->type = CSI_OBJECT_TYPE_STRING;
+    obj->datum.string = string;
+
+    return CSI_STATUS_SUCCESS;
+}
+
 static inline csi_status_t
 _csi_string_execute (csi_t *ctx, csi_string_t *string)
 {
diff --git a/util/cairo-script/cairo-script-private.h b/util/cairo-script/cairo-script-private.h
index d177a29..d19737a 100644
--- a/util/cairo-script/cairo-script-private.h
+++ b/util/cairo-script/cairo-script-private.h
@@ -737,6 +737,12 @@ csi_string_new (csi_t *ctx,
 		const char *str,
 		int len);
 
+csi_private csi_status_t
+csi_string_new_from_bytes (csi_t *ctx,
+	                   csi_object_t *obj,
+			   char *bytes,
+			   unsigned int len);
+
 csi_private void
 csi_string_free (csi_t *ctx, csi_string_t *string);
 


More information about the cairo-commit mailing list