diff options
Diffstat (limited to 'util/cairo-script/cairo-script-scanner.c')
-rw-r--r-- | util/cairo-script/cairo-script-scanner.c | 184 |
1 files changed, 142 insertions, 42 deletions
diff --git a/util/cairo-script/cairo-script-scanner.c b/util/cairo-script/cairo-script-scanner.c index eeec6861f..4254aa01e 100644 --- a/util/cairo-script/cairo-script-scanner.c +++ b/util/cairo-script/cairo-script-scanner.c @@ -38,10 +38,15 @@ #include <math.h> /* pow */ #include <stdio.h> /* EOF */ #include <stdint.h> /* for {INT,UINT}*_{MIN,MAX} */ +#include <stdlib.h> /* malloc/free */ #include <string.h> /* memset */ #include <assert.h> #include <zlib.h> +#if HAVE_LZO +#include <lzo/lzo2a.h> +#endif + #define DEBUG_SCAN 0 #if WORDS_BIGENDIAN @@ -124,7 +129,8 @@ fprintf_obj (FILE *stream, csi_t *ctx, const csi_object_t *obj) obj->datum.matrix->matrix.y0); break; case CSI_OBJECT_TYPE_STRING: - fprintf (stream, "string: len=%ld\n", obj->datum.string->len); + fprintf (stream, "string: len=%ld, defate=%ld, method=%d\n", + obj->datum.string->len, obj->datum.string->deflate, obj->datum.string->method); break; /* cairo */ @@ -799,6 +805,7 @@ string_read (csi_t *ctx, uint32_t u32; scan_read (scan, src, &u32, 4); obj->datum.string->deflate = be32 (u32); + obj->datum.string->method = compressed; } if (_csi_likely (len)) @@ -994,8 +1001,13 @@ scan_none: obj.type &= ~CSI_OBJECT_ATTR_EXECUTABLE; break; +#define STRING_LZO 154 + case STRING_LZO: + scan_read (scan, src, &u.u32, 4); + string_read (ctx, scan, src, be32 (u.u32), LZO, &obj); + break; + /* unassigned */ - case 154: case 155: case 156: case 157: @@ -1569,51 +1581,139 @@ _translate_string (csi_t *ctx, uint16_t u16; uint32_t u32; } u; - int len; + void *buf; + unsigned long hdr_len, buf_len, deflate; + int method; + + buf = string->string; + buf_len = string->len; + deflate = string->deflate; + method = string->method; + +#if HAVE_LZO + if (method == NONE && buf_len > 16) { + unsigned long mem_len = 2*string->len > LZO2A_999_MEM_COMPRESS ? 2*string->len : LZO2A_999_MEM_COMPRESS; + void *mem = malloc (mem_len); + void *work = malloc(LZO2A_999_MEM_COMPRESS); + + if (lzo2a_999_compress ((lzo_bytep) buf, buf_len, + (lzo_bytep) mem, &mem_len, + work) == 0 && + 8+2*mem_len < buf_len) + { + method = LZO; + deflate = buf_len; + buf_len = mem_len; + buf = mem; + } + else + { + free (mem); + } -#if WORDS_BIGENDIAN - if (string->len <= UINT8_MAX) { - hdr = STRING_1; - u.u8 = string->len; - len = 1; - } else if (string->len <= UINT16_MAX) { - hdr = STRING_2_MSB; - u.u16 = string->len; - len = 2; - } else { - hdr = STRING_4_MSB; - u.u32 = string->len; - len = 4; + free (work); } -#else - if (string->len <= UINT8_MAX) { - hdr = STRING_1; - u.u8 = string->len; - len = 1; - } else if (string->len <= UINT16_MAX) { - hdr = STRING_2_LSB; - u.u16 = string->len; - len = 2; - } else { - hdr = STRING_4_LSB; - u.u32 = string->len; - len = 4; +#if HAVE_ZLIB + if (method == ZLIB) { + buf_len = string->deflate; + buf = malloc (string->deflate); + if (uncompress ((Bytef *) buf, &buf_len, + (Bytef *) string->string, string->len) == Z_OK) + { + if (buf_len <= 8 + 2*string->len) { + method = NONE; + deflate = 0; + } else { + unsigned long mem_len = 2*string->deflate; + void *mem = malloc (mem_len); + void *work = malloc(LZO2A_999_MEM_COMPRESS); + + if (lzo2a_999_compress ((lzo_bytep) buf, buf_len, + (lzo_bytep) mem, &mem_len, + work) == 0) + { + if (8 + mem_len > buf_len) { + method = NONE; + deflate = 0; + } else { + free (buf); + method = LZO; + deflate = buf_len; + buf_len = mem_len; + buf = mem; + assert(deflate); + } + } + else + { + free (buf); + buf = string->string; + buf_len = string->len; + } + + free (work); + } + } + else + { + free (buf); + buf = string->string; + buf_len = string->len; + } } #endif - if (string->deflate) - hdr |= STRING_DEFLATE; - - closure->write_func (closure->closure, - (unsigned char *) &hdr, 1); - closure->write_func (closure->closure, - (unsigned char *) &u, len); - if (string->deflate) { - uint32_t u32 = to_be32 (string->deflate); - closure->write_func (closure->closure, - (unsigned char *) &u32, 4); +#endif + + if (method == LZO) { + hdr = STRING_LZO; + u.u32 = to_be32 (buf_len); + hdr_len = 4; + } else { +#if WORDS_BIGENDIAN + if (buf_len <= UINT8_MAX) { + hdr = STRING_1; + u.u8 = buf_len; + hdr_len = 1; + } else if (buf_len <= UINT16_MAX) { + hdr = STRING_2_MSB; + u.u16 = buf_len; + hdr_len = 2; + } else { + hdr = STRING_4_MSB; + u.u32 = buf_len; + hdr_len = 4; + } +#else + if (buf_len <= UINT8_MAX) { + hdr = STRING_1; + u.u8 = buf_len; + hdr_len = 1; + } else if (buf_len <= UINT16_MAX) { + hdr = STRING_2_LSB; + u.u16 = buf_len; + hdr_len = 2; + } else { + hdr = STRING_4_LSB; + u.u32 = buf_len; + hdr_len = 4; + } +#endif + if (deflate) { + assert (method == ZLIB); + hdr |= STRING_DEFLATE; + } } - closure->write_func (closure->closure, - (unsigned char *) string->string, string->len); + + closure->write_func (closure->closure, (unsigned char *) &hdr, 1); + closure->write_func (closure->closure, (unsigned char *) &u, hdr_len); + if (deflate) { + uint32_t u32 = to_be32 (deflate); + closure->write_func (closure->closure, (unsigned char *) &u32, 4); + } + closure->write_func (closure->closure, (unsigned char *) buf, buf_len); + + if (buf != string->string) + free (buf); return CSI_STATUS_SUCCESS; } |