summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-01-08 12:19:33 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2013-01-08 15:01:37 +0000
commit146da77d85b304651949a819bc8b0a74819f0416 (patch)
tree85f5a9f199ef491782045935d39ff93dae1a40e6
parent5f2e89660d5e38d8e2682945962521958f150825 (diff)
downloadcairo-146da77d85b304651949a819bc8b0a74819f0416.tar.gz
script: Attempt to decompress images in place
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--perf/cairo-perf-trace.c16
-rw-r--r--util/cairo-script/cairo-script-interpreter.h7
-rw-r--r--util/cairo-script/cairo-script-operators.c391
3 files changed, 247 insertions, 167 deletions
diff --git a/perf/cairo-perf-trace.c b/perf/cairo-perf-trace.c
index bd0cb07d1..4b8c85eab 100644
--- a/perf/cairo-perf-trace.c
+++ b/perf/cairo-perf-trace.c
@@ -299,6 +299,19 @@ _similar_surface_create (void *closure,
return surface;
}
+static cairo_surface_t *
+_source_image_create (void *closure,
+ cairo_format_t format,
+ int width,
+ int height,
+ long uid)
+{
+ struct trace *args = closure;
+
+ return cairo_surface_create_similar_image (args->surface,
+ format, width, height);
+}
+
static cairo_t *
_context_create (void *closure,
cairo_surface_t *surface)
@@ -643,7 +656,8 @@ cairo_perf_trace (cairo_perf_t *perf,
_context_create,
NULL, /* context_destroy */
NULL, /* show_page */
- NULL /* copy_page */
+ NULL, /* copy_page */
+ _source_image_create,
};
args.tile_size = perf->tile_size;
diff --git a/util/cairo-script/cairo-script-interpreter.h b/util/cairo-script/cairo-script-interpreter.h
index bbdd15d38..27fb98661 100644
--- a/util/cairo-script/cairo-script-interpreter.h
+++ b/util/cairo-script/cairo-script-interpreter.h
@@ -65,6 +65,12 @@ typedef void
(*csi_copy_page_func_t) (void *closure,
cairo_t *cr);
+typedef cairo_surface_t *
+(*csi_create_source_image_t) (void *closure,
+ cairo_format_t format,
+ int width, int height,
+ long uid);
+
typedef struct _cairo_script_interpreter_hooks {
void *closure;
csi_surface_create_func_t surface_create;
@@ -73,6 +79,7 @@ typedef struct _cairo_script_interpreter_hooks {
csi_destroy_func_t context_destroy;
csi_show_page_func_t show_page;
csi_copy_page_func_t copy_page;
+ csi_create_source_image_t create_source_image;
} cairo_script_interpreter_hooks_t;
cairo_public cairo_script_interpreter_t *
diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c
index 9ba24f8fb..efc1970cf 100644
--- a/util/cairo-script/cairo-script-operators.c
+++ b/util/cairo-script/cairo-script-operators.c
@@ -2892,7 +2892,8 @@ _ifelse (csi_t *ctx)
}
static csi_status_t
-_image_read_raw (csi_file_t *src,
+_image_read_raw (csi_t *ctx,
+ csi_object_t *src,
cairo_format_t format,
int width, int height,
cairo_surface_t **image_out)
@@ -2902,20 +2903,34 @@ _image_read_raw (csi_file_t *src,
int rem, len, ret, x, rowlen, instride, stride;
cairo_status_t status;
- stride = cairo_format_stride_for_width (format, width);
- data = malloc (stride * height);
- if (data == NULL)
- return CAIRO_STATUS_NO_MEMORY;
+ if (width == 0 || height == 0) {
+ *image_out = cairo_image_surface_create (format, 0, 0);
+ return CSI_STATUS_SUCCESS;
+ }
- image = cairo_image_surface_create_for_data (data, format,
- width, height, stride);
- status = cairo_surface_set_user_data (image,
- (const cairo_user_data_key_t *) image,
- data, free);
- if (status) {
- cairo_surface_destroy (image);
- free (image);
- return status;
+ if (ctx->hooks.create_source_image != NULL) {
+ image = ctx->hooks.create_source_image (ctx->hooks.closure,
+ format, width, height,
+ 0);
+
+ stride = cairo_image_surface_get_stride (image);
+ data = cairo_image_surface_get_data (image);
+ } else {
+ stride = cairo_format_stride_for_width (format, width);
+ data = malloc (stride * height);
+ if (data == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ image = cairo_image_surface_create_for_data (data, format,
+ width, height, stride);
+ status = cairo_surface_set_user_data (image,
+ (const cairo_user_data_key_t *) image,
+ data, free);
+ if (status) {
+ cairo_surface_destroy (image);
+ free (image);
+ return status;
+ }
}
switch (format) {
@@ -2941,192 +2956,236 @@ _image_read_raw (csi_file_t *src,
}
len = rowlen * height;
- bp = data;
- rem = len;
- while (rem) {
- ret = csi_file_read (src, bp, rem);
- if (_csi_unlikely (ret == 0)) {
+ if (rowlen == instride &&
+ src->type == CSI_OBJECT_TYPE_STRING &&
+ len == src->datum.string->deflate)
+ {
+ csi_string_t *s = src->datum.string;
+ unsigned long out;
+
+ switch (s->method) {
+ default:
+ case NONE:
+err_decompress:
cairo_surface_destroy (image);
return _csi_error (CSI_STATUS_READ_ERROR);
+
+#if HAVE_ZLIB
+ case ZLIB:
+ if (uncompress ((Bytef *) data, &out,
+ (Bytef *) s->string, s->len) != Z_OK)
+ goto err_decompress;
+ break;
+#endif
+
+#if HAVE_LZO
+ case LZO:
+ if (lzo2a_decompress ((Bytef *) s->string, s->len,
+ (Bytef *) data, &out,
+ NULL))
+ goto err_decompress;
+ break;
+#endif
}
- rem -= ret;
- bp += ret;
}
+ else
+ {
+ csi_object_t file;
+
+ status = csi_object_as_file (ctx, src, &file);
+ if (_csi_unlikely (status)) {
+ cairo_surface_destroy (image);
+ return status;
+ }
+
+ bp = data;
+ rem = len;
+ while (rem) {
+ ret = csi_file_read (file.datum.file, bp, rem);
+ if (_csi_unlikely (ret == 0)) {
+ cairo_surface_destroy (image);
+ return _csi_error (CSI_STATUS_READ_ERROR);
+ }
+ rem -= ret;
+ bp += ret;
+ }
- if (len != height * stride) {
- while (--height) {
- uint8_t *row = data + height * stride;
+ if (len != height * stride) {
+ while (--height) {
+ uint8_t *row = data + height * stride;
+
+ /* XXX pixel conversion */
+ switch (format) {
+ case CAIRO_FORMAT_A1:
+ for (x = rowlen; x--; ) {
+ uint8_t byte = *--bp;
+ row[x] = CSI_BITSWAP8_IF_LITTLE_ENDIAN (byte);
+ }
+ break;
+ case CAIRO_FORMAT_A8:
+ for (x = width; x--; )
+ row[x] = *--bp;
+ break;
+ case CAIRO_FORMAT_RGB16_565:
+ for (x = width; x--; ) {
+#ifdef WORDS_BIGENDIAN
+ row[2*x + 1] = *--bp;
+ row[2*x + 0] = *--bp;
+#else
+ row[2*x + 0] = *--bp;
+ row[2*x + 1] = *--bp;
+#endif
+ }
+ break;
+ case CAIRO_FORMAT_RGB24:
+ for (x = width; x--; ) {
+#ifdef WORDS_BIGENDIAN
+ row[4*x + 3] = *--bp;
+ row[4*x + 2] = *--bp;
+ row[4*x + 1] = *--bp;
+ row[4*x + 0] = 0xff;
+#else
+ row[4*x + 0] = *--bp;
+ row[4*x + 1] = *--bp;
+ row[4*x + 2] = *--bp;
+ row[4*x + 3] = 0xff;
+#endif
+ }
+ break;
+ case CAIRO_FORMAT_RGB30:
+ case CAIRO_FORMAT_INVALID:
+ case CAIRO_FORMAT_ARGB32:
+ /* stride == width */
+ break;
+ }
- /* XXX pixel conversion */
+ memset (row + instride, 0, stride - instride);
+ }
+
+ /* need to treat last row carefully */
switch (format) {
case CAIRO_FORMAT_A1:
for (x = rowlen; x--; ) {
uint8_t byte = *--bp;
- row[x] = CSI_BITSWAP8_IF_LITTLE_ENDIAN (byte);
+ data[x] = CSI_BITSWAP8_IF_LITTLE_ENDIAN (byte);
}
break;
case CAIRO_FORMAT_A8:
for (x = width; x--; )
- row[x] = *--bp;
+ data[x] = *--bp;
break;
case CAIRO_FORMAT_RGB16_565:
for (x = width; x--; ) {
#ifdef WORDS_BIGENDIAN
- row[2*x + 1] = *--bp;
- row[2*x + 0] = *--bp;
+ data[2*x + 1] = *--bp;
+ data[2*x + 0] = *--bp;
#else
- row[2*x + 0] = *--bp;
- row[2*x + 1] = *--bp;
+ data[2*x + 0] = *--bp;
+ data[2*x + 1] = *--bp;
#endif
}
break;
case CAIRO_FORMAT_RGB24:
- for (x = width; x--; ) {
+ for (x = width; --x>1; ) {
#ifdef WORDS_BIGENDIAN
- row[4*x + 3] = *--bp;
- row[4*x + 2] = *--bp;
- row[4*x + 1] = *--bp;
- row[4*x + 0] = 0xff;
+ data[4*x + 3] = *--bp;
+ data[4*x + 2] = *--bp;
+ data[4*x + 1] = *--bp;
+ data[4*x + 0] = 0xff;
#else
- row[4*x + 0] = *--bp;
- row[4*x + 1] = *--bp;
- row[4*x + 2] = *--bp;
- row[4*x + 3] = 0xff;
+ data[4*x + 0] = *--bp;
+ data[4*x + 1] = *--bp;
+ data[4*x + 2] = *--bp;
+ data[4*x + 3] = 0xff;
#endif
}
- break;
- case CAIRO_FORMAT_RGB30:
- case CAIRO_FORMAT_INVALID:
- case CAIRO_FORMAT_ARGB32:
- /* stride == width */
- break;
- }
-
- memset (row + instride, 0, stride - instride);
- }
-
- /* need to treat last row carefully */
- switch (format) {
- case CAIRO_FORMAT_A1:
- for (x = rowlen; x--; ) {
- uint8_t byte = *--bp;
- data[x] = CSI_BITSWAP8_IF_LITTLE_ENDIAN (byte);
- }
- break;
- case CAIRO_FORMAT_A8:
- for (x = width; x--; )
- data[x] = *--bp;
- break;
- case CAIRO_FORMAT_RGB16_565:
- for (x = width; x--; ) {
+ if (width > 1) {
+ uint8_t rgb[2][3];
+ /* shuffle the last couple of overlapping pixels */
+ rgb[1][0] = data[5];
+ rgb[1][1] = data[4];
+ rgb[1][2] = data[3];
+ rgb[0][0] = data[2];
+ rgb[0][1] = data[1];
+ rgb[0][2] = data[0];
#ifdef WORDS_BIGENDIAN
- data[2*x + 1] = *--bp;
- data[2*x + 0] = *--bp;
+ data[4] = 0xff;
+ data[5] = rgb[1][2];
+ data[6] = rgb[1][1];
+ data[7] = rgb[1][0];
+ data[0] = 0xff;
+ data[1] = rgb[0][2];
+ data[2] = rgb[0][1];
+ data[3] = rgb[0][0];
#else
- data[2*x + 0] = *--bp;
- data[2*x + 1] = *--bp;
+ data[7] = 0xff;
+ data[6] = rgb[1][2];
+ data[5] = rgb[1][1];
+ data[4] = rgb[1][0];
+ data[3] = 0xff;
+ data[2] = rgb[0][2];
+ data[1] = rgb[0][1];
+ data[0] = rgb[0][0];
#endif
- }
- break;
- case CAIRO_FORMAT_RGB24:
- for (x = width; --x>1; ) {
-#ifdef WORDS_BIGENDIAN
- data[4*x + 3] = *--bp;
- data[4*x + 2] = *--bp;
- data[4*x + 1] = *--bp;
- data[4*x + 0] = 0xff;
-#else
- data[4*x + 0] = *--bp;
- data[4*x + 1] = *--bp;
- data[4*x + 2] = *--bp;
- data[4*x + 3] = 0xff;
-#endif
- }
- if (width > 1) {
- uint8_t rgb[2][3];
- /* shuffle the last couple of overlapping pixels */
- rgb[1][0] = data[5];
- rgb[1][1] = data[4];
- rgb[1][2] = data[3];
- rgb[0][0] = data[2];
- rgb[0][1] = data[1];
- rgb[0][2] = data[0];
-#ifdef WORDS_BIGENDIAN
- data[4] = 0xff;
- data[5] = rgb[1][2];
- data[6] = rgb[1][1];
- data[7] = rgb[1][0];
- data[0] = 0xff;
- data[1] = rgb[0][2];
- data[2] = rgb[0][1];
- data[3] = rgb[0][0];
-#else
- data[7] = 0xff;
- data[6] = rgb[1][2];
- data[5] = rgb[1][1];
- data[4] = rgb[1][0];
- data[3] = 0xff;
- data[2] = rgb[0][2];
- data[1] = rgb[0][1];
- data[0] = rgb[0][0];
-#endif
- } else {
+ } else {
#ifdef WORDS_BIGENDIAN
- data[0] = 0xff;
- data[1] = data[0];
- data[2] = data[1];
- data[3] = data[2];
+ data[0] = 0xff;
+ data[1] = data[0];
+ data[2] = data[1];
+ data[3] = data[2];
#else
- data[3] = data[0];
- data[0] = data[2];
- data[2] = data[3];
- data[3] = 0xff;
+ data[3] = data[0];
+ data[0] = data[2];
+ data[2] = data[3];
+ data[3] = 0xff;
#endif
+ }
+ break;
+ case CAIRO_FORMAT_RGB30:
+ case CAIRO_FORMAT_INVALID:
+ case CAIRO_FORMAT_ARGB32:
+ /* stride == width */
+ break;
}
- break;
- case CAIRO_FORMAT_RGB30:
- case CAIRO_FORMAT_INVALID:
- case CAIRO_FORMAT_ARGB32:
- /* stride == width */
- break;
- }
- memset (data + instride, 0, stride - instride);
- } else {
+ memset (data + instride, 0, stride - instride);
+ } else {
#ifndef WORDS_BIGENDIAN
- switch (format) {
- case CAIRO_FORMAT_A1:
- for (x = 0; x < len; x++) {
- uint8_t byte = data[x];
- data[x] = CSI_BITSWAP8_IF_LITTLE_ENDIAN (byte);
- }
- break;
- case CAIRO_FORMAT_RGB16_565:
- {
- uint32_t *rgba = (uint32_t *) data;
- for (x = len/2; x--; rgba++) {
- *rgba = bswap_16 (*rgba);
+ switch (format) {
+ case CAIRO_FORMAT_A1:
+ for (x = 0; x < len; x++) {
+ uint8_t byte = data[x];
+ data[x] = CSI_BITSWAP8_IF_LITTLE_ENDIAN (byte);
}
- }
- break;
- case CAIRO_FORMAT_ARGB32:
- {
- uint32_t *rgba = (uint32_t *) data;
- for (x = len/4; x--; rgba++) {
- *rgba = bswap_32 (*rgba);
+ break;
+ case CAIRO_FORMAT_RGB16_565:
+ {
+ uint32_t *rgba = (uint32_t *) data;
+ for (x = len/2; x--; rgba++) {
+ *rgba = bswap_16 (*rgba);
+ }
}
- }
- break;
+ break;
+ case CAIRO_FORMAT_ARGB32:
+ {
+ uint32_t *rgba = (uint32_t *) data;
+ for (x = len/4; x--; rgba++) {
+ *rgba = bswap_32 (*rgba);
+ }
+ }
+ break;
- case CAIRO_FORMAT_A8:
- break;
+ case CAIRO_FORMAT_A8:
+ break;
- case CAIRO_FORMAT_RGB30:
- case CAIRO_FORMAT_RGB24:
- case CAIRO_FORMAT_INVALID:
- default:
- break;
- }
+ case CAIRO_FORMAT_RGB30:
+ case CAIRO_FORMAT_RGB24:
+ case CAIRO_FORMAT_INVALID:
+ default:
+ break;
+ }
#endif
+ }
+ csi_object_free (ctx, &file);
}
cairo_surface_mark_dirty (image);
@@ -3303,22 +3362,22 @@ _image_load_from_dictionary (csi_t *ctx,
mime_type = MIME_TYPE_PNG;
}
- status = csi_object_as_file (ctx, &obj, &file);
- if (_csi_unlikely (status))
- return status;
/* XXX hook for general mime-type decoder */
switch (mime_type) {
case MIME_TYPE_NONE:
- status = _image_read_raw (file.datum.file,
- format, width, height, &image);
+ status = _image_read_raw (ctx, &obj, format, width, height, &image);
break;
case MIME_TYPE_PNG:
+ status = csi_object_as_file (ctx, &obj, &file);
+ if (_csi_unlikely (status))
+ return status;
+
status = _image_read_png (file.datum.file, &image);
+ csi_object_free (ctx, &file);
break;
}
- csi_object_free (ctx, &file);
if (_csi_unlikely (status))
return status;