summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2014-05-13 15:16:59 +0100
committerTor Andersson <tor.andersson@artifex.com>2014-05-19 15:17:07 +0200
commit6a8abce9603f69b57e407f0df4044be919f507d7 (patch)
tree27b375d3e99ae1f2c23f8d893f9198a71a771a57
parent5faaa444cb08a19eb9eb932010bb70cb3e3423f4 (diff)
downloadmupdf-6a8abce9603f69b57e407f0df4044be919f507d7.tar.xz
Add an application agnostic memory handler for libjpeg
This adds a custom memory management layer between libjpeg and the calling app - in such a way that the code can be shared between mupdf and Ghostscript/PDL.
-rw-r--r--.gitattributes1
-rw-r--r--Makethird3
-rw-r--r--platform/android/jni/ThirdParty.mk1
-rw-r--r--platform/win32/libthirdparty.vcproj3
-rw-r--r--source/fitz/filter-dct.c70
-rw-r--r--source/fitz/jmemcust.c168
-rw-r--r--source/fitz/jmemcust.h56
-rw-r--r--source/fitz/load-jpeg.c62
8 files changed, 355 insertions, 9 deletions
diff --git a/.gitattributes b/.gitattributes
index 66254021..d48981b1 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -11,3 +11,4 @@ Make* tabs
*.xml tabs
memento.* spaces
*.vcxproj* spaces
+jmem* spaces
diff --git a/Makethird b/Makethird
index 73638699..10f3e23b 100644
--- a/Makethird
+++ b/Makethird
@@ -202,7 +202,6 @@ JPEG_SRC := \
jidctfst.c \
jidctint.c \
jmemmgr.c \
- jmemnobs.c \
jquant1.c \
jquant2.c \
jutils.c \
@@ -215,7 +214,7 @@ $(JPEG_OUT)/%.o: $(JPEG_DIR)/%.c | $(JPEG_OUT)
JPEG_CFLAGS := -Iscripts/jpeg -I$(JPEG_DIR)
else
-JPEG_CFLAGS := $(SYS_JPEG_CFLAGS)
+JPEG_CFLAGS := $(SYS_JPEG_CFLAGS) -DSHARE_JPEG
JPEG_LIBS := $(SYS_JPEG_LIBS)
endif
diff --git a/platform/android/jni/ThirdParty.mk b/platform/android/jni/ThirdParty.mk
index 91c6db18..7cde2a3d 100644
--- a/platform/android/jni/ThirdParty.mk
+++ b/platform/android/jni/ThirdParty.mk
@@ -97,7 +97,6 @@ LOCAL_SRC_FILES := \
$(MY_ROOT)/thirdparty/jpeg/jidctfst.c \
$(MY_ROOT)/thirdparty/jpeg/jidctint.c \
$(MY_ROOT)/thirdparty/jpeg/jmemmgr.c \
- $(MY_ROOT)/thirdparty/jpeg/jmemnobs.c \
$(MY_ROOT)/thirdparty/jpeg/jquant1.c \
$(MY_ROOT)/thirdparty/jpeg/jquant2.c \
$(MY_ROOT)/thirdparty/jpeg/jutils.c \
diff --git a/platform/win32/libthirdparty.vcproj b/platform/win32/libthirdparty.vcproj
index 0b56d346..bf2ace43 100644
--- a/platform/win32/libthirdparty.vcproj
+++ b/platform/win32/libthirdparty.vcproj
@@ -313,9 +313,6 @@
RelativePath="..\..\thirdparty\jpeg\jmemmgr.c"
>
</File>
- <File
- RelativePath="..\..\thirdparty\jpeg\jmemnobs.c"
- >
</File>
<File
RelativePath="..\..\thirdparty\jpeg\jquant1.c"
diff --git a/source/fitz/filter-dct.c b/source/fitz/filter-dct.c
index 86268032..b72c7ce6 100644
--- a/source/fitz/filter-dct.c
+++ b/source/fitz/filter-dct.c
@@ -1,6 +1,8 @@
#include "mupdf/fitz.h"
#include <jpeglib.h>
+typedef void * backing_store_ptr;
+#include "jmemcust.h"
#include <setjmp.h>
typedef struct fz_dctd_s fz_dctd;
@@ -26,9 +28,66 @@ struct fz_dctd_s
unsigned char buffer[4096];
};
+#ifdef SHARE_JPEG
+
+#define JZ_DCT_STATE_FROM_CINFO(c) (fz_dctd *)(c->client_data)
+
+#define fz_dct_mem_init(st)
+#define fz_dct_mem_term(st)
+
+#else /* SHARE_JPEG */
+
+#define JZ_DCT_STATE_FROM_CINFO(c) (fz_dctd *)(GET_CUST_MEM_DATA(c)->priv)
+
+static void *
+fz_dct_mem_alloc(j_common_ptr cinfo, size_t size)
+{
+ fz_dctd *state = JZ_DCT_STATE_FROM_CINFO(cinfo);
+ return fz_malloc(state->ctx, size);
+}
+
+static void
+fz_dct_mem_free(j_common_ptr cinfo, void *object, size_t size)
+{
+ fz_dctd *state = JZ_DCT_STATE_FROM_CINFO(cinfo);
+ UNUSED(size);
+ fz_free(state->ctx, object);
+}
+
+static void
+fz_dct_mem_init(fz_dctd *state)
+{
+ j_common_ptr cinfo = (j_common_ptr)&state->cinfo;
+ jpeg_cust_mem_data *custmptr;
+
+ custmptr = fz_malloc_struct(state->ctx, jpeg_cust_mem_data);
+
+ if (!jpeg_cust_mem_init(custmptr, (void *) state, NULL, NULL, NULL,
+ fz_dct_mem_alloc, fz_dct_mem_free,
+ fz_dct_mem_alloc, fz_dct_mem_free, NULL))
+ {
+ fz_free(state->ctx, custmptr);
+ fz_throw(state->ctx, FZ_ERROR_GENERIC, "cannot initialize custom JPEG memory handler");
+ }
+
+ cinfo->client_data = custmptr;
+}
+
+static void
+fz_dct_mem_term(fz_dctd *state)
+{
+ if(state->cinfo.client_data)
+ {
+ fz_free(state->ctx, state->cinfo.client_data);
+ state->cinfo.client_data = NULL;
+ }
+}
+
+#endif /* SHARE_JPEG */
+
static void error_exit(j_common_ptr cinfo)
{
- fz_dctd *state = cinfo->client_data;
+ fz_dctd *state = JZ_DCT_STATE_FROM_CINFO(cinfo);
cinfo->err->format_message(cinfo, state->msg);
longjmp(state->jb, 1);
}
@@ -46,11 +105,10 @@ static void term_source(j_decompress_ptr cinfo)
static boolean fill_input_buffer(j_decompress_ptr cinfo)
{
struct jpeg_source_mgr *src = cinfo->src;
- fz_dctd *state = cinfo->client_data;
+ fz_dctd *state = JZ_DCT_STATE_FROM_CINFO(cinfo);
fz_stream *curr_stm = state->curr_stm;
fz_context *ctx = curr_stm->ctx;
-
curr_stm->rp = curr_stm->wp;
fz_try(ctx)
{
@@ -115,6 +173,9 @@ next_dctd(fz_stream *stm, int max)
cinfo->err = &state->errmgr;
jpeg_std_error(cinfo->err);
cinfo->err->error_exit = error_exit;
+
+ fz_dct_mem_init(state);
+
jpeg_create_decompress(cinfo);
state->init = 1;
@@ -237,6 +298,8 @@ skip:
if (state->init)
jpeg_destroy_decompress(&state->cinfo);
+ fz_dct_mem_term(state);
+
fz_free(ctx, state->scanline);
fz_close(state->chain);
fz_close(state->jpegtables);
@@ -269,6 +332,7 @@ fz_open_dctd(fz_stream *chain, int color_transform, int l2factor, fz_stream *jpe
state->color_transform = color_transform;
state->init = 0;
state->l2factor = l2factor;
+ state->cinfo.client_data = NULL;
}
fz_catch(ctx)
{
diff --git a/source/fitz/jmemcust.c b/source/fitz/jmemcust.c
new file mode 100644
index 00000000..c8764509
--- /dev/null
+++ b/source/fitz/jmemcust.c
@@ -0,0 +1,168 @@
+/* Copyright (C) 2001-2014 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied,
+ modified or distributed except as expressly authorized under the terms
+ of the license contained in the file LICENSE in this distribution.
+
+ Refer to licensing information at http://www.artifex.com or contact
+ Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
+ CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+#if !defined(SHARE_JPEG) || SHARE_JPEG==0
+
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmorecfg.h"
+#include "jmemsys.h"
+#include "jerror.h"
+#include "jmemcust.h"
+
+GLOBAL(void *)
+jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+{
+ jpeg_cust_mem_data *cmem = GET_CUST_MEM_DATA(cinfo);
+
+ return (void *) (cmem->j_mem_get_small)(cinfo, sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
+{
+ jpeg_cust_mem_data *cmem = GET_CUST_MEM_DATA(cinfo);
+
+ (cmem->j_mem_free_small)(cinfo, object, sizeofobject);
+}
+
+/*
+ * "Large" objects are treated the same as "small" ones.
+ * NB: although we include FAR keywords in the routine declarations,
+ * this file won't actually work in 80x86 small/medium model; at least,
+ * you probably won't be able to process useful-size images in only 64KB.
+ */
+
+GLOBAL(void FAR *)
+jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+{
+ jpeg_cust_mem_data *cmem = GET_CUST_MEM_DATA(cinfo);
+
+ return (void *) (cmem->j_mem_get_large)(cinfo, sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
+{
+ jpeg_cust_mem_data *cmem = GET_CUST_MEM_DATA(cinfo);
+
+ (cmem->j_mem_free_large)(cinfo, object, sizeofobject);
+}
+
+/*
+ * This routine computes the total memory space available for allocation.
+ * Here we always say, "we got all you want bud!"
+ */
+
+GLOBAL(long)
+jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
+ long max_bytes_needed, long already_allocated)
+{
+ jpeg_cust_mem_data *cmem = GET_CUST_MEM_DATA(cinfo);
+ long ret = max_bytes_needed;
+
+ if (cmem->j_mem_avail)
+ ret = (cmem->j_mem_avail)(cinfo);
+
+ return ret;
+}
+
+/*
+ * Backing store (temporary file) management.
+ * Since jpeg_mem_available always promised the moon,
+ * this should never be called and we can just error out.
+ */
+
+GLOBAL(void)
+jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ jpeg_cust_mem_data *cmem = GET_CUST_MEM_DATA(cinfo);
+
+ if (cmem->j_mem_open_backing_store) {
+ (cmem->j_mem_open_backing_store)(cinfo, info, total_bytes_needed);
+ }
+ else
+ ERREXIT(cinfo, JERR_NO_BACKING_STORE);
+}
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required. Here, there isn't any.
+ */
+
+GLOBAL(long)
+jpeg_mem_init (j_common_ptr cinfo)
+{
+ jpeg_cust_mem_data *cmem = GET_CUST_MEM_DATA(cinfo);
+ long ret = 0;
+
+ if (cmem->j_mem_init)
+ ret = (cmem->j_mem_init)(cinfo);
+
+ return ret;
+}
+
+GLOBAL(void)
+jpeg_mem_term (j_common_ptr cinfo)
+{
+ jpeg_cust_mem_data *cmem = GET_CUST_MEM_DATA(cinfo);
+
+ if (cmem->j_mem_term)
+ (cmem->j_mem_term)(cinfo);
+}
+
+GLOBAL(jpeg_cust_mem_data *)
+jpeg_cust_mem_init(jpeg_cust_mem_data *custm, void *priv,
+ j_custmem_init_ptr init,
+ j_custmem_term_ptr term,
+ j_custmem_avail_ptr avail,
+ j_custmem_get_small_ptr get_small,
+ j_custmem_free_small_ptr free_small,
+ j_cust_mem_get_large_ptr get_large,
+ j_custmem_free_large_ptr free_large,
+ j_custmem_open_backing_store_ptr open_backing_store)
+{
+ jpeg_cust_mem_data *lcustm = NULL;
+
+ /* We need at least the following for a viable memory manager */
+ if (get_small && free_small && get_large && free_large)
+ {
+ lcustm = custm;
+
+ lcustm->priv = priv;
+ lcustm->j_mem_init = init;
+ lcustm->j_mem_term = term;
+ lcustm->j_mem_avail = avail;
+ lcustm->j_mem_get_small = get_small;
+ lcustm->j_mem_free_small = free_small;
+ lcustm->j_mem_get_large = get_large;
+ lcustm->j_mem_free_large = free_large;
+ lcustm->j_mem_open_backing_store = open_backing_store;
+ }
+ return lcustm;
+}
+
+GLOBAL(jpeg_cust_mem_data *)
+jpeg_cust_mem_set_private(jpeg_cust_mem_data *custm, void *priv)
+{
+ if (custm)
+ {
+ custm->priv = priv;
+ }
+ return custm;
+}
+
+#endif /* !defined(SHARE_JPEG) || SHARE_JPEG==0 */
diff --git a/source/fitz/jmemcust.h b/source/fitz/jmemcust.h
new file mode 100644
index 00000000..6371113e
--- /dev/null
+++ b/source/fitz/jmemcust.h
@@ -0,0 +1,56 @@
+/* Copyright (C) 2001-2014 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied,
+ modified or distributed except as expressly authorized under the terms
+ of the license contained in the file LICENSE in this distribution.
+
+ Refer to licensing information at http://www.artifex.com or contact
+ Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
+ CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+typedef JMETHOD(long, j_custmem_init_ptr, (j_common_ptr cinfo));
+typedef JMETHOD(void, j_custmem_term_ptr, (j_common_ptr cinfo));
+typedef JMETHOD(long, j_custmem_avail_ptr, (j_common_ptr cinfo));
+typedef JMETHOD(void *, j_custmem_get_small_ptr,
+ (j_common_ptr cinfo, size_t size));
+typedef JMETHOD(void, j_custmem_free_small_ptr,
+ (j_common_ptr cinfo, void *object, size_t size));
+typedef JMETHOD(void *, j_cust_mem_get_large_ptr,
+ (j_common_ptr cinfo, size_t size));
+typedef JMETHOD(void, j_custmem_free_large_ptr,
+ (j_common_ptr cinfo, void *object, size_t size));
+typedef JMETHOD(void, j_custmem_open_backing_store_ptr,
+ (j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed));
+
+typedef struct {
+ j_custmem_init_ptr j_mem_init;
+ j_custmem_term_ptr j_mem_term;
+ j_custmem_avail_ptr j_mem_avail;
+ j_custmem_get_small_ptr j_mem_get_small;
+ j_custmem_free_small_ptr j_mem_free_small;
+ j_cust_mem_get_large_ptr j_mem_get_large;
+ j_custmem_free_large_ptr j_mem_free_large;
+ j_custmem_open_backing_store_ptr j_mem_open_backing_store;
+ void *priv;
+} jpeg_cust_mem_data;
+
+#define GET_CUST_MEM_DATA(c) ((jpeg_cust_mem_data *)c->client_data)
+
+GLOBAL(jpeg_cust_mem_data *)
+jpeg_cust_mem_init(jpeg_cust_mem_data *custm, void *priv,
+ j_custmem_init_ptr init,
+ j_custmem_term_ptr term,
+ j_custmem_avail_ptr avail,
+ j_custmem_get_small_ptr get_small,
+ j_custmem_free_small_ptr free_small,
+ j_cust_mem_get_large_ptr get_large,
+ j_custmem_free_large_ptr free_large,
+ j_custmem_open_backing_store_ptr open_backing_store);
+
+GLOBAL(jpeg_cust_mem_data *)
+jpeg_cust_mem_set_private(jpeg_cust_mem_data *custm, void *priv);
diff --git a/source/fitz/load-jpeg.c b/source/fitz/load-jpeg.c
index f3bffd63..15e6e713 100644
--- a/source/fitz/load-jpeg.c
+++ b/source/fitz/load-jpeg.c
@@ -1,6 +1,65 @@
#include "mupdf/fitz.h"
#include <jpeglib.h>
+typedef void * backing_store_ptr;
+#include "jmemcust.h"
+
+#ifdef SHARE_JPEG
+
+#define JZ_CTX_FROM_CINFO(c) (fz_context *)(c->client_data)
+
+#define fz_jpg_mem_init(ctx, cinfo)
+#define fz_jpg_mem_term(cinfo)
+
+#else /* SHARE_JPEG */
+
+#define JZ_CTX_FROM_CINFO(c) (fz_context *)(GET_CUST_MEM_DATA(c)->priv)
+
+static void *
+fz_jpg_mem_alloc(j_common_ptr cinfo, size_t size)
+{
+ fz_context *ctx = JZ_CTX_FROM_CINFO(cinfo);
+ return fz_malloc(ctx, size);
+}
+
+static void
+fz_jpg_mem_free(j_common_ptr cinfo, void *object, size_t size)
+{
+ fz_context *ctx = JZ_CTX_FROM_CINFO(cinfo);
+ UNUSED(size);
+ fz_free(ctx, object);
+}
+
+static void
+fz_jpg_mem_init(fz_context *ctx, struct jpeg_decompress_struct *cinfo)
+{
+ jpeg_cust_mem_data *custmptr;
+
+ custmptr = fz_malloc_struct(ctx, jpeg_cust_mem_data);
+
+ if (!jpeg_cust_mem_init(custmptr, (void *) ctx, NULL, NULL, NULL,
+ fz_jpg_mem_alloc, fz_jpg_mem_free,
+ fz_jpg_mem_alloc, fz_jpg_mem_free, NULL))
+ {
+ fz_free(ctx, custmptr);
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cannot initialize custom JPEG memory handler");
+ }
+
+ cinfo->client_data = custmptr;
+}
+
+static void
+fz_jpg_mem_term(struct jpeg_decompress_struct *cinfo)
+{
+ if(cinfo->client_data)
+ {
+ fz_context *ctx = JZ_CTX_FROM_CINFO(cinfo);
+ fz_free(ctx, cinfo->client_data);
+ cinfo->client_data = NULL;
+ }
+}
+
+#endif /* SHARE_JPEG */
static void error_exit(j_common_ptr cinfo)
{
@@ -168,6 +227,8 @@ fz_load_jpeg_info(fz_context *ctx, unsigned char *rbuf, int rlen, int *xp, int *
cinfo.err = jpeg_std_error(&err);
err.error_exit = error_exit;
+ fz_jpg_mem_init(ctx, &cinfo);
+
jpeg_create_decompress(&cinfo);
cinfo.src = &src;
@@ -222,6 +283,7 @@ fz_load_jpeg_info(fz_context *ctx, unsigned char *rbuf, int rlen, int *xp, int *
fz_always(ctx)
{
jpeg_destroy_decompress(&cinfo);
+ fz_jpg_mem_term(&cinfo);
}
fz_catch(ctx)
{