[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