shithub: jbig2

Download patch

ref: f5d16095a001e741bc8e570c0e231e65e831ea47
parent: e20979d9e27342a2e5d54f12702e038df015de01
author: Robin Watts <Robin.Watts@artifex.com>
date: Wed Feb 5 06:53:57 EST 2020

jbig2dec: Simplify jbig2_arith_decode.

Previously we passed in an int * to get errors back, and
used the return code for 0 or 1. Now we use the return code
for 0, 1 or -ve for error.

This saves between 1% and 2% of gs runtime for decoding
tests/pdf/Jbig2_042_06.pdf.

--- a/jbig2_arith.c
+++ b/jbig2_arith.c
@@ -61,6 +61,23 @@
 
     /* invariant: as->next_word_bytes > 0 */
 
+    /* This code confused me no end when I first read it, so a quick note
+     * to save others (and future me's) from being similarly confused.
+     * 'next_word' does indeed contain 'next_word_bytes' of valid data
+     * (always starting at the most significant byte). The confusing
+     * thing is that the first byte has always already been read.
+     * i.e. it serves only as an indication that the last byte we read
+     * was FF or not.
+     *
+     * The jbig2 bytestream uses FF bytes, followed by a byte > 0x8F as
+     * marker bytes. These never occur in normal streams of arithmetic
+     * encoding, so meeting one terminates the stream (with an infinite
+     * series of 1 bits).
+     *
+     * If we meet an FF byte, we return it as normal. We just 'remember'
+     * that fact for the next byte we read.
+     */
+
     /* Figure G.3 */
     B = (byte)((as->next_word >> 24) & 0xFF);
     if (B == 0xFF) {
@@ -231,8 +248,8 @@
     } while ((as->A & 0x8000) == 0);
 }
 
-bool
-jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx, int *code)
+int
+jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx)
 {
     Jbig2ArithCx cx = *pcx;
     const Jbig2ArithQe *pqe;
@@ -239,19 +256,14 @@
     unsigned int index = cx & 0x7f;
     bool D;
 
-    if (index >= MAX_QE_ARRAY_SIZE) {
-        *code = -1;
-        return 0;
-    } else {
-        pqe = &jbig2_arith_Qe[index];
-    }
+    if (index >= MAX_QE_ARRAY_SIZE)
+        return -1; /* Error */
 
+    pqe = &jbig2_arith_Qe[index];
+
     /* Figure E.15 */
     as->A -= pqe->Qe;
-    if (
-        /* Note: I do not think this is correct. See above. */
-        (as->C >> 16) < as->A
-    ) {
+    if ((as->C >> 16) < as->A) {
         if ((as->A & 0x8000) == 0) {
             /* MPS_EXCHANGE, Figure E.16 */
             if (as->A < pqe->Qe) {
@@ -262,10 +274,8 @@
                 *pcx ^= pqe->mps_xor;
             }
             jbig2_arith_renormd(as);
-            *code = 0;
             return D;
         } else {
-            *code = 0;
             return cx >> 7;
         }
     } else {
@@ -281,7 +291,6 @@
             *pcx ^= pqe->lps_xor;
         }
         jbig2_arith_renormd(as);
-        *code = 0;
         return D;
     }
 }
@@ -342,7 +351,6 @@
     Jbig2ArithState *as;
     int i;
     Jbig2ArithCx cx = 0;
-    int code;
 
     ctx = jbig2_ctx_new(NULL, 0, NULL, NULL, NULL);
 
@@ -358,7 +366,7 @@
 #else
         (void)
 #endif
-            jbig2_arith_decode(as, &cx, &code);
+            jbig2_arith_decode(as, &cx);
 
 #ifdef JBIG2_DEBUG_ARITH
         fprintf(stderr, "%3d: D = %d, ", i, D);
--- a/jbig2_arith.h
+++ b/jbig2_arith.h
@@ -31,7 +31,8 @@
 Jbig2ArithState *jbig2_arith_new(Jbig2Ctx *ctx, Jbig2WordStream *ws);
 
 /* decode a bit */
-bool jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx, int *code);
+/* Normally returns 0 or 1. May return negative in case of error. */
+int jbig2_arith_decode(Jbig2ArithState *as, Jbig2ArithCx *pcx);
 
 /* returns true if the end of the data stream has been reached (for sanity checks) */
 bool jbig2_arith_has_reached_marker(Jbig2ArithState *as);
--- a/jbig2_arith_iaid.c
+++ b/jbig2_arith_iaid.c
@@ -75,12 +75,11 @@
     int PREV = 1;
     int D;
     int i;
-    int code = 0;
 
     /* A.3 (2) */
     for (i = 0; i < SBSYMCODELEN; i++) {
-        D = jbig2_arith_decode(as, &IAIDx[PREV], &code);
-        if (code)
+        D = jbig2_arith_decode(as, &IAIDx[PREV]);
+        if (D < 0)
             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAIDx code");
 #ifdef VERBOSE
         fprintf(stderr, "IAID%x: D = %d\n", PREV, D);
--- a/jbig2_arith_int.c
+++ b/jbig2_arith_int.c
@@ -70,38 +70,37 @@
     int bit;
     int n_tail, offset;
     int i;
-    int code = 0;
 
-    S = jbig2_arith_decode(as, &IAx[PREV], &code);
-    if (code)
+    S = jbig2_arith_decode(as, &IAx[PREV]);
+    if (S < 0)
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx S");
     PREV = (PREV << 1) | S;
 
-    bit = jbig2_arith_decode(as, &IAx[PREV], &code);
-    if (code)
+    bit = jbig2_arith_decode(as, &IAx[PREV]);
+    if (bit < 0)
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx decision bit 0");
     PREV = (PREV << 1) | bit;
     if (bit) {
-        bit = jbig2_arith_decode(as, &IAx[PREV], &code);
-        if (code)
+        bit = jbig2_arith_decode(as, &IAx[PREV]);
+        if (bit < 0)
             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx decision bit 1");
         PREV = (PREV << 1) | bit;
 
         if (bit) {
-            bit = jbig2_arith_decode(as, &IAx[PREV], &code);
-            if (code)
+            bit = jbig2_arith_decode(as, &IAx[PREV]);
+            if (bit < 0)
                 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx decision bit 2");
             PREV = (PREV << 1) | bit;
 
             if (bit) {
-                bit = jbig2_arith_decode(as, &IAx[PREV], &code);
-                if (code)
+                bit = jbig2_arith_decode(as, &IAx[PREV]);
+                if (bit < 0)
                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx decision bit 3");
                 PREV = (PREV << 1) | bit;
 
                 if (bit) {
-                    bit = jbig2_arith_decode(as, &IAx[PREV], &code);
-                    if (code)
+                    bit = jbig2_arith_decode(as, &IAx[PREV]);
+                    if (bit < 0)
                         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx decision bit 4");
                     PREV = (PREV << 1) | bit;
 
@@ -131,8 +130,8 @@
 
     V = 0;
     for (i = 0; i < n_tail; i++) {
-        bit = jbig2_arith_decode(as, &IAx[PREV], &code);
-        if (code)
+        bit = jbig2_arith_decode(as, &IAx[PREV]);
+        if (bit < 0)
             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode IAx V bit %d", i);
         PREV = ((PREV << 1) & 511) | (PREV & 256) | bit;
         V = (V << 1) | bit;
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -391,7 +391,6 @@
         uint32_t line_m1;
         uint32_t line_m2;
         uint32_t padded_width = (GBW + 7) & -8;
-        int code = 0;
 
         line_m1 = line1 ? line1[0] : 0;
         line_m2 = line2 ? line2[0] << 6 : 0;
@@ -411,10 +410,10 @@
 
             /* This is the speed-critical inner loop. */
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
-                bool bit;
+                int bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                if (code)
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                if (bit < 0)
                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 optimized");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x7bf7) << 1) | bit | ((line_m1 >> (7 - x_minor)) & 0x10) | ((line_m2 >> (7 - x_minor)) & 0x800);
@@ -444,8 +443,7 @@
     const uint32_t GBH = image->height;
     uint32_t CONTEXT;
     uint32_t x, y;
-    bool bit;
-    int code = 0;
+    int bit;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]) ||
         pixel_outside_field(params->gbat[2], params->gbat[3]) ||
@@ -483,8 +481,8 @@
                 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], y + params->gbat[5]) << 11;
                 CONTEXT |= (ppd>>2) & 0x7000; /* Next 3 pixels */
                 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], y + params->gbat[7]) << 15;
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                if (code)
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                if (bit < 0)
                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 unoptimized");
             }
             pd = pd<<1;
@@ -517,8 +515,7 @@
     const uint32_t GBH = image->height;
     uint32_t CONTEXT;
     uint32_t x, y;
-    bool bit;
-    int code = 0;
+    int bit;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]))
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -550,8 +547,8 @@
                 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 3;
                 CONTEXT |= (pd>>9) & 0x01F0; /* Next 5 pixels */
                 CONTEXT |= (ppd>>4) & 0x1E00; /* Next 4 pixels */
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                if (code)
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                if (bit < 0)
                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 unoptimized");
             }
             pd = pd<<1;
@@ -587,7 +584,6 @@
     byte *line2 = NULL;
     byte *line1 = NULL;
     byte *gbreg_line = (byte *) image->data;
-    int code = 0;
 
 #ifdef OUTPUT_PBM
     printf("P4\n%d %d\n", GBW, GBH);
@@ -620,10 +616,10 @@
 
             /* This is the speed-critical inner loop. */
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
-                bool bit;
+                int bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                if (code)
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                if (bit < 0)
                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 optimized");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0xefb) << 1) | bit | ((line_m1 >> (8 - x_minor)) & 0x8) | ((line_m2 >> (8 - x_minor)) & 0x200);
@@ -650,8 +646,7 @@
     const uint32_t GBH = image->height;
     uint32_t CONTEXT;
     uint32_t x, y;
-    bool bit;
-    int code = 0;
+    int bit;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]))
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -683,8 +678,8 @@
                 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 2;
                 CONTEXT |= (pd>>11) & 0x078; /* Next 4 pixels */
                 CONTEXT |= (ppd>>7) & 0x380; /* Next 3 pixels */
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                if (code)
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                if (bit < 0)
                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 unoptimized");
             }
             pd = pd<<1;
@@ -721,7 +716,6 @@
     byte *line2 = NULL;
     byte *line1 = NULL;
     byte *gbreg_line = (byte *) image->data;
-    int code = 0;
 
 #ifdef OUTPUT_PBM
     printf("P4\n%d %d\n", GBW, GBH);
@@ -754,10 +748,10 @@
 
             /* This is the speed-critical inner loop. */
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
-                bool bit;
+                int bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                if (code)
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                if (bit < 0)
                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 optimized");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x1bd) << 1) | bit | ((line_m1 >> (10 - x_minor)) & 0x4) | ((line_m2 >> (10 - x_minor)) & 0x80);
@@ -786,7 +780,6 @@
     byte *line1 = NULL;
     byte *gbreg_line = (byte *) image->data;
     uint32_t x, y;
-    int code;
 
 #ifdef OUTPUT_PBM
     printf("P4\n%d %d\n", GBW, GBH);
@@ -814,10 +807,10 @@
 
             /* This is the speed-critical inner loop. */
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
-                bool bit;
+                int bit;
 
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                if (code)
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                if (bit < 0)
                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 optimized");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x1f7) << 1) | bit | ((line_m1 >> (8 - x_minor)) & 0x10);
@@ -843,8 +836,7 @@
     const uint32_t GBH = image->height;
     uint32_t CONTEXT;
     uint32_t x, y;
-    bool bit;
-    int code = 0;
+    int bit;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]))
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -868,8 +860,8 @@
                 CONTEXT  = out_byte & 0x00F; /* First 4 pixels */
                 CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
                 CONTEXT |= (pd>>9) & 0x3E0; /* Next 5 pixels */
-                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                if (code)
+                bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                if (bit < 0)
                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 unoptimized");
             }
             pd = pd<<1;
@@ -912,9 +904,7 @@
     const uint32_t GBH = image->height;
     uint32_t CONTEXT;
     uint32_t x, y;
-    bool bit;
     int LTP = 0;
-    int code = 0;
     int gmin, gmax;
     uint32_t left, right, top;
 
@@ -935,9 +925,10 @@
         params->gbat[6] == -2 && params->gbat[7] == -2)
     {
         for (y = 0; y < GBH; y++) {
-            LTP ^= jbig2_arith_decode(as, &GB_stats[0x9B25], &code);
-            if (code)
+            int bit = jbig2_arith_decode(as, &GB_stats[0x9B25]);
+            if (bit < 0)
                 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON1");
+            LTP ^= bit;
             if (!LTP) {
                 uint32_t out_byte = 0;
                 int out_bits_to_go_in_byte = 8;
@@ -963,8 +954,8 @@
                         CONTEXT  = out_byte & 0x00F; /* First 4 pixels */
                         CONTEXT |= (pd>>8) & 0x7F0; /* Next 7 pixels */
                         CONTEXT |= (ppd>>2) & 0xF800; /* Final 5 pixels */
-                        bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                        if (code)
+                        bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                        if (bit < 0)
                             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
                     }
                     pd = pd<<1;
@@ -1032,9 +1023,10 @@
     /* So 0 <= y < top needs bounds checking. */
 
     for (y = 0; y < GBH; y++) {
-        LTP ^= jbig2_arith_decode(as, &GB_stats[0x9B25], &code);
-        if (code)
+        int bit = jbig2_arith_decode(as, &GB_stats[0x9B25]);
+        if (bit < 0)
             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON1");
+        LTP ^= bit;
         if (!LTP) {
             uint32_t out_byte = 0;
             int out_bits_to_go_in_byte = 8;
@@ -1074,8 +1066,8 @@
                         CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4], y + params->gbat[5]) << 11;
                         CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], y + params->gbat[7]) << 15;
                     }
-                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                    if (code)
+                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                    if (bit < 0)
                         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
                 }
                 pd = pd<<1;
@@ -1112,9 +1104,7 @@
     const uint32_t GBH = image->height;
     uint32_t CONTEXT;
     uint32_t x, y;
-    bool bit;
     int LTP = 0;
-    int code = 0;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]))
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -1121,9 +1111,10 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GBH; y++) {
-        LTP ^= jbig2_arith_decode(as, &GB_stats[0x0795], &code);
-        if (code)
+        int bit = jbig2_arith_decode(as, &GB_stats[0x0795]);
+        if (bit < 0)
             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON1");
+        LTP ^= bit;
         if (!LTP) {
             uint32_t out_byte = 0;
             int out_bits_to_go_in_byte = 8;
@@ -1150,8 +1141,8 @@
                     CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 3;
                     CONTEXT |= (pd>>9) & 0x01F0; /* next 5 pixels */
                     CONTEXT |= (ppd>>4) & 0x1E00; /* next 4 pixels */
-                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                    if (code)
+                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                    if (bit < 0)
                         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON2");
                 }
                 pd = pd<<1;
@@ -1188,9 +1179,7 @@
     const uint32_t GBH = image->height;
     uint32_t CONTEXT;
     uint32_t x, y;
-    bool bit;
     int LTP = 0;
-    int code = 0;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]))
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -1197,9 +1186,10 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GBH; y++) {
-        LTP ^= jbig2_arith_decode(as, &GB_stats[0xE5], &code);
-        if (code)
+        int bit = jbig2_arith_decode(as, &GB_stats[0xE5]);
+        if (bit < 0)
             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON1");
+        LTP ^= bit;
         if (!LTP) {
             uint32_t out_byte = 0;
             int out_bits_to_go_in_byte = 8;
@@ -1226,8 +1216,8 @@
                     CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 2;
                     CONTEXT |= (pd>>11) & 0x078; /* next 4 pixels */
                     CONTEXT |= (ppd>>7) & 0x380; /* next 3 pixels */
-                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                    if (code)
+                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                    if (bit < 0)
                         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON2");
                 }
                 pd = pd<<1;
@@ -1264,9 +1254,7 @@
     const uint32_t GBH = image->height;
     uint32_t CONTEXT;
     uint32_t x, y;
-    bool bit;
     int LTP = 0;
-    int code = 0;
 
     if (pixel_outside_field(params->gbat[0], params->gbat[1]))
         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
@@ -1273,9 +1261,10 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GBH; y++) {
-        LTP ^= jbig2_arith_decode(as, &GB_stats[0x0195], &code);
-        if (code)
+        int bit = jbig2_arith_decode(as, &GB_stats[0x0195]);
+        if (bit < 0)
             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON1");
+        LTP ^= bit;
         if (!LTP) {
             uint32_t out_byte = 0;
             int out_bits_to_go_in_byte = 8;
@@ -1294,8 +1283,8 @@
                     CONTEXT  = out_byte & 0x0F; /* First 4 pixels */
                     CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
                     CONTEXT |= (pd>>9) & 0x3E0; /* next 5 pixels */
-                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT], &code);
-                    if (code)
+                    bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
+                    if (bit < 0)
                         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON2");
                 }
                 pd = pd<<1;
--- a/jbig2_refinement.c
+++ b/jbig2_refinement.c
@@ -57,8 +57,7 @@
     const int dy = params->GRREFERENCEDY;
     uint32_t CONTEXT;
     int x, y;
-    bool bit;
-    int code = 0;
+    int bit;
 
     if (pixel_outside_field(params->grat[0], params->grat[1]) ||
         refpixel_outside_field(params->grat[2], params->grat[3]))
@@ -81,8 +80,8 @@
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy - 1) << 10;
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 11;
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx + params->grat[2], y - dy + params->grat[3]) << 12;
-            bit = jbig2_arith_decode(as, &GR_stats[CONTEXT], &code);
-            if (code)
+            bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
+            if (bit < 0)
                 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling refinement template0");
             jbig2_image_set_pixel(image, x, y, bit);
         }
@@ -120,8 +119,7 @@
     const int dy = params->GRREFERENCEDY;
     uint32_t CONTEXT;
     int x, y;
-    bool bit;
-    int code = 0;
+    int bit;
 
     for (y = 0; y < GRH; y++) {
         for (x = 0; x < GRW; x++) {
@@ -136,8 +134,8 @@
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 7;
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 8;
             CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 9;
-            bit = jbig2_arith_decode(as, &GR_stats[CONTEXT], &code);
-            if (code)
+            bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
+            if (bit < 0)
                 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling refinement template0");
             jbig2_image_set_pixel(image, x, y, bit);
         }
@@ -177,7 +175,6 @@
     byte *grreg_line = (byte *) image->data;
     byte *grref_line = (byte *) params->reference->data;
     int x, y;
-    int code = 0;
 
     for (y = 0; y < GRH; y++) {
         const int padded_width = (GRW + 7) & -8;
@@ -212,10 +209,10 @@
 
             /* this is the speed critical inner-loop */
             for (x_minor = 0; x_minor < minor_width; x_minor++) {
-                bool bit;
+                int bit;
 
-                bit = jbig2_arith_decode(as, &GR_stats[CONTEXT], &code);
-                if (code)
+                bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
+                if (bit < 0)
                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to decode arithmetic code when handling refinement template1");
                 result |= bit << (7 - x_minor);
                 CONTEXT = ((CONTEXT & 0x0d6) << 1) | bit |
@@ -308,10 +305,9 @@
 {
     const int GRW = image->width;
     const int GRH = image->height;
-    int x, y, iv, bit, LTP = 0;
+    int x, y, iv, LTP = 0;
     uint32_t start_context = (params->GRTEMPLATE ? 0x40 : 0x100);
     ContextBuilder mkctx = (params->GRTEMPLATE ? mkctx1 : mkctx0);
-    int code = 0;
 
     if (params->GRTEMPLATE == 0 &&
         (pixel_outside_field(params->grat[0], params->grat[1]) ||
@@ -320,13 +316,14 @@
                            "adaptive template pixel is out of field");
 
     for (y = 0; y < GRH; y++) {
-        LTP ^= jbig2_arith_decode(as, &GR_stats[start_context], &code);
-        if (code)
+        int bit = jbig2_arith_decode(as, &GR_stats[start_context]);
+        if (bit < 0)
             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
+        LTP ^= bit;
         if (!LTP) {
             for (x = 0; x < GRW; x++) {
-                bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)], &code);
-                if (code)
+                bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]);
+                if (bit < 0)
                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
                 jbig2_image_set_pixel(image, x, y, bit);
             }
@@ -334,8 +331,8 @@
             for (x = 0; x < GRW; x++) {
                 iv = implicit_value(params, image, x, y);
                 if (iv < 0) {
-                    bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)], &code);
-                    if (code)
+                    int bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]);
+                    if (bit < 0)
                         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to decode arithmetic code when handling refinement TPGRON1");
                     jbig2_image_set_pixel(image, x, y, bit);
                 } else