Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.     jbig2dec
  3.  
  4.     Copyright (C) 2002-2008 Artifex Software, Inc.
  5.  
  6.     This software is distributed under license and may not
  7.     be copied, modified or distributed except as expressly
  8.     authorized under the terms of the license contained in
  9.     the file LICENSE in this distribution.
  10.  
  11.     For further licensing information refer to http://artifex.com/ or
  12.     contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
  13.     San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  14. */
  15.  
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include "os_types.h"
  20.  
  21. #include <stddef.h>
  22. #include <string.h> /* memset() */
  23.  
  24. #include "jbig2.h"
  25. #include "jbig2_priv.h"
  26. #include "jbig2_arith.h"
  27. #include "jbig2_arith_int.h"
  28. #include "jbig2_arith_iaid.h"
  29. #include "jbig2_huffman.h"
  30. #include "jbig2_generic.h"
  31. #include "jbig2_symbol_dict.h"
  32. #include "jbig2_text.h"
  33.  
  34.  
  35. /**
  36.  * jbig2_decode_text_region: decode a text region segment
  37.  *
  38.  * @ctx: jbig2 decoder context
  39.  * @segment: jbig2 segment (header) structure
  40.  * @params: parameters from the text region header
  41.  * @dicts: an array of referenced symbol dictionaries
  42.  * @n_dicts: the number of referenced symbol dictionaries
  43.  * @image: image structure in which to store the decoded region bitmap
  44.  * @data: pointer to text region data to be decoded
  45.  * @size: length of text region data
  46.  *
  47.  * Implements the text region decoding procedure
  48.  * described in section 6.4 of the JBIG2 spec.
  49.  *
  50.  * returns: 0 on success
  51.  **/
  52. int
  53. jbig2_decode_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
  54.                              const Jbig2TextRegionParams *params,
  55.                              const Jbig2SymbolDict * const *dicts, const int n_dicts,
  56.                              Jbig2Image *image,
  57.                              const byte *data, const size_t size,
  58.                              Jbig2ArithCx *GR_stats, Jbig2ArithState *as, Jbig2WordStream *ws)
  59. {
  60.     /* relevent bits of 6.4.4 */
  61.     uint32_t NINSTANCES;
  62.     uint32_t ID;
  63.     int32_t STRIPT;
  64.     int32_t FIRSTS;
  65.     int32_t DT;
  66.     int32_t DFS;
  67.     int32_t IDS;
  68.     int32_t CURS;
  69.     int32_t CURT;
  70.     int S,T;
  71.     int x,y;
  72.     bool first_symbol;
  73.     uint32_t index, SBNUMSYMS;
  74.     Jbig2Image *IB;
  75.     Jbig2HuffmanState *hs = NULL;
  76.     Jbig2HuffmanTable *SBSYMCODES = NULL;
  77.     int code = 0;
  78.     int RI;
  79.  
  80.     SBNUMSYMS = 0;
  81.     for (index = 0; index < n_dicts; index++) {
  82.         SBNUMSYMS += dicts[index]->n_symbols;
  83.     }
  84.     jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  85.         "symbol list contains %d glyphs in %d dictionaries", SBNUMSYMS, n_dicts);
  86.  
  87.     if (params->SBHUFF) {
  88.         Jbig2HuffmanTable *runcodes;
  89.         Jbig2HuffmanParams runcodeparams;
  90.         Jbig2HuffmanLine runcodelengths[35];
  91.         Jbig2HuffmanLine *symcodelengths;
  92.         Jbig2HuffmanParams symcodeparams;
  93.         int code, err, len, range, r;
  94.  
  95.         jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  96.           "huffman coded text region");
  97.         hs = jbig2_huffman_new(ctx, ws);
  98.  
  99.         /* 7.4.3.1.7 - decode symbol ID Huffman table */
  100.         /* this is actually part of the segment header, but it is more
  101.            convenient to handle it here */
  102.  
  103.         /* parse and build the runlength code huffman table */
  104.         for (index = 0; index < 35; index++) {
  105.           runcodelengths[index].PREFLEN = jbig2_huffman_get_bits(hs, 4);
  106.           runcodelengths[index].RANGELEN = 0;
  107.           runcodelengths[index].RANGELOW = index;
  108.           jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  109.             "  read runcode%d length %d", index, runcodelengths[index].PREFLEN);
  110.         }
  111.         runcodeparams.HTOOB = 0;
  112.         runcodeparams.lines = runcodelengths;
  113.         runcodeparams.n_lines = 35;
  114.         runcodes = jbig2_build_huffman_table(ctx, &runcodeparams);
  115.         if (runcodes == NULL) {
  116.           jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  117.             "error constructing symbol id runcode table!");
  118.           return -1;
  119.         }
  120.  
  121.         /* decode the symbol id codelengths using the runlength table */
  122.         symcodelengths = jbig2_alloc(ctx->allocator, SBNUMSYMS*sizeof(Jbig2HuffmanLine));
  123.         if (symcodelengths == NULL) {
  124.           jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  125.             "memory allocation failure reading symbol ID huffman table!");
  126.           return -1;
  127.         }
  128.         index = 0;
  129.         while (index < SBNUMSYMS) {
  130.           code = jbig2_huffman_get(hs, runcodes, &err);
  131.           if (err != 0 || code < 0 || code >= 35) {
  132.             jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  133.               "error reading symbol ID huffman table!");
  134.             return err ? err : -1;
  135.           }
  136.  
  137.           if (code < 32) {
  138.             len = code;
  139.             range = 1;
  140.           } else {
  141.             if (code == 32) {
  142.               len = symcodelengths[index-1].PREFLEN;
  143.               if (index < 1) {
  144.                 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  145.                   "error decoding symbol id table: run length with no antecedent!");
  146.                 /* todo: memory cleanup */
  147.                 return -1;
  148.               }
  149.             } else {
  150.               len = 0; /* code == 33 or 34 */
  151.             }
  152.             if (code == 32) range = jbig2_huffman_get_bits(hs, 2) + 3;
  153.             else if (code == 33) range = jbig2_huffman_get_bits(hs, 3) + 3;
  154.             else if (code == 34) range = jbig2_huffman_get_bits(hs, 7) + 11;
  155.           }
  156.           jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  157.             "  read runcode%d at index %d (length %d range %d)", code, index, len, range);
  158.           if (index+range > SBNUMSYMS) {
  159.             jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
  160.               "runlength extends %d entries beyond the end of symbol id table!",
  161.                 index+range - SBNUMSYMS);
  162.             range = SBNUMSYMS - index;
  163.           }
  164.           for (r = 0; r < range; r++) {
  165.             symcodelengths[index+r].PREFLEN = len;
  166.             symcodelengths[index+r].RANGELEN = 0;
  167.             symcodelengths[index+r].RANGELOW = index + r;
  168.           }
  169.           index += r;
  170.         }
  171.  
  172.         if (index < SBNUMSYMS) {
  173.           jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
  174.             "runlength codes do not cover the available symbol set");
  175.         }
  176.         symcodeparams.HTOOB = 0;
  177.         symcodeparams.lines = symcodelengths;
  178.         symcodeparams.n_lines = SBNUMSYMS;
  179.  
  180.         /* skip to byte boundary */
  181.         jbig2_huffman_skip(hs);
  182.  
  183.         /* finally, construct the symbol id huffman table itself */
  184.         SBSYMCODES = jbig2_build_huffman_table(ctx, &symcodeparams);
  185.  
  186.         jbig2_free(ctx->allocator, symcodelengths);
  187.         jbig2_release_huffman_table(ctx, runcodes);
  188.  
  189.         if (SBSYMCODES == NULL) {
  190.             jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  191.                 "could not construct Symbol ID huffman table!");
  192.             return -1;
  193.         }
  194.     }
  195.  
  196.     /* 6.4.5 (1) */
  197.     jbig2_image_clear(ctx, image, params->SBDEFPIXEL);
  198.  
  199.     /* 6.4.6 */
  200.     if (params->SBHUFF) {
  201.         STRIPT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
  202.     } else {
  203.         code = jbig2_arith_int_decode(params->IADT, as, &STRIPT);
  204.     }
  205.  
  206.     /* 6.4.5 (2) */
  207.     STRIPT *= -(params->SBSTRIPS);
  208.     FIRSTS = 0;
  209.     NINSTANCES = 0;
  210.  
  211.     /* 6.4.5 (3) */
  212.     while (NINSTANCES < params->SBNUMINSTANCES) {
  213.         /* (3b) */
  214.         if (params->SBHUFF) {
  215.             DT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
  216.         } else {
  217.             code = jbig2_arith_int_decode(params->IADT, as, &DT);
  218.         }
  219.         DT *= params->SBSTRIPS;
  220.         STRIPT += DT;
  221.  
  222.         first_symbol = TRUE;
  223.         /* 6.4.5 (3c) - decode symbols in strip */
  224.         for (;;) {
  225.             /* (3c.i) */
  226.             if (first_symbol) {
  227.                 /* 6.4.7 */
  228.                 if (params->SBHUFF) {
  229.                     DFS = jbig2_huffman_get(hs, params->SBHUFFFS, &code);
  230.                 } else {
  231.                     code = jbig2_arith_int_decode(params->IAFS, as, &DFS);
  232.                 }
  233.                 FIRSTS += DFS;
  234.                 CURS = FIRSTS;
  235.                 first_symbol = FALSE;
  236.  
  237.             } else {
  238.                 /* (3c.ii) / 6.4.8 */
  239.                 if (params->SBHUFF) {
  240.                     IDS = jbig2_huffman_get(hs, params->SBHUFFDS, &code);
  241.                 } else {
  242.                     code = jbig2_arith_int_decode(params->IADS, as, &IDS);
  243.                 }
  244.                 if (code) {
  245.                     break;
  246.                 }
  247.                 CURS += IDS + params->SBDSOFFSET;
  248.             }
  249.  
  250.             /* (3c.iii) / 6.4.9 */
  251.             if (params->SBSTRIPS == 1) {
  252.                 CURT = 0;
  253.             } else if (params->SBHUFF) {
  254.                 CURT = jbig2_huffman_get_bits(hs, params->LOGSBSTRIPS);
  255.             } else {
  256.                 code = jbig2_arith_int_decode(params->IAIT, as, &CURT);
  257.             }
  258.             T = STRIPT + CURT;
  259.  
  260.             /* (3b.iv) / 6.4.10 - decode the symbol id */
  261.             if (params->SBHUFF) {
  262.                 ID = jbig2_huffman_get(hs, SBSYMCODES, &code);
  263.             } else {
  264.                 code = jbig2_arith_iaid_decode(params->IAID, as, (int *)&ID);
  265.             }
  266.             if (ID >= SBNUMSYMS) {
  267.                 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  268.                     "symbol id out of range! (%d/%d)", ID, SBNUMSYMS);
  269.             }
  270.  
  271.             /* (3c.v) / 6.4.11 - look up the symbol bitmap IB */
  272.             {
  273.                 uint32_t id = ID;
  274.  
  275.                 index = 0;
  276.                 while (id >= dicts[index]->n_symbols)
  277.                     id -= dicts[index++]->n_symbols;
  278.                 IB = jbig2_image_clone(ctx, dicts[index]->glyphs[id]);
  279.             }
  280.             if (params->SBREFINE) {
  281.               if (params->SBHUFF) {
  282.                 RI = jbig2_huffman_get_bits(hs, 1);
  283.               } else {
  284.                 code = jbig2_arith_int_decode(params->IARI, as, &RI);
  285.               }
  286.             } else {
  287.                 RI = 0;
  288.             }
  289.             if (RI) {
  290.                 Jbig2RefinementRegionParams rparams;
  291.                 Jbig2Image *IBO;
  292.                 int32_t RDW, RDH, RDX, RDY;
  293.                 Jbig2Image *refimage;
  294.                 int BMSIZE = 0;
  295.  
  296.                 /* 6.4.11 (1, 2, 3, 4) */
  297.                 if (!params->SBHUFF) {
  298.                   code = jbig2_arith_int_decode(params->IARDW, as, &RDW);
  299.                   code = jbig2_arith_int_decode(params->IARDH, as, &RDH);
  300.                   code = jbig2_arith_int_decode(params->IARDX, as, &RDX);
  301.                   code = jbig2_arith_int_decode(params->IARDY, as, &RDY);
  302.                 } else {
  303.                   RDW = jbig2_huffman_get(hs, params->SBHUFFRDW, &code);
  304.                   RDH = jbig2_huffman_get(hs, params->SBHUFFRDH, &code);
  305.                   RDX = jbig2_huffman_get(hs, params->SBHUFFRDX, &code);
  306.                   RDY = jbig2_huffman_get(hs, params->SBHUFFRDY, &code);
  307.                   BMSIZE = jbig2_huffman_get(hs, params->SBHUFFRSIZE, &code);
  308.                   jbig2_huffman_skip(hs);
  309.                 }
  310.  
  311.                 /* 6.4.11 (6) */
  312.                 IBO = IB;
  313.                 refimage = jbig2_image_new(ctx, IBO->width + RDW,
  314.                                                 IBO->height + RDH);
  315.                 if (refimage == NULL) {
  316.                   jbig2_image_release(ctx, IBO);
  317.                   if (params->SBHUFF) {
  318.                     jbig2_release_huffman_table(ctx, SBSYMCODES);
  319.                   }
  320.                   return jbig2_error(ctx, JBIG2_SEVERITY_FATAL,
  321.                         segment->number,
  322.                         "couldn't allocate reference image");
  323.                 }
  324.  
  325.                 /* Table 12 */
  326.                 rparams.GRTEMPLATE = params->SBRTEMPLATE;
  327.                 rparams.reference = IBO;
  328.                 rparams.DX = (RDW >> 1) + RDX;
  329.                 rparams.DY = (RDH >> 1) + RDY;
  330.                 rparams.TPGRON = 0;
  331.                 memcpy(rparams.grat, params->sbrat, 4);
  332.                 jbig2_decode_refinement_region(ctx, segment,
  333.                     &rparams, as, refimage, GR_stats);
  334.                 IB = refimage;
  335.  
  336.                 jbig2_image_release(ctx, IBO);
  337.  
  338.                 /* 6.4.11 (7) */
  339.                 if (params->SBHUFF) {
  340.                   jbig2_huffman_advance(hs, BMSIZE);
  341.                 }
  342.  
  343.             }
  344.  
  345.             /* (3c.vi) */
  346.             if ((!params->TRANSPOSED) && (params->REFCORNER > 1)) {
  347.                 CURS += IB->width - 1;
  348.             } else if ((params->TRANSPOSED) && !(params->REFCORNER & 1)) {
  349.                 CURS += IB->height - 1;
  350.             }
  351.  
  352.             /* (3c.vii) */
  353.             S = CURS;
  354.  
  355.             /* (3c.viii) */
  356.             if (!params->TRANSPOSED) {
  357.                 switch (params->REFCORNER) {
  358.                 case JBIG2_CORNER_TOPLEFT: x = S; y = T; break;
  359.                 case JBIG2_CORNER_TOPRIGHT: x = S - IB->width + 1; y = T; break;
  360.                 case JBIG2_CORNER_BOTTOMLEFT: x = S; y = T - IB->height + 1; break;
  361.                 case JBIG2_CORNER_BOTTOMRIGHT: x = S - IB->width + 1; y = T - IB->height + 1; break;
  362.                 }
  363.             } else { /* TRANSPOSED */
  364.                 switch (params->REFCORNER) {
  365.                 case JBIG2_CORNER_TOPLEFT: x = T; y = S; break;
  366.                 case JBIG2_CORNER_TOPRIGHT: x = T - IB->width + 1; y = S; break;
  367.                 case JBIG2_CORNER_BOTTOMLEFT: x = T; y = S - IB->height + 1; break;
  368.                 case JBIG2_CORNER_BOTTOMRIGHT: x = T - IB->width + 1; y = S - IB->height + 1; break;
  369.                 }
  370.             }
  371.  
  372.             /* (3c.ix) */
  373. #ifdef JBIG2_DEBUG
  374.             jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  375.                         "composing glyph id %d: %dx%d @ (%d,%d) symbol %d/%d",
  376.                         ID, IB->width, IB->height, x, y, NINSTANCES + 1,
  377.                         params->SBNUMINSTANCES);
  378. #endif
  379.             jbig2_image_compose(ctx, image, IB, x, y, params->SBCOMBOP);
  380.  
  381.             /* (3c.x) */
  382.             if ((!params->TRANSPOSED) && (params->REFCORNER < 2)) {
  383.                 CURS += IB->width -1 ;
  384.             } else if ((params->TRANSPOSED) && (params->REFCORNER & 1)) {
  385.                 CURS += IB->height - 1;
  386.             }
  387.  
  388.             /* (3c.xi) */
  389.             NINSTANCES++;
  390.  
  391.             jbig2_image_release(ctx, IB);
  392.         }
  393.         /* end strip */
  394.     }
  395.     /* 6.4.5 (4) */
  396.  
  397.     if (params->SBHUFF) {
  398.       jbig2_release_huffman_table(ctx, SBSYMCODES);
  399.     }
  400.  
  401.     return 0;
  402. }
  403.  
  404. /**
  405.  * jbig2_text_region: read a text region segment header
  406.  **/
  407. int
  408. jbig2_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
  409. {
  410.     int offset = 0;
  411.     Jbig2RegionSegmentInfo region_info;
  412.     Jbig2TextRegionParams params;
  413.     Jbig2Image *image;
  414.     Jbig2SymbolDict **dicts;
  415.     int n_dicts;
  416.     uint16_t flags;
  417.     uint16_t huffman_flags = 0;
  418.     Jbig2ArithCx *GR_stats = NULL;
  419.     int code = 0;
  420.     Jbig2WordStream *ws = NULL;
  421.     Jbig2ArithState *as = NULL;
  422.  
  423.     /* 7.4.1 */
  424.     if (segment->data_length < 17)
  425.         goto too_short;
  426.     jbig2_get_region_segment_info(&region_info, segment_data);
  427.     offset += 17;
  428.  
  429.     /* 7.4.3.1.1 */
  430.     flags = jbig2_get_int16(segment_data + offset);
  431.     offset += 2;
  432.  
  433.     jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  434.         "text region header flags 0x%04x", flags);
  435.  
  436.     params.SBHUFF = flags & 0x0001;
  437.     params.SBREFINE = flags & 0x0002;
  438.     params.LOGSBSTRIPS = (flags & 0x000c) >> 2;
  439.     params.SBSTRIPS = 1 << params.LOGSBSTRIPS;
  440.     params.REFCORNER = (flags & 0x0030) >> 4;
  441.     params.TRANSPOSED = flags & 0x0040;
  442.     params.SBCOMBOP = (flags & 0x0180) >> 7;
  443.     params.SBDEFPIXEL = flags & 0x0200;
  444.     /* SBDSOFFSET is a signed 5 bit integer */
  445.     params.SBDSOFFSET = (flags & 0x7C00) >> 10;
  446.     if (params.SBDSOFFSET > 0x0f) params.SBDSOFFSET -= 0x20;
  447.     params.SBRTEMPLATE = flags & 0x8000;
  448.  
  449.     if (params.SBDSOFFSET) {
  450.       jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  451.         "text region has SBDSOFFSET %d", params.SBDSOFFSET);
  452.     }
  453.  
  454.     if (params.SBHUFF)  /* Huffman coding */
  455.       {
  456.         /* 7.4.3.1.2 */
  457.         huffman_flags = jbig2_get_int16(segment_data + offset);
  458.         offset += 2;
  459.  
  460.         if (huffman_flags & 0x8000)
  461.             jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
  462.                 "reserved bit 15 of text region huffman flags is not zero");
  463.       }
  464.     else        /* arithmetic coding */
  465.       {
  466.         /* 7.4.3.1.3 */
  467.         if ((params.SBREFINE) && !(params.SBRTEMPLATE))
  468.           {
  469.             params.sbrat[0] = segment_data[offset];
  470.             params.sbrat[1] = segment_data[offset + 1];
  471.             params.sbrat[2] = segment_data[offset + 2];
  472.             params.sbrat[3] = segment_data[offset + 3];
  473.             offset += 4;
  474.           } else {
  475.             /* zero these for the sake of later debug messages */
  476.             memset(params.sbrat, 0, sizeof(params.sbrat));
  477.           }
  478.       }
  479.  
  480.     /* 7.4.3.1.4 */
  481.     params.SBNUMINSTANCES = jbig2_get_int32(segment_data + offset);
  482.     offset += 4;
  483.  
  484.     if (params.SBHUFF) {
  485.         /* 7.4.3.1.5 - Symbol ID Huffman table */
  486.         /* ...this is handled in the segment body decoder */
  487.  
  488.         /* 7.4.3.1.6 - Other Huffman table selection */
  489.         switch (huffman_flags & 0x0003) {
  490.           case 0: /* Table B.6 */
  491.             params.SBHUFFFS = jbig2_build_huffman_table(ctx,
  492.                         &jbig2_huffman_params_F);
  493.             break;
  494.           case 1: /* Table B.7 */
  495.             params.SBHUFFFS = jbig2_build_huffman_table(ctx,
  496.                         &jbig2_huffman_params_G);
  497.             break;
  498.           case 3: /* Custom table from referred segment */
  499.             /* We handle this case later by leaving the table as NULL */
  500.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  501.                 "text region uses custom FS huffman table (NYI)");
  502.             break;
  503.           case 2: /* invalid */
  504.           default:
  505.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  506.                 "text region specified invalid FS huffman table");
  507.             break;
  508.         }
  509.         switch ((huffman_flags & 0x000c) >> 2) {
  510.           case 0: /* Table B.8 */
  511.             params.SBHUFFDS = jbig2_build_huffman_table(ctx,
  512.                         &jbig2_huffman_params_H);
  513.             break;
  514.           case 1: /* Table B.9 */
  515.             params.SBHUFFDS = jbig2_build_huffman_table(ctx,
  516.                         &jbig2_huffman_params_I);
  517.             break;
  518.           case 2: /* Table B.10 */
  519.             params.SBHUFFDS = jbig2_build_huffman_table(ctx,
  520.                         &jbig2_huffman_params_J);
  521.             break;
  522.           case 3: /* Custom table from referred segment */
  523.             /* We handle this case later by leaving the table as NULL */
  524.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  525.                 "text region uses custom DS huffman table (NYI)");
  526.             break;
  527.         }
  528.         switch ((huffman_flags & 0x0030) >> 4) {
  529.           case 0: /* Table B.11 */
  530.             params.SBHUFFDT = jbig2_build_huffman_table(ctx,
  531.                         &jbig2_huffman_params_K);
  532.             break;
  533.           case 1: /* Table B.12 */
  534.             params.SBHUFFDT = jbig2_build_huffman_table(ctx,
  535.                         &jbig2_huffman_params_L);
  536.             break;
  537.           case 2: /* Table B.13 */
  538.             params.SBHUFFDT = jbig2_build_huffman_table(ctx,
  539.                         &jbig2_huffman_params_M);
  540.             break;
  541.           case 3: /* Custom table from referred segment */
  542.             /* We handle this case later by leaving the table as NULL */
  543.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  544.                 "text region uses custom DT huffman table (NYI)");
  545.             break;
  546.         }
  547.         switch ((huffman_flags & 0x00c0) >> 6) {
  548.           case 0: /* Table B.14 */
  549.             params.SBHUFFRDW = jbig2_build_huffman_table(ctx,
  550.                         &jbig2_huffman_params_N);
  551.             break;
  552.           case 1: /* Table B.15 */
  553.             params.SBHUFFRDW = jbig2_build_huffman_table(ctx,
  554.                         &jbig2_huffman_params_O);
  555.             break;
  556.           case 3: /* Custom table from referred segment */
  557.             /* We handle this case later by leaving the table as NULL */
  558.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  559.                 "text region uses custom RDW huffman table (NYI)");
  560.             break;
  561.           case 2: /* invalid */
  562.           default:
  563.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  564.                 "text region specified invalid RDW huffman table");
  565.             break;
  566.         }
  567.         switch ((huffman_flags & 0x0300) >> 8) {
  568.           case 0: /* Table B.14 */
  569.             params.SBHUFFRDH = jbig2_build_huffman_table(ctx,
  570.                         &jbig2_huffman_params_N);
  571.             break;
  572.           case 1: /* Table B.15 */
  573.             params.SBHUFFRDH = jbig2_build_huffman_table(ctx,
  574.                         &jbig2_huffman_params_O);
  575.             break;
  576.           case 3: /* Custom table from referred segment */
  577.             /* We handle this case later by leaving the table as NULL */
  578.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  579.                 "text region uses custom RDH huffman table (NYI)");
  580.             break;
  581.           case 2: /* invalid */
  582.           default:
  583.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  584.                 "text region specified invalid RDH huffman table");
  585.             break;
  586.         }
  587.         switch ((huffman_flags & 0x0c00) >> 10) {
  588.           case 0: /* Table B.14 */
  589.             params.SBHUFFRDX = jbig2_build_huffman_table(ctx,
  590.                         &jbig2_huffman_params_N);
  591.             break;
  592.           case 1: /* Table B.15 */
  593.             params.SBHUFFRDX = jbig2_build_huffman_table(ctx,
  594.                         &jbig2_huffman_params_O);
  595.             break;
  596.           case 3: /* Custom table from referred segment */
  597.             /* We handle this case later by leaving the table as NULL */
  598.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  599.                 "text region uses custom RDX huffman table (NYI)");
  600.             break;
  601.           case 2: /* invalid */
  602.           default:
  603.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  604.                 "text region specified invalid RDX huffman table");
  605.             break;
  606.         }
  607.         switch ((huffman_flags & 0x3000) >> 12) {
  608.           case 0: /* Table B.14 */
  609.             params.SBHUFFRDY = jbig2_build_huffman_table(ctx,
  610.                         &jbig2_huffman_params_N);
  611.             break;
  612.           case 1: /* Table B.15 */
  613.             params.SBHUFFRDY = jbig2_build_huffman_table(ctx,
  614.                         &jbig2_huffman_params_O);
  615.             break;
  616.           case 3: /* Custom table from referred segment */
  617.             /* We handle this case later by leaving the table as NULL */
  618.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  619.                 "text region uses custom RDY huffman table (NYI)");
  620.             break;
  621.           case 2: /* invalid */
  622.           default:
  623.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  624.                 "text region specified invalid RDY huffman table");
  625.             break;
  626.         }
  627.         switch ((huffman_flags & 0x4000) >> 14) {
  628.           case 0: /* Table B.1 */
  629.             params.SBHUFFRSIZE = jbig2_build_huffman_table(ctx,
  630.                         &jbig2_huffman_params_A);
  631.             break;
  632.           case 1: /* Custom table from referred segment */
  633.             /* We handle this case later by leaving the table as NULL */
  634.             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  635.                 "text region uses custom RSIZE huffman table (NYI)");
  636.             break;
  637.         }
  638.  
  639.         if (huffman_flags & 0x8000) {
  640.           jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
  641.             "text region huffman flags bit 15 is set, contrary to spec");
  642.         }
  643.  
  644.         /* 7.4.3.1.7 */
  645.         /* For convenience this is done in the body decoder routine */
  646.     }
  647.  
  648.     jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
  649.         "text region: %d x %d @ (%d,%d) %d symbols",
  650.         region_info.width, region_info.height,
  651.         region_info.x, region_info.y, params.SBNUMINSTANCES);
  652.  
  653.     /* 7.4.3.2 (2) - compose the list of symbol dictionaries */
  654.     n_dicts = jbig2_sd_count_referred(ctx, segment);
  655.     if (n_dicts != 0) {
  656.         dicts = jbig2_sd_list_referred(ctx, segment);
  657.     } else {
  658.         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  659.                 "text region refers to no symbol dictionaries!");
  660.     }
  661.     if (dicts == NULL) {
  662.         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  663.                 "unable to retrive symbol dictionaries!"
  664.                 " previous parsing error?");
  665.     } else {
  666.         int index;
  667.         if (dicts[0] == NULL) {
  668.             return jbig2_error(ctx, JBIG2_SEVERITY_WARNING,
  669.                         segment->number,
  670.                         "unable to find first referenced symbol dictionary!");
  671.         }
  672.         for (index = 1; index < n_dicts; index++)
  673.             if (dicts[index] == NULL) {
  674.                 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
  675.                         "unable to find all referenced symbol dictionaries!");
  676.             n_dicts = index;
  677.         }
  678.     }
  679.  
  680.     /* 7.4.3.2 (3) */
  681.     if (!params.SBHUFF && params.SBREFINE) {
  682.         int stats_size = params.SBRTEMPLATE ? 1 << 10 : 1 << 13;
  683.         GR_stats = jbig2_alloc(ctx->allocator, stats_size);
  684.         memset(GR_stats, 0, stats_size);
  685.     }
  686.  
  687.     image = jbig2_image_new(ctx, region_info.width, region_info.height);
  688.     if (image == NULL) {
  689.       if (!params.SBHUFF && params.SBREFINE) {
  690.         jbig2_free(ctx->allocator, GR_stats);
  691.       } else if (params.SBHUFF) {
  692.         jbig2_release_huffman_table(ctx, params.SBHUFFFS);
  693.         jbig2_release_huffman_table(ctx, params.SBHUFFDS);
  694.         jbig2_release_huffman_table(ctx, params.SBHUFFDT);
  695.         jbig2_release_huffman_table(ctx, params.SBHUFFRDX);
  696.         jbig2_release_huffman_table(ctx, params.SBHUFFRDY);
  697.         jbig2_release_huffman_table(ctx, params.SBHUFFRDW);
  698.         jbig2_release_huffman_table(ctx, params.SBHUFFRDH);
  699.         jbig2_release_huffman_table(ctx, params.SBHUFFRSIZE);
  700.       }
  701.       return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  702.                 "couldn't allocate text region image");
  703.     }
  704.  
  705.     ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset);
  706.     if (!params.SBHUFF) {
  707.         int SBSYMCODELEN, index;
  708.         int SBNUMSYMS = 0;
  709.         for (index = 0; index < n_dicts; index++) {
  710.             SBNUMSYMS += dicts[index]->n_symbols;
  711.         }
  712.  
  713.         as = jbig2_arith_new(ctx, ws);
  714.         ws = 0;
  715.  
  716.         params.IADT = jbig2_arith_int_ctx_new(ctx);
  717.         params.IAFS = jbig2_arith_int_ctx_new(ctx);
  718.         params.IADS = jbig2_arith_int_ctx_new(ctx);
  719.         params.IAIT = jbig2_arith_int_ctx_new(ctx);
  720.         /* Table 31 */
  721.         for (SBSYMCODELEN = 0; (1 << SBSYMCODELEN) < SBNUMSYMS; SBSYMCODELEN++);
  722.         params.IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
  723.         params.IARI = jbig2_arith_int_ctx_new(ctx);
  724.         params.IARDW = jbig2_arith_int_ctx_new(ctx);
  725.         params.IARDH = jbig2_arith_int_ctx_new(ctx);
  726.         params.IARDX = jbig2_arith_int_ctx_new(ctx);
  727.         params.IARDY = jbig2_arith_int_ctx_new(ctx);
  728.     }
  729.  
  730.     code = jbig2_decode_text_region(ctx, segment, &params,
  731.                 (const Jbig2SymbolDict * const *)dicts, n_dicts, image,
  732.                 segment_data + offset, segment->data_length - offset,
  733.                 GR_stats, as, ws);
  734.  
  735.     if (!params.SBHUFF && params.SBREFINE) {
  736.         jbig2_free(ctx->allocator, GR_stats);
  737.     }
  738.  
  739.     if (params.SBHUFF) {
  740.       jbig2_release_huffman_table(ctx, params.SBHUFFFS);
  741.       jbig2_release_huffman_table(ctx, params.SBHUFFDS);
  742.       jbig2_release_huffman_table(ctx, params.SBHUFFDT);
  743.       jbig2_release_huffman_table(ctx, params.SBHUFFRDX);
  744.       jbig2_release_huffman_table(ctx, params.SBHUFFRDY);
  745.       jbig2_release_huffman_table(ctx, params.SBHUFFRDW);
  746.       jbig2_release_huffman_table(ctx, params.SBHUFFRDH);
  747.       jbig2_release_huffman_table(ctx, params.SBHUFFRSIZE);
  748.     }
  749.     else {
  750.         jbig2_arith_int_ctx_free(ctx, params.IADT);
  751.         jbig2_arith_int_ctx_free(ctx, params.IAFS);
  752.         jbig2_arith_int_ctx_free(ctx, params.IADS);
  753.         jbig2_arith_int_ctx_free(ctx, params.IAIT);
  754.         jbig2_arith_iaid_ctx_free(ctx, params.IAID);
  755.         jbig2_arith_int_ctx_free(ctx, params.IARI);
  756.         jbig2_arith_int_ctx_free(ctx, params.IARDW);
  757.         jbig2_arith_int_ctx_free(ctx, params.IARDH);
  758.         jbig2_arith_int_ctx_free(ctx, params.IARDX);
  759.         jbig2_arith_int_ctx_free(ctx, params.IARDY);
  760.         jbig2_free(ctx->allocator, as);
  761.         jbig2_word_stream_buf_free(ctx, ws);
  762.     }
  763.  
  764.     jbig2_free(ctx->allocator, dicts);
  765.  
  766.     /* todo: check errors */
  767.  
  768.     if ((segment->flags & 63) == 4) {
  769.         /* we have an intermediate region here. save it for later */
  770.         segment->result = image;
  771.     } else {
  772.         /* otherwise composite onto the page */
  773.         jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  774.             "composing %dx%d decoded text region onto page at (%d, %d)",
  775.             region_info.width, region_info.height, region_info.x, region_info.y);
  776.         jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image,
  777.                               region_info.x, region_info.y, region_info.op);
  778.         jbig2_image_release(ctx, image);
  779.     }
  780.  
  781.     /* success */
  782.     return 0;
  783.  
  784.     too_short:
  785.         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  786.                     "Segment too short");
  787. }
  788.