[gs-commits] ghostpdl branch, master, updated. jbig2dec-0.14-1932-ge0c2e4d

[email protected] (Robin Watts) Thu, 21 Nov 2019 20:21:37 +0000 (UTC)
Newsgroups gmane.comp.printing.ghostscript.cvs
Message-ID <[email protected]>
The ghostpdl branch, master has been updated
       via  e0c2e4d8f43d6e83a0a04e6d2c350d2d7fc1e7a6 (commit)
       via  23ea32bf2bd205c44c9a7979b3a187199e47da59 (commit)
       via  0c30c4cda3c2487ce52f79a952e3d0febef1d8bd (commit)
      from  7043e985298f75291e1fc25ad272140be31ffe6d (commit)

----------------------------------------------------------------------
commit e0c2e4d8f43d6e83a0a04e6d2c350d2d7fc1e7a6
Author: Robin Watts <[email protected]>
Date:   Thu Nov 21 18:45:55 2019 +0000

    gpdl: Fixup some warnings.

diff --git a/gpdl/gpdl.mak b/gpdl/gpdl.mak
index 9497810..9b1f33d 100644
--- a/gpdl/gpdl.mak
+++ b/gpdl/gpdl.mak
@@ -86,22 +86,23 @@ $(GPDL_PSI_TOP_OBJ): $(GPDLSRC)psitop.c $(AK) $(stdio__h)\
 # URF.
 $(GPDLOBJ)/$(GPDL_URF_TOP_OBJ_FILE): $(GPDLURFSRC)urftop.c $(AK)\
  $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(surfx_h) $(strimpl_h)\
- $(gscoord_h) $(pltop_h)
+ $(gscoord_h) $(pltop_h) $(gsicc_manage_h) $(gspaint_h) $(plmain_h)
 	$(GPDLCC) $(GPDLURFSRC)urftop.c $(GPDLO_)$(GPDL_URF_TOP_OBJ_FILE)
 
 $(GPDL_JPG_TOP_OBJ): $(GPDLSRC)jpgtop.c $(AK)\
  $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(strimpl_h) $(gscoord_h)\
- $(jpeglib_h) $(setjmp__h) $(sjpeg_h) $(pltop_h)
-	$(GPDLCC) $(II)$(JI_)$(_I) $(GPDLSRC)jpgtop.c $(GPDLO_)$(GPDL_JPG_TOP_OBJ_FILE)
+ $(jpeglib_h) $(setjmp__h) $(sjpeg_h) $(pltop_h) $(gsicc_manage_h)\
+ $(gspaint_h) $(plmain_h) $(jpeglib__h)
+	$(GPDLCC) $(I_)$(GLI_) $(II)$(JI_)$(_I) $(JCF_) $(GLF_) $(GPDLSRC)jpgtop.c $(GPDLO_)$(GPDL_JPG_TOP_OBJ_FILE)
 
 $(GPDL_PWG_TOP_OBJ): $(GPDLSRC)pwgtop.c $(AK)\
  $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(strimpl_h) $(gscoord_h)\
- $(spwgx_h) $(pltop_h)
+ $(spwgx_h) $(pltop_h) $(gsicc_manage_h) $(gspaint_h) $(plmain_h)
 	$(GPDLCC) $(GPDLSRC)pwgtop.c $(GPDLO_)$(GPDL_PWG_TOP_OBJ_FILE)
 
 $(GPDL_TIFF_TOP_OBJ): $(GPDLSRC)tifftop.c $(AK)\
  $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(strimpl_h) $(gscoord_h)\
- $(pltop_h)
+ $(pltop_h) $(gsicc_manage_h) $(gspaint_h) $(plmain_h)
 	$(GPDLCC) $(II)$(TI_)$(_I) $(GPDLSRC)tifftop.c $(GPDLO_)$(GPDL_TIFF_TOP_OBJ_FILE)
 
 $(GPDL_JBIG2_TOP_OBJ): $(GPDLSRC)jbig2top.c $(AK)\
diff --git a/gpdl/jpgtop.c b/gpdl/jpgtop.c
index c2b46ed..b01a835 100644
--- a/gpdl/jpgtop.c
+++ b/gpdl/jpgtop.c
@@ -22,6 +22,9 @@
 #include "gsstate.h"
 #include "strimpl.h"
 #include "gscoord.h"
+#include "gsicc_manage.h"
+#include "gspaint.h"
+#include "plmain.h"
 #include "jpeglib.h"
 #include "setjmp_.h"
 #include "sjpeg.h"
@@ -280,8 +283,6 @@ jpg_impl_process_file(pl_interp_implementation_t *impl, const char *filename)
 static int                      /* ret 0 or +ve if ok, else -ve error code */
 jpg_impl_process_begin(pl_interp_implementation_t * impl)
 {
-    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
-
     return 0;
 }
 
@@ -373,24 +374,6 @@ bytes_until_uel(const stream_cursor_read *pr)
     return pr->limit - pr->ptr;
 }
 
-static int
-get32be(stream_cursor_read *pr)
-{
-    int v = pr->ptr[1] << 24;
-    v |= pr->ptr[2] << 16;
-    v |= pr->ptr[3] << 8;
-    v |= pr->ptr[4];
-    pr->ptr += 4;
-
-    return v;
-}
-
-static int
-get8(stream_cursor_read *pr)
-{
-    return *++(pr->ptr);
-}
-
 static void
 jpg_jpeg_init_source(j_decompress_ptr cinfo)
 {
@@ -437,7 +420,7 @@ jpg_error_exit(j_common_ptr cinfo)
 static int
 fill_jpeg_source(jpg_interp_instance_t *jpg, stream_cursor_read * pr)
 {
-    size_t n = pr->limit - pr->ptr;
+    size_t n = bytes_until_uel(pr);
     size_t skip = jpg->bytes_to_skip;
 
     /* Skip any bytes we are supposed to be skipping. */
@@ -779,14 +762,7 @@ jpg_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr)
 static int
 jpg_impl_process_end(pl_interp_implementation_t * impl)
 {
-    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
-    int code = 0;
-
-    /* FIXME: */
-    if (code == gs_error_InterpreterExit || code == gs_error_NeedInput)
-        code = 0;
-
-    return code;
+    return 0;
 }
 
 /* Not implemented */
diff --git a/gpdl/pwgtop.c b/gpdl/pwgtop.c
index 1083508..c61fd31 100644
--- a/gpdl/pwgtop.c
+++ b/gpdl/pwgtop.c
@@ -20,9 +20,13 @@
 #include "gserrors.h"
 #include "gxdevice.h"
 #include "gsstate.h"
-#include "spwgx.h"
 #include "strimpl.h"
 #include "gscoord.h"
+#include "gsicc_manage.h"
+#include "gspaint.h"
+#include "plmain.h"
+#include "spwgx.h"
+#include "stream.h"
 
 /* Forward decls */
 
@@ -261,8 +265,6 @@ pwg_impl_process_file(pl_interp_implementation_t *impl, const char *filename)
 static int                      /* ret 0 or +ve if ok, else -ve error code */
 pwg_impl_process_begin(pl_interp_implementation_t * impl)
 {
-    pwg_interp_instance_t *pwg = (pwg_interp_instance_t *)impl->interp_client_data;
-
     return 0;
 }
 
@@ -367,12 +369,6 @@ get32be(stream_cursor_read *pr)
 }
 
 static int
-get8(stream_cursor_read *pr)
-{
-    return *++(pr->ptr);
-}
-
-static int
 pwg_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr)
 {
     pwg_interp_instance_t *pwg = (pwg_interp_instance_t *)impl->interp_client_data;
@@ -575,7 +571,9 @@ bad_header:
                                                                    &local_r, &local_w,
                                                                    true);
                 /* status = 0 => need data
-                 *          1 => need output space */
+                 *          1 => need output space
+                 * but we don't actually use this currently. */
+                (void)status;
                 /* Copy the updated pointer back */
                 pr->ptr = local_r.ptr;
                 if (local_w.ptr + 1 == pwg->stream_buffer)
@@ -644,6 +642,7 @@ pwg_impl_process_end(pl_interp_implementation_t * impl)
     pwg_interp_instance_t *pwg = (pwg_interp_instance_t *)impl->interp_client_data;
     int code = 0;
 
+    (void)pwg;
     /* FIXME: */
     if (code == gs_error_InterpreterExit || code == gs_error_NeedInput)
         code = 0;
diff --git a/gpdl/tifftop.c b/gpdl/tifftop.c
index ce1ca9a..bf14110 100644
--- a/gpdl/tifftop.c
+++ b/gpdl/tifftop.c
@@ -22,6 +22,9 @@
 #include "gsstate.h"
 #include "strimpl.h"
 #include "gscoord.h"
+#include "gsicc_manage.h"
+#include "gspaint.h"
+#include "plmain.h"
 #include "tiffio.h"
 
 /* Forward decls */
@@ -261,8 +264,6 @@ tiff_impl_process_file(pl_interp_implementation_t *impl, const char *filename)
 static int                      /* ret 0 or +ve if ok, else -ve error code */
 tiff_impl_process_begin(pl_interp_implementation_t * impl)
 {
-    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
-
     return 0;
 }
 
@@ -399,7 +400,7 @@ static toff_t tifsSeekProc(thandle_t tiff_, toff_t offset, int whence)
     return offset;
 }
 
-static tifsCloseProc(thandle_t tiff_)
+static int tifsCloseProc(thandle_t tiff_)
 {
     return 0;
 }
@@ -527,7 +528,6 @@ do_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr, int
             tiff->yresolution = (uint32_t)(f+0.5);
 
             if (TIFFIsTiled(tiff->handle)) {
-                int x, y;
                 tiff->samples = gs_alloc_bytes(tiff->memory, TIFFTileSize(tiff->handle), "tiff_tile");
             } else {
                 tiff->tile_width = tiff->width;
@@ -712,14 +712,7 @@ tiff_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr) {
 static int
 tiff_impl_process_end(pl_interp_implementation_t * impl)
 {
-    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
-    int code = 0;
-
-    /* FIXME: */
-    if (code == gs_error_InterpreterExit || code == gs_error_NeedInput)
-        code = 0;
-
-    return code;
+    return 0;
 }
 
 /* Not implemented */

----------------------------------------------------------------------
commit 23ea32bf2bd205c44c9a7979b3a187199e47da59
Author: Robin Watts <[email protected]>
Date:   Wed Nov 20 19:02:47 2019 +0000

    gpdl: Add 'jbig2' language implementation.

diff --git a/gpdl/gpdl.mak b/gpdl/gpdl.mak
index 7c674b7..9497810 100644
--- a/gpdl/gpdl.mak
+++ b/gpdl/gpdl.mak
@@ -38,7 +38,11 @@ GPDL_PWG_TOP_OBJ=$(GPDLOBJ)/$(GPDL_PWG_TOP_OBJ_FILE)
 GPDL_TIFF_TOP_OBJ_FILE=tifftop.$(OBJ)
 GPDL_TIFF_TOP_OBJ=$(GPDLOBJ)/$(GPDL_TIFF_TOP_OBJ_FILE)
 
+GPDL_JBIG2_TOP_OBJ_FILE=jbig2top.$(OBJ)
+GPDL_JBIG2_TOP_OBJ=$(GPDLOBJ)/$(GPDL_JBIG2_TOP_OBJ_FILE)
+
 GPDL_PSI_TOP_OBJS=\
+	$(GPDL_JBIG2_TOP_OBJ)\
 	$(GPDL_TIFF_TOP_OBJ)\
 	$(GPDL_PWG_TOP_OBJ)\
 	$(GPDL_JPG_TOP_OBJ)\
@@ -53,7 +57,8 @@ LANG_CFLAGS=\
 	$(ENABLE_URF)\
 	$(D_)JPG_INCLUDED$(_D)\
 	$(D_)PWG_INCLUDED$(_D)\
-	$(ENABLE_TIFF)
+	$(ENABLE_TIFF)\
+	$(D_)JBIG2_INCLUDED$(_D)
 
 GPDLCC=$(CC_) $(LANG_CFLAGS) $(I_)$(PSSRCDIR)$(_I) $(I_)$(PLSRCDIR)$(_I) $(I_)$(GLSRCDIR)$(_I) $(I_)$(DEVSRCDIR)$(_I) $(I_)$(GLGENDIR)$(_I) $(C_)
 
@@ -98,3 +103,8 @@ $(GPDL_TIFF_TOP_OBJ): $(GPDLSRC)tifftop.c $(AK)\
  $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(strimpl_h) $(gscoord_h)\
  $(pltop_h)
 	$(GPDLCC) $(II)$(TI_)$(_I) $(GPDLSRC)tifftop.c $(GPDLO_)$(GPDL_TIFF_TOP_OBJ_FILE)
+
+$(GPDL_JBIG2_TOP_OBJ): $(GPDLSRC)jbig2top.c $(AK)\
+ $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(strimpl_h) $(gscoord_h)\
+ $(pltop_h) $(gsicc_manage_h) $(gspaint_h) $(plmain_h)
+	$(GPDLCC) $(I_)$(LDF_JB2I_) $(JBIG2_CFLAGS) $(II)$(JB2I_)$(_I) $(GPDLSRC)jbig2top.c $(GPDLO_)$(GPDL_JBIG2_TOP_OBJ_FILE)
diff --git a/gpdl/jbig2top.c b/gpdl/jbig2top.c
new file mode 100644
index 0000000..4f87221
--- /dev/null
+++ b/gpdl/jbig2top.c
@@ -0,0 +1,814 @@
+/* Copyright (C) 2019 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.,  1305 Grant Avenue - Suite 200, Novato,
+   CA 94945, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* jbig2top.c */
+/* Top-level API implementation of "JBIG2" Language Interface */
+
+#include "pltop.h"
+#include "gserrors.h"
+#include "gxdevice.h"
+#include "gsstate.h"
+#include "strimpl.h"
+#include "gscoord.h"
+#include "gsicc_manage.h"
+#include "gspaint.h"
+#include "plmain.h"
+#ifdef USE_LDF_JB2
+#include <ldf_jb2.h>
+#else
+#include "jbig2.h"
+#endif
+
+/* Forward decls */
+
+/************************************************************/
+/******** Language wrapper implementation (see pltop.h) *****/
+/************************************************************/
+
+typedef enum
+{
+    ii_state_identifying = 0,
+    ii_state_jbig2,
+    ii_state_jbig2_start,
+    ii_state_jbig2_decode,
+    ii_state_flush
+} ii_state;
+
+/*
+ * JBig2 interpreter instance
+ */
+typedef struct jbig2_interp_instance_s {
+    gs_memory_t       *memory;
+    gs_memory_t       *cmemory;
+    gx_device         *dev;
+    gx_device         *nulldev;
+
+    gs_color_space    *gray;
+
+    /* JBig2 parser state machine */
+    ii_state           state;
+
+    gs_image_t         image;
+    gs_image_enum     *penum;
+    gs_gstate         *pgs;
+
+#ifdef USE_LDF_JB2
+    JB2_Handle_Document doc;
+    int                page;
+    size_t             buffer_full;
+    size_t             buffer_max;
+    byte              *jbig2_buffer;
+    size_t             file_pos;
+#else
+    Jbig2Ctx          *jbig_ctx;
+    struct _Jbig2Allocator allocator;
+#endif
+
+
+    byte              *samples;
+
+} jbig2_interp_instance_t;
+
+static int
+jbig2_detect_language(const char *s, int len)
+{
+    const byte *hdr = (const byte *)s;
+    if (len >= 8) {
+        if (hdr[0] == 0x97 &&
+            hdr[1] == 'J' &&
+            hdr[2] == 'B' &&
+            hdr[3] == '2' &&
+            hdr[4] == 0x0d &&
+            hdr[5] == 0x0a &&
+            hdr[6] == 0x1a &&
+            hdr[7] == 0x0a)
+            return 100;
+    }
+
+    return 0;
+}
+
+static const pl_interp_characteristics_t jbig2_characteristics = {
+    "JBIG2",
+    jbig2_detect_language,
+    "Artifex",
+    "0.01",
+    "18 Nov 2019",
+    1 /* minimum input size */
+};
+
+/* Get implementation's characteristics */
+static const pl_interp_characteristics_t * /* always returns a descriptor */
+jbig2_impl_characteristics(const pl_interp_implementation_t *impl)     /* implementation of interpreter to alloc */
+{
+  return &jbig2_characteristics;
+}
+
+static void
+jbig2_deallocate(jbig2_interp_instance_t *jbig2)
+{
+    if (jbig2 == NULL)
+        return;
+
+    rc_decrement_cs(jbig2->gray, "jbig2_deallocate");
+
+    if (jbig2->pgs != NULL)
+        gs_gstate_free_chain(jbig2->pgs);
+    gs_free_object(jbig2->memory, jbig2, "jbig2_impl_allocate_interp_instance");
+}
+
+/* Deallocate a interpreter instance */
+static int
+jbig2_impl_deallocate_interp_instance(pl_interp_implementation_t *impl)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)impl->interp_client_data;
+
+    jbig2_deallocate(jbig2);
+    impl->interp_client_data = NULL;
+
+    return 0;
+}
+
+/* Do per-instance interpreter allocation/init. */
+static int
+jbig2_impl_allocate_interp_instance(pl_interp_implementation_t *impl, gs_memory_t *mem)
+{
+    int code;
+    jbig2_interp_instance_t *jbig2
+        = (jbig2_interp_instance_t *)gs_alloc_bytes(mem,
+                                                  sizeof(jbig2_interp_instance_t),
+                                                  "jbig2_impl_allocate_interp_instance");
+    if (!jbig2)
+        return_error(gs_error_VMerror);
+    memset(jbig2, 0, sizeof(*jbig2));
+
+    jbig2->memory = mem;
+    jbig2->pgs = gs_gstate_alloc(mem);
+    if (jbig2->pgs == NULL)
+        goto failVM;
+
+    /* Push one save level onto the stack to assuage the memory handling */
+    code = gs_gsave(jbig2->pgs);
+    if (code < 0)
+        goto fail;
+
+    code = gsicc_init_iccmanager(jbig2->pgs);
+    if (code < 0)
+        goto fail;
+
+    jbig2->gray = gs_cspace_new_ICC(mem, jbig2->pgs, 1);
+
+    impl->interp_client_data = jbig2;
+
+    return 0;
+
+failVM:
+    code = gs_note_error(gs_error_VMerror);
+fail:
+    (void)jbig2_deallocate(jbig2);
+    return code;
+}
+
+/*
+ * Get the allocator with which to allocate a device
+ */
+static gs_memory_t *
+jbig2_impl_get_device_memory(pl_interp_implementation_t *impl)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)impl->interp_client_data;
+
+    return jbig2->dev ? jbig2->dev->memory : NULL;
+}
+
+/* Prepare interp instance for the next "job" */
+static int
+jbig2_impl_init_job(pl_interp_implementation_t *impl,
+                  gx_device                  *device)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)impl->interp_client_data;
+
+    jbig2->dev = device;
+    jbig2->state = ii_state_identifying;
+
+    return 0;
+}
+
+/* Do any setup for parser per-cursor */
+static int                      /* ret 0 or +ve if ok, else -ve error code */
+jbig2_impl_process_begin(pl_interp_implementation_t * impl)
+{
+    return 0;
+}
+
+/* Ensure we have 'required' bytes to read, and further ensure
+ * that we have no UEL's within those bytes. */
+static int
+ensure_bytes(jbig2_interp_instance_t *jpg, stream_cursor_read *pr, int required)
+{
+    int n;
+    const uint8_t *p = pr->ptr+1;
+    const uint8_t *q;
+    int avail;
+
+    /* Find out how many bytes we need to check */
+    n = pr->limit - pr->ptr;
+    if (n > required)
+        n = required;
+
+    /* Make sure there are no UELs in that block */
+    q = p + n;
+    while (p != q) {
+        while (p != q && *p != '\033')
+            p++;
+        if (p == q)
+            break;
+        avail = pr->limit - pr->ptr;
+        if (memcmp(p, "\033%-12345X", min(avail, 9)) == 0) {
+            /* At least a partial match to a UEL */
+            return avail < 9 ? gs_error_NeedInput : gs_error_InterpreterExit;
+        }
+        p++;
+    }
+
+    /* If we have enough bytes, great, if not, get some more */
+    return (n < required) ? gs_error_NeedInput : 0;
+}
+
+static int
+flush_to_uel(stream_cursor_read *pr)
+{
+    const uint8_t *p = pr->ptr+1;
+    const uint8_t *q = pr->limit+1;
+    int avail;
+
+    while (p != q) {
+        while (p != q && *p != '\033')
+            p++;
+        if (p == q)
+            break;
+        avail = pr->limit - pr->ptr;
+        if (memcmp(p, "\033%-12345X", min(avail, 9)) == 0) {
+            /* At least a partial match to a UEL. Bin everything to
+             * the start of the match. */
+            pr->ptr = p-1;
+            if (avail == 9) /* Complete match. Exit! */
+                return gs_error_InterpreterExit;
+            /* Partial match. Get more data. */
+            return gs_error_NeedInput;
+        }
+        p++;
+    }
+
+    pr->ptr = pr->limit;
+
+    return 0;
+}
+
+static int
+bytes_until_uel(const stream_cursor_read *pr)
+{
+    const uint8_t *p = pr->ptr+1;
+    const uint8_t *q = pr->limit+1;
+    int avail;
+
+    while (p != q) {
+        while (p != q && *p != '\033')
+            p++;
+        if (p == q)
+            break;
+        avail = pr->limit - pr->ptr;
+        if (memcmp(p, "\033%-12345X", min(avail, 9)) == 0) {
+            /* At least a partial match to a UEL. Everything up to
+             * the start of the match is up for grabs. */
+            return p - (pr->ptr+1);
+        }
+        p++;
+    }
+
+    return pr->limit - pr->ptr;
+}
+
+#ifdef USE_LDF_JB2
+static void * JB2_Callback my_lur_alloc(unsigned long  size,
+                                        void          *pParam)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)pParam;
+
+    return gs_alloc_bytes(jbig2->memory, size, "my_lur_alloc");
+}
+
+static JB2_Error JB2_Callback my_lur_free(void *ptr,
+                                          void *pParam)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)pParam;
+
+    gs_free_object(jbig2->memory, ptr, "my_lur_free");
+
+    return cJB2_Error_OK;
+}
+
+static void JB2_Callback my_lur_message(const char        *message,
+                                        JB2_Message_Level  level,
+                                        void              *messageParam)
+{
+    /* Just swallow messages for now */
+}
+
+static JB2_Size_T JB2_Callback my_lur_read(unsigned char *buffer,
+                                           JB2_Size_T     pos,
+                                           JB2_Size_T     size,
+                                           void           *readParam)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)readParam;
+    size_t avail;
+
+    if (pos < 0)
+        return 0;
+    if (pos > jbig2->buffer_full)
+        pos = jbig2->buffer_full;
+    avail = jbig2->buffer_full - pos;
+    if (avail > size)
+        avail = size;
+
+    memcpy(buffer, &jbig2->jbig2_buffer[pos], avail);
+
+    return (JB2_Size_T)avail;
+}
+
+static JB2_Error JB2_Callback my_output(unsigned char *buffer,
+                                        unsigned long  rownum,
+                                        unsigned long  width,
+                                        unsigned long  bps,
+                                        void          *param)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)param;
+    int code;
+    unsigned int used;
+
+    if (bps != 1)
+        return cJB2_Error_Failure_Output;
+
+    code = gs_image_next(jbig2->penum,
+                         buffer,
+                         (width+7)>>3,
+                         &used);
+
+    return (code < 0) ? cJB2_Error_Failure_Output : 0;
+
+}
+
+#else
+static void my_errors(void *data, const char *msg, Jbig2Severity severity, int32_t seg_idx)
+{
+    /* Do nothing */
+}
+
+static void *my_alloc(Jbig2Allocator *allocator, size_t size)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)(((char *)allocator)-offsetof(jbig2_interp_instance_t, allocator));
+
+    return gs_alloc_bytes(jbig2->memory, size, "jbig2(my_alloc)");
+}
+
+static void my_free(Jbig2Allocator *allocator, void *p)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)(((char *)allocator)-offsetof(jbig2_interp_instance_t, allocator));
+
+    gs_free_object(jbig2->memory, p, "jbig2(my_free)");
+}
+
+static void *my_realloc(Jbig2Allocator *allocator, void *p, size_t size)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)(((char *)allocator)-offsetof(jbig2_interp_instance_t, allocator));
+
+    return gs_resize_object(jbig2->memory, p, size, "jbig2(my_realloc)");
+}
+#endif
+
+static int
+do_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr, int eof)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)impl->interp_client_data;
+    int code = 0;
+    ii_state ostate = (ii_state)-1;
+    int bytes_left = 0;
+
+    while (jbig2->state != ostate || pr->limit - pr->ptr != bytes_left)
+    {
+        ostate = jbig2->state;
+        bytes_left = pr->limit - pr->ptr;
+        switch(jbig2->state)
+        {
+        case ii_state_identifying:
+        {
+            const byte *hdr;
+            /* Try and get us 8 bytes */
+            code = ensure_bytes(jbig2, pr, 8);
+            if (code < 0)
+                return code;
+            hdr = pr->ptr+1;
+            if (hdr[0] == 0x97 &&
+                hdr[1] == 'J' &&
+                hdr[2] == 'B' &&
+                hdr[3] == '2' &&
+                hdr[4] == 0x0d &&
+                hdr[5] == 0x0a &&
+                hdr[6] == 0x1a &&
+                hdr[7] == 0x0a) {
+                jbig2->state = ii_state_jbig2;
+                break;
+            }
+            jbig2->state = ii_state_flush;
+            break;
+        }
+        case ii_state_jbig2:
+        {
+            /* Gather data into a buffer */
+            int bytes = bytes_until_uel(pr);
+
+            if (bytes == 0 && pr->limit - pr->ptr > 9) {
+                /* No bytes until UEL, and there is space for a UEL in the buffer */
+                jbig2->state = ii_state_jbig2_start;
+                break;
+            }
+            if (bytes == 0 && eof) {
+                /* No bytes until UEL, and we are at eof */
+                jbig2->state = ii_state_jbig2_start;
+                break;
+            }
+
+#ifdef USE_LDF_JB2
+            /* For luratech, we need to gather all the data into a buffer.
+             * Once we've got it all, we drop to the next state and pass
+             * it in/decode it all at once. */
+            if (jbig2->buffer_full + bytes > jbig2->buffer_max) {
+                /* Need to expand our buffer */
+                size_t proposed = jbig2->buffer_full*2;
+                if (proposed == 0)
+                    proposed = 32768;
+                while (proposed < jbig2->buffer_full + bytes)
+                    proposed *= 2;
+
+                if (jbig2->jbig2_buffer == NULL) {
+                    jbig2->jbig2_buffer = gs_alloc_bytes(jbig2->memory, proposed, "jbig2_buffer");
+                    if (jbig2->jbig2_buffer == NULL) {
+                        jbig2->state = ii_state_flush;
+                        break;
+                    }
+                } else {
+                    void *new_buf = gs_resize_object(jbig2->memory, jbig2->jbig2_buffer, proposed, "jbig2_buffer");
+                    if (new_buf == NULL) {
+                        jbig2->state = ii_state_flush;
+                        break;
+                    }
+                    jbig2->jbig2_buffer = new_buf;
+                }
+                jbig2->buffer_max = proposed;
+            }
+
+            memcpy(&jbig2->jbig2_buffer[jbig2->buffer_full], pr->ptr+1, bytes);
+            jbig2->buffer_full += bytes;
+            pr->ptr += bytes;
+#else
+            if (jbig2->jbig_ctx == NULL) {
+                jbig2->allocator.alloc = &my_alloc;
+                jbig2->allocator.free = &my_free;
+                jbig2->allocator.realloc = &my_realloc;
+                jbig2->jbig_ctx = jbig2_ctx_new(&jbig2->allocator,
+                                                0, /* Options */
+                                                NULL, /* Global ctx */
+                                                &my_errors,
+                                                jbig2);
+                if (jbig2->jbig_ctx == NULL) {
+                    jbig2->state = ii_state_flush;
+                    break;
+                }
+            }
+            if (jbig2_data_in(jbig2->jbig_ctx, pr->ptr+1, bytes)) {
+                jbig2->state = ii_state_flush;
+                break;
+            }
+            pr->ptr += bytes;
+#endif
+            break;
+        }
+        case ii_state_jbig2_start:
+            /* This state exists so we can change back to it after
+             * a successful decode. It avoids the enclosing loop
+             * exiting after the first image of a jbig2 due to the
+             * state not having changed. We could avoid this by using
+             * a while loop in the "decode" state below, but that would
+             * make breaking harder. */
+            jbig2->state = ii_state_jbig2_decode;
+            break;
+        case ii_state_jbig2_decode:
+        {
+            float xext, yext, xoffset, yoffset, scale;
+            unsigned long y, w, h;
+            unsigned int used;
+#ifdef USE_LDF_JB2
+            JB2_Error error;
+
+            if (jbig2->doc == NULL) {
+                error = JB2_Document_Start(&jbig2->doc,
+                                           my_lur_alloc, jbig2->memory,
+                                           my_lur_free, jbig2->memory,
+                                           my_lur_read, jbig2,
+                                           my_lur_message, jbig2);
+#if defined(JB2_LICENSE_NUM_1) && defined(JB2_LICENSE_NUM_2)
+                if (error == cJB2_Error_OK) {
+                    /* set the license keys if appropriate */
+                    error = JB2_Document_Set_License(jbig2->doc,
+                                                     JB2_LICENSE_NUM_1,
+                                                     JB2_LICENSE_NUM_2);
+                }
+#endif
+                if (error != cJB2_Error_OK) {
+                    jbig2->state = ii_state_flush;
+                    break;
+                }
+            }
+            /* decode relevent image parameters */
+            error = JB2_Document_Set_Page(jbig2->doc, jbig2->page++);
+            if (error == cJB2_Error_Invalid_Index) {
+                /* Normal exit! */
+                jbig2->state = ii_state_flush;
+                break;
+            }
+            if (error == cJB2_Error_OK)
+                error = JB2_Document_Get_Property(jbig2->doc,
+                                                  cJB2_Prop_Page_Width,
+                                                  &w);
+            if (error == cJB2_Error_OK)
+                error = JB2_Document_Get_Property(jbig2->doc,
+                                                  cJB2_Prop_Page_Height,
+                                                  &h);
+            if (error != cJB2_Error_OK) {
+                jbig2->state = ii_state_flush;
+                break;
+            }
+#else
+            Jbig2Image *img = jbig2_page_out(jbig2->jbig_ctx);
+            if (img == NULL) {
+                jbig2->state = ii_state_flush;
+                break;
+            }
+            w = img->width;
+            h = img->height;
+#endif
+
+            /* Scale to fit, if too large. */
+            scale = 1.0f;
+            if (w * jbig2->dev->HWResolution[0] > jbig2->dev->width * 200)
+                scale = ((float)jbig2->dev->width * 200) / (w * jbig2->dev->HWResolution[0]);
+            if (scale * h * jbig2->dev->HWResolution[1] > jbig2->dev->height * 200)
+                scale = ((float)jbig2->dev->height * 200) / (h * jbig2->dev->HWResolution[1]);
+
+            jbig2->nulldev = gs_currentdevice(jbig2->pgs);
+            rc_increment(jbig2->nulldev);
+            code = gs_setdevice_no_erase(jbig2->pgs, jbig2->dev);
+            if (code < 0)
+                goto fail_during_decode;
+
+            code = gs_erasepage(jbig2->pgs);
+            if (code < 0)
+                goto fail_during_decode;
+
+            jbig2->penum = gs_image_enum_alloc(jbig2->memory, "jbig2_impl_process(penum)");
+            if (jbig2->penum == NULL) {
+                code = gs_note_error(gs_error_VMerror);
+                goto fail_during_decode;
+            }
+
+            /* Centre - Extents and offsets are all calculated in points (1/72 of an inch) */
+            xext = (((float)w) * 72 * scale / 200);
+            xoffset = (jbig2->dev->width * 72 / jbig2->dev->HWResolution[0] - xext)/2;
+            yext = (((float)h) * 72 * scale / 200);
+            yoffset = (jbig2->dev->height * 72 / jbig2->dev->HWResolution[1] - yext)/2;
+
+            gs_initmatrix(jbig2->pgs);
+
+            /* By default the ctm is set to:
+             *   xres/72   0
+             *   0         -yres/72
+             *   0         dev->height * yres/72
+             * i.e. it moves the origin from being top right to being bottom left.
+             * We want to move it back, as without this, the image will be displayed
+             * upside down.
+             */
+            code = gs_translate(jbig2->pgs, 0.0, jbig2->dev->height * 72 / jbig2->dev->HWResolution[1]);
+            if (code >= 0)
+                code = gs_translate(jbig2->pgs, xoffset, -yoffset);
+            if (code >= 0)
+                code = gs_scale(jbig2->pgs, scale, -scale);
+            if (code < 0)
+                goto fail_during_decode;
+
+            memset(&jbig2->image, 0, sizeof(jbig2->image));
+            gs_image_t_init(&jbig2->image, jbig2->gray);
+            jbig2->image.BitsPerComponent = 1;
+            jbig2->image.Width = w;
+            jbig2->image.Height = h;
+
+            jbig2->image.ImageMatrix.xx = 200.0f/72.0f;
+            jbig2->image.ImageMatrix.yy = 200.0f/72.0f;
+            jbig2->image.Decode[0] = 1.0f;
+            jbig2->image.Decode[1] = 0.0f;
+
+            code = gs_image_init(jbig2->penum,
+                                 &jbig2->image,
+                                 false,
+                                 false,
+                                 jbig2->pgs);
+            if (code < 0)
+                goto fail_during_decode;
+
+#ifdef USE_LDF_JB2
+            {
+                JB2_Scaling_Factor scale;
+                JB2_Rect rect;
+                scale.ulScaleUpFactor = 1;
+                scale.ulScaleDownFactor = 1;
+                rect.ulLeft = 0;
+                rect.ulRight = w;
+                rect.ulTop = 0;
+                rect.ulBottom = h;
+                error = JB2_Document_Decompress_Page(jbig2->doc,
+                                                     scale,
+                                                     rect,
+                                                     my_output,
+                                                     jbig2);
+                if (error != cJB2_Error_OK) {
+                    code = (error == cJB2_Error_Failure_Alloc) ?
+gs_error_VMerror : gs_error_unknownerror;
+                    goto fail_during_decode;
+                }
+            }
+#else
+            for (y = 0; y < img->height; y++) {
+                code = gs_image_next(jbig2->penum,
+                                     &img->data[y*img->stride],
+                                     (img->width+7)>>3,
+                                     &used);
+                if (code < 0)
+                    goto fail_during_decode;
+            }
+            jbig2_release_page(jbig2->jbig_ctx, img);
+#endif
+            code = gs_image_cleanup_and_free_enum(jbig2->penum, jbig2->pgs);
+            jbig2->penum = NULL;
+            if (code < 0) {
+                jbig2->state = ii_state_flush;
+                break;
+            }
+            (void)pl_finish_page(jbig2->memory->gs_lib_ctx->top_of_system,
+                                 jbig2->pgs, 1, true);
+            jbig2->state = ii_state_jbig2_start;
+            break;
+fail_during_decode:
+#ifdef USE_LDF_JB2
+#else
+            jbig2_release_page(jbig2->jbig_ctx, img);
+            jbig2->state = ii_state_flush;
+#endif
+            break;
+        }
+        default:
+        case ii_state_flush:
+
+#ifdef USE_LDF_JB2
+            if (jbig2->doc) {
+                JB2_Document_End(&jbig2->doc);
+                jbig2->doc = NULL;
+            }
+
+            if (jbig2->jbig2_buffer) {
+                gs_free_object(jbig2->memory, jbig2->jbig2_buffer, "jbig2_impl_process(jbig2_buffer)");
+                jbig2->jbig2_buffer = NULL;
+            }
+#else
+            if (jbig2->jbig_ctx) {
+                jbig2_ctx_free(jbig2->jbig_ctx);
+                jbig2->jbig_ctx = NULL;
+            }
+#endif
+
+            if (jbig2->penum) {
+                (void)gs_image_cleanup_and_free_enum(jbig2->penum, jbig2->pgs);
+                jbig2->penum = NULL;
+            }
+
+            /* We want to bin any data we get up to, but not including
+             * a UEL. */
+            return flush_to_uel(pr);
+        }
+    }
+
+    return code;
+}
+
+static int
+jbig2_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr) {
+    return do_impl_process(impl, pr, 0);
+}
+
+static int
+jbig2_impl_process_end(pl_interp_implementation_t * impl)
+{
+    return 0;
+}
+
+/* Not implemented */
+static int
+jbig2_impl_flush_to_eoj(pl_interp_implementation_t *impl, stream_cursor_read *cursor)
+{
+    const byte *p = cursor->ptr;
+    const byte *rlimit = cursor->limit;
+
+    /* Skip to, but leave UEL in buffer for PJL to find later */
+    for (; p < rlimit; ++p)
+        if (p[1] == '\033') {
+            uint avail = rlimit - p;
+
+            if (memcmp(p + 1, "\033%-12345X", min(avail, 9)))
+                continue;
+            if (avail < 9)
+                break;
+            cursor->ptr = p;
+            return 1;           /* found eoj */
+        }
+    cursor->ptr = p;
+    return 0;                   /* need more */
+}
+
+/* Parser action for end-of-file */
+static int
+jbig2_impl_process_eof(pl_interp_implementation_t *impl)
+{
+    stream_cursor_read r;
+
+    r.ptr = NULL;
+    r.limit = NULL;
+    return do_impl_process(impl, &r, 1);
+}
+
+/* Report any errors after running a job */
+static int
+jbig2_impl_report_errors(pl_interp_implementation_t *impl,          /* interp instance to wrap up job in */
+                        int                         code,          /* prev termination status */
+                        long                        file_position, /* file position of error, -1 if unknown */
+                        bool                        force_to_cout  /* force errors to cout */
+)
+{
+    return 0;
+}
+
+/* Wrap up interp instance after a "job" */
+static int
+jbig2_impl_dnit_job(pl_interp_implementation_t *impl)
+{
+    jbig2_interp_instance_t *jbig2 = (jbig2_interp_instance_t *)impl->interp_client_data;
+
+    if (jbig2->nulldev) {
+        int code = gs_setdevice(jbig2->pgs, jbig2->nulldev);
+        jbig2->dev = NULL;
+        rc_decrement(jbig2->nulldev, "jbig2_impl_dnit_job(nulldevice)");
+        jbig2->nulldev = NULL;
+        return code;
+    }
+    return 0;
+}
+
+/* Parser implementation descriptor */
+const pl_interp_implementation_t jbig2_implementation = {
+  jbig2_impl_characteristics,
+  jbig2_impl_allocate_interp_instance,
+  jbig2_impl_get_device_memory,
+  NULL, /* jbig2_impl_set_param */
+  NULL, /* jbig2_impl_add_path */
+  NULL, /* jbig2_impl_post_args_init */
+  jbig2_impl_init_job,
+  NULL, /* jbig2_impl_run_prefix_commands */
+  NULL, /* jbig2_impl_process_file */
+  jbig2_impl_process_begin,
+  jbig2_impl_process,
+  jbig2_impl_process_end,
+  jbig2_impl_flush_to_eoj,
+  jbig2_impl_process_eof,
+  jbig2_impl_report_errors,
+  jbig2_impl_dnit_job,
+  jbig2_impl_deallocate_interp_instance,
+  NULL
+};
diff --git a/pcl/pl/plimpl.c b/pcl/pl/plimpl.c
index fdbf8e9..ff2dba4 100644
--- a/pcl/pl/plimpl.c
+++ b/pcl/pl/plimpl.c
@@ -43,6 +43,8 @@ extern pl_interp_implementation_t pwg_implementation;
 
 extern pl_interp_implementation_t tiff_implementation;
 
+extern pl_interp_implementation_t jbig2_implementation;
+
 /* Zero-terminated list of pointers to implementations */
 pl_interp_implementation_t *pdl_implementations[] = {
     &pjl_implementation,
@@ -68,6 +70,9 @@ pl_interp_implementation_t *pdl_implementations[] = {
 #ifdef TIFF_INCLUDED
     &tiff_implementation,
 #endif
+#ifdef JBIG2_INCLUDED
+    &jbig2_implementation,
+#endif
     0
 };
 
diff --git a/windows/ghostpdl.vcproj b/windows/ghostpdl.vcproj
index 955d375..92694ae 100644
--- a/windows/ghostpdl.vcproj
+++ b/windows/ghostpdl.vcproj
@@ -306,6 +306,10 @@
 			Name="gpdl"
 			>
 			<File
+				RelativePath="..\gpdl\jbig2top.c"
+				>
+			</File>
+			<File
 				RelativePath="..\gpdl\jpgtop.c"
 				>
 			</File>

----------------------------------------------------------------------
commit 0c30c4cda3c2487ce52f79a952e3d0febef1d8bd
Author: Robin Watts <[email protected]>
Date:   Wed Nov 20 19:01:31 2019 +0000

    Remove some dead code/variables from tifftop.c

diff --git a/gpdl/tifftop.c b/gpdl/tifftop.c
index 2f55e1b..ce1ca9a 100644
--- a/gpdl/tifftop.c
+++ b/gpdl/tifftop.c
@@ -55,8 +55,6 @@ typedef struct tiff_interp_instance_s {
     /* Tiff parser state machine */
     ii_state           state;
 
-    int                pages;
-
     uint32_t           bpp;
     uint32_t           bpc;
     uint32_t           cs;
@@ -69,9 +67,6 @@ typedef struct tiff_interp_instance_s {
 
     uint32_t           num_comps;
     uint32_t           byte_width;
-    uint32_t           y;
-
-    uint32_t           bytes_available_on_entry;
 
     gs_image_t         image;
     gs_image_enum     *penum;
@@ -359,24 +354,6 @@ bytes_until_uel(const stream_cursor_read *pr)
     return pr->limit - pr->ptr;
 }
 
-static int
-get32be(stream_cursor_read *pr)
-{
-    int v = pr->ptr[1] << 24;
-    v |= pr->ptr[2] << 16;
-    v |= pr->ptr[3] << 8;
-    v |= pr->ptr[4];
-    pr->ptr += 4;
-
-    return v;
-}
-
-static int
-get8(stream_cursor_read *pr)
-{
-    return *++(pr->ptr);
-}
-
 static tmsize_t tifsReadProc(thandle_t  tiff_,
                              void      *buf,
                              tmsize_t   size)


Summary of changes:
 gpdl/gpdl.mak           |  23 +-
 gpdl/jbig2top.c         | 814 ++++++++++++++++++++++++++++++++++++++++++++++++
 gpdl/jpgtop.c           |  34 +-
 gpdl/pwgtop.c           |  19 +-
 gpdl/tifftop.c          |  40 +--
 pcl/pl/plimpl.c         |   5 +
 windows/ghostpdl.vcproj |   4 +
 7 files changed, 859 insertions(+), 80 deletions(-)
 create mode 100644 gpdl/jbig2top.c