summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-07-23 17:05:28 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-07-23 17:05:28 +0100
commit9d7fd626c39c37368ea05f91a358899e5b5b898c (patch)
treec6ee9bc54659349e907d8cca0efcd4d7b2495891 /util
parent5d8f366581c0ca31fac76c991cb681d036af275f (diff)
[script] Decompress font sources
Need to decompress patterns and embedded bytecode before passing to fontconfig/FreeType.
Diffstat (limited to 'util')
-rw-r--r--util/cairo-script/cairo-script-operators.c119
1 files changed, 99 insertions, 20 deletions
diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c
index c447b942..04028374 100644
--- a/util/cairo-script/cairo-script-operators.c
+++ b/util/cairo-script/cairo-script-operators.c
@@ -42,6 +42,7 @@
#include <math.h>
#include <limits.h> /* INT_MAX */
#include <assert.h>
+#include <zlib.h>
#ifdef HAVE_MMAP
# ifdef HAVE_UNISTD_H
@@ -1535,6 +1536,7 @@ struct _ft_face_data {
csi_blob_t blob;
FT_Face face;
csi_string_t *source;
+ void *bytes;
cairo_font_face_t *font_face;
};
@@ -1560,6 +1562,9 @@ _ft_done_face (void *closure)
#endif
}
+ if (data->bytes != NULL)
+ _csi_free (ctx, data->bytes);
+
_csi_slab_free (ctx, data, sizeof (*data));
cairo_script_interpreter_destroy (ctx);
@@ -1567,28 +1572,39 @@ _ft_done_face (void *closure)
#ifdef HAVE_MMAP
/* manual form of swapping for swapless systems like tiny */
+struct mmap_vec {
+ const uint8_t *bytes;
+ size_t num_bytes;
+};
static void *
-_mmap_bytes (const uint8_t *bytes, size_t num_bytes)
+_mmap_bytes (const struct mmap_vec *vec, int count)
{
char template[] = "/tmp/csi-font.XXXXXX";
- size_t len;
void *ptr;
int fd;
+ int num_bytes;
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;
+ num_bytes = 0;
+ while (count--) {
+ const uint8_t *bytes = vec->bytes;
+ size_t len = vec->num_bytes;
+ while (len) {
+ int ret = write (fd, bytes, len);
+ if (ret < 0) {
+ close (fd);
+ return MAP_FAILED;
+ }
+ len -= ret;
+ bytes += ret;
}
- len -= ret;
- bytes += ret;
+
+ num_bytes += vec->num_bytes;
+ vec++;
}
ptr = mmap (NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);
@@ -1598,6 +1614,31 @@ _mmap_bytes (const uint8_t *bytes, size_t num_bytes)
}
#endif
+static void *
+inflate_string (csi_t *ctx, csi_string_t *src)
+{
+ uLongf len;
+ uint8_t *bytes;
+
+ len = src->deflate;
+ bytes = _csi_alloc (ctx, len + 1);
+ if (bytes == NULL)
+ return NULL;
+
+ if (uncompress ((Bytef *) bytes, &len,
+ (Bytef *) src->string, src->len) != Z_OK)
+ {
+ _csi_free (ctx, bytes);
+ bytes = NULL;
+ }
+ else
+ {
+ bytes[len] = '\0';
+ }
+
+ return bytes;
+}
+
static csi_status_t
_ft_create_for_source (csi_t *ctx,
csi_string_t *source,
@@ -1610,6 +1651,10 @@ _ft_create_for_source (csi_t *ctx,
FT_Error err;
cairo_font_face_t *font_face;
csi_status_t status;
+ struct mmap_vec vec[2];
+ int vec_count;
+ void *bytes;
+ int len;
/* check for an existing FT_Face (kept alive by the font cache) */
/* XXX index/flags */
@@ -1631,29 +1676,50 @@ _ft_create_for_source (csi_t *ctx,
}
data = _csi_slab_alloc (ctx, sizeof (*data));
+ data->bytes = NULL;
+ data->source = source;
+
+ vec[0].bytes = tmpl.bytes;
+ vec[0].num_bytes = tmpl.len;
+
+ if (source->deflate) {
+ len = source->deflate;
+ bytes = inflate_string (ctx, source);
+ if (_csi_unlikely (bytes == NULL))
+ return _csi_error (CSI_STATUS_NO_MEMORY);
+
+ vec[1].bytes = bytes;
+ vec[1].num_bytes = len;
+ data->bytes = bytes;
+ vec_count = 2;
+ } else {
+ bytes = tmpl.bytes;
+ len = tmpl.len;
+ vec_count = 1;
+ }
+
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);
+ data->blob.bytes = _mmap_bytes (vec, vec_count);
if (data->blob.bytes != MAP_FAILED) {
- data->source = NULL;
if (--source->base.ref == 0)
csi_string_free (ctx, source);
+
+ data->source = NULL;
+ data->bytes = NULL;
} 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,
- data->blob.bytes,
- data->blob.len,
+ bytes, len,
index,
&data->face);
if (_csi_unlikely (err != FT_Err_Ok)) {
@@ -1692,6 +1758,8 @@ _ft_create_for_pattern (csi_t *ctx,
cairo_font_face_t *font_face;
FcPattern *pattern;
csi_status_t status;
+ struct mmap_vec vec;
+ void *bytes;
_csi_blob_init (&tmpl, (uint8_t *) string->string, string->len);
link = _csi_list_find (ctx->_faces, _csi_blob_equal, &tmpl);
@@ -1703,9 +1771,17 @@ _ft_create_for_pattern (csi_t *ctx,
return CSI_STATUS_SUCCESS;
}
- pattern = FcNameParse ((FcChar8 *) string->string);
- if (_csi_unlikely (pattern == NULL))
- return _csi_error (CSI_STATUS_NO_MEMORY);
+ if (string->deflate) {
+ bytes = inflate_string (ctx, string);
+ if (_csi_unlikely (bytes == NULL))
+ return _csi_error (CSI_STATUS_NO_MEMORY);
+ } else {
+ bytes = tmpl.bytes;
+ }
+
+ pattern = FcNameParse (bytes);
+ if (bytes != tmpl.bytes)
+ _csi_free (ctx, bytes);
font_face = cairo_ft_font_face_create_for_pattern (pattern);
FcPatternDestroy (pattern);
@@ -1715,9 +1791,12 @@ _ft_create_for_pattern (csi_t *ctx,
data->ctx = cairo_script_interpreter_reference (ctx);
data->blob.hash = tmpl.hash;
data->blob.len = tmpl.len;
+ data->bytes = NULL;
data->face = NULL;
#ifdef HAVE_MMAP
- data->blob.bytes = _mmap_bytes (tmpl.bytes, tmpl.len);
+ vec.bytes = tmpl.bytes;
+ vec.num_bytes = tmpl.len;
+ data->blob.bytes = _mmap_bytes (&vec, 1);
if (data->blob.bytes != MAP_FAILED) {
data->source = NULL;
if (--string->base.ref == 0)