Cleanup JBig2_ArithIntDecoder.
[pdfium.git] / core / src / fxcodec / jbig2 / JBig2_SddProc.cpp
1 // Copyright 2015 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "JBig2_SddProc.h"
8
9 #include "../../../../third_party/base/nonstd_unique_ptr.h"
10 #include "../../../include/fxcrt/fx_basic.h"
11 #include "JBig2_ArithIntDecoder.h"
12 #include "JBig2_GrdProc.h"
13 #include "JBig2_GrrdProc.h"
14 #include "JBig2_HuffmanDecoder.h"
15 #include "JBig2_HuffmanTable.h"
16 #include "JBig2_SymbolDict.h"
17 #include "JBig2_TrdProc.h"
18
19 CJBig2_SymbolDict* CJBig2_SDDProc::decode_Arith(
20     CJBig2_ArithDecoder* pArithDecoder,
21     JBig2ArithCtx* gbContext,
22     JBig2ArithCtx* grContext) {
23   CJBig2_Image** SDNEWSYMS;
24   FX_DWORD HCHEIGHT, NSYMSDECODED;
25   int32_t HCDH;
26   FX_DWORD SYMWIDTH, TOTWIDTH;
27   int32_t DW;
28   CJBig2_Image* BS;
29   FX_DWORD I, J, REFAGGNINST;
30   FX_BOOL* EXFLAGS;
31   FX_DWORD EXINDEX;
32   FX_BOOL CUREXFLAG;
33   FX_DWORD EXRUNLENGTH;
34   int32_t nVal;
35   FX_DWORD nTmp;
36   FX_DWORD SBNUMSYMS;
37   uint8_t SBSYMCODELEN;
38   int32_t RDXI, RDYI;
39   CJBig2_Image** SBSYMS;
40   nonstd::unique_ptr<CJBig2_ArithIaidDecoder> IAID;
41   nonstd::unique_ptr<CJBig2_SymbolDict> pDict;
42   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IADH(new CJBig2_ArithIntDecoder);
43   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IADW(new CJBig2_ArithIntDecoder);
44   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IAAI(new CJBig2_ArithIntDecoder);
45   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IARDX(new CJBig2_ArithIntDecoder);
46   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IARDY(new CJBig2_ArithIntDecoder);
47   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IAEX(new CJBig2_ArithIntDecoder);
48   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IADT(new CJBig2_ArithIntDecoder);
49   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IAFS(new CJBig2_ArithIntDecoder);
50   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IADS(new CJBig2_ArithIntDecoder);
51   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IAIT(new CJBig2_ArithIntDecoder);
52   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IARI(new CJBig2_ArithIntDecoder);
53   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IARDW(new CJBig2_ArithIntDecoder);
54   nonstd::unique_ptr<CJBig2_ArithIntDecoder> IARDH(new CJBig2_ArithIntDecoder);
55   nTmp = 0;
56   while ((FX_DWORD)(1 << nTmp) < (SDNUMINSYMS + SDNUMNEWSYMS)) {
57     nTmp++;
58   }
59   IAID.reset(new CJBig2_ArithIaidDecoder((uint8_t)nTmp));
60   SDNEWSYMS = FX_Alloc(CJBig2_Image*, SDNUMNEWSYMS);
61   FXSYS_memset(SDNEWSYMS, 0, SDNUMNEWSYMS * sizeof(CJBig2_Image*));
62
63   HCHEIGHT = 0;
64   NSYMSDECODED = 0;
65   while (NSYMSDECODED < SDNUMNEWSYMS) {
66     BS = nullptr;
67     if (!IADH->decode(pArithDecoder, &HCDH)) {
68       goto failed;
69     }
70     HCHEIGHT = HCHEIGHT + HCDH;
71     if ((int)HCHEIGHT < 0 || (int)HCHEIGHT > JBIG2_MAX_IMAGE_SIZE) {
72       goto failed;
73     }
74     SYMWIDTH = 0;
75     TOTWIDTH = 0;
76     for (;;) {
77       nVal = IADW->decode(pArithDecoder, &DW);
78       if (nVal == JBIG2_OOB) {
79         break;
80       } else if (nVal != 0) {
81         goto failed;
82       } else {
83         if (NSYMSDECODED >= SDNUMNEWSYMS) {
84           goto failed;
85         }
86         SYMWIDTH = SYMWIDTH + DW;
87         if ((int)SYMWIDTH < 0 || (int)SYMWIDTH > JBIG2_MAX_IMAGE_SIZE) {
88           goto failed;
89         } else if (HCHEIGHT == 0 || SYMWIDTH == 0) {
90           TOTWIDTH = TOTWIDTH + SYMWIDTH;
91           SDNEWSYMS[NSYMSDECODED] = nullptr;
92           NSYMSDECODED = NSYMSDECODED + 1;
93           continue;
94         }
95         TOTWIDTH = TOTWIDTH + SYMWIDTH;
96       }
97       if (SDREFAGG == 0) {
98         nonstd::unique_ptr<CJBig2_GRDProc> pGRD(new CJBig2_GRDProc());
99         pGRD->MMR = 0;
100         pGRD->GBW = SYMWIDTH;
101         pGRD->GBH = HCHEIGHT;
102         pGRD->GBTEMPLATE = SDTEMPLATE;
103         pGRD->TPGDON = 0;
104         pGRD->USESKIP = 0;
105         pGRD->GBAT[0] = SDAT[0];
106         pGRD->GBAT[1] = SDAT[1];
107         pGRD->GBAT[2] = SDAT[2];
108         pGRD->GBAT[3] = SDAT[3];
109         pGRD->GBAT[4] = SDAT[4];
110         pGRD->GBAT[5] = SDAT[5];
111         pGRD->GBAT[6] = SDAT[6];
112         pGRD->GBAT[7] = SDAT[7];
113         BS = pGRD->decode_Arith(pArithDecoder, gbContext);
114         if (!BS) {
115           goto failed;
116         }
117       } else {
118         if (!IAAI->decode(pArithDecoder, (int*)&REFAGGNINST)) {
119           goto failed;
120         }
121         if (REFAGGNINST > 1) {
122           nonstd::unique_ptr<CJBig2_TRDProc> pDecoder(new CJBig2_TRDProc());
123           pDecoder->SBHUFF = SDHUFF;
124           pDecoder->SBREFINE = 1;
125           pDecoder->SBW = SYMWIDTH;
126           pDecoder->SBH = HCHEIGHT;
127           pDecoder->SBNUMINSTANCES = REFAGGNINST;
128           pDecoder->SBSTRIPS = 1;
129           pDecoder->SBNUMSYMS = SDNUMINSYMS + NSYMSDECODED;
130           SBNUMSYMS = pDecoder->SBNUMSYMS;
131           nTmp = 0;
132           while ((FX_DWORD)(1 << nTmp) < SBNUMSYMS) {
133             nTmp++;
134           }
135           SBSYMCODELEN = (uint8_t)nTmp;
136           pDecoder->SBSYMCODELEN = SBSYMCODELEN;
137           SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS);
138           JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*));
139           JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS,
140                        NSYMSDECODED * sizeof(CJBig2_Image*));
141           pDecoder->SBSYMS = SBSYMS;
142           pDecoder->SBDEFPIXEL = 0;
143           pDecoder->SBCOMBOP = JBIG2_COMPOSE_OR;
144           pDecoder->TRANSPOSED = 0;
145           pDecoder->REFCORNER = JBIG2_CORNER_TOPLEFT;
146           pDecoder->SBDSOFFSET = 0;
147           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFFS(
148               new CJBig2_HuffmanTable(HuffmanTable_B6,
149                                       FX_ArraySize(HuffmanTable_B6),
150                                       HuffmanTable_HTOOB_B6));
151           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFDS(
152               new CJBig2_HuffmanTable(HuffmanTable_B8,
153                                       FX_ArraySize(HuffmanTable_B8),
154                                       HuffmanTable_HTOOB_B8));
155           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFDT(
156               new CJBig2_HuffmanTable(HuffmanTable_B11,
157                                       FX_ArraySize(HuffmanTable_B11),
158                                       HuffmanTable_HTOOB_B11));
159           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDW(
160               new CJBig2_HuffmanTable(HuffmanTable_B15,
161                                       FX_ArraySize(HuffmanTable_B15),
162                                       HuffmanTable_HTOOB_B15));
163           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDH(
164               new CJBig2_HuffmanTable(HuffmanTable_B15,
165                                       FX_ArraySize(HuffmanTable_B15),
166                                       HuffmanTable_HTOOB_B15));
167           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDX(
168               new CJBig2_HuffmanTable(HuffmanTable_B15,
169                                       FX_ArraySize(HuffmanTable_B15),
170                                       HuffmanTable_HTOOB_B15));
171           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDY(
172               new CJBig2_HuffmanTable(HuffmanTable_B15,
173                                       FX_ArraySize(HuffmanTable_B15),
174                                       HuffmanTable_HTOOB_B15));
175           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRSIZE(
176               new CJBig2_HuffmanTable(HuffmanTable_B1,
177                                       FX_ArraySize(HuffmanTable_B1),
178                                       HuffmanTable_HTOOB_B1));
179           pDecoder->SBHUFFFS = SBHUFFFS.get();
180           pDecoder->SBHUFFDS = SBHUFFDS.get();
181           pDecoder->SBHUFFDT = SBHUFFDT.get();
182           pDecoder->SBHUFFRDW = SBHUFFRDW.get();
183           pDecoder->SBHUFFRDH = SBHUFFRDH.get();
184           pDecoder->SBHUFFRDX = SBHUFFRDX.get();
185           pDecoder->SBHUFFRDY = SBHUFFRDY.get();
186           pDecoder->SBHUFFRSIZE = SBHUFFRSIZE.get();
187           pDecoder->SBRTEMPLATE = SDRTEMPLATE;
188           pDecoder->SBRAT[0] = SDRAT[0];
189           pDecoder->SBRAT[1] = SDRAT[1];
190           pDecoder->SBRAT[2] = SDRAT[2];
191           pDecoder->SBRAT[3] = SDRAT[3];
192           JBig2IntDecoderState ids;
193           ids.IADT = IADT.get();
194           ids.IAFS = IAFS.get();
195           ids.IADS = IADS.get();
196           ids.IAIT = IAIT.get();
197           ids.IARI = IARI.get();
198           ids.IARDW = IARDW.get();
199           ids.IARDH = IARDH.get();
200           ids.IARDX = IARDX.get();
201           ids.IARDY = IARDY.get();
202           ids.IAID = IAID.get();
203           BS = pDecoder->decode_Arith(pArithDecoder, grContext, &ids);
204           if (!BS) {
205             FX_Free(SBSYMS);
206             goto failed;
207           }
208           FX_Free(SBSYMS);
209         } else if (REFAGGNINST == 1) {
210           SBNUMSYMS = SDNUMINSYMS + NSYMSDECODED;
211           FX_DWORD IDI;
212           IAID->decode(pArithDecoder, &IDI);
213           if (!IARDX->decode(pArithDecoder, &RDXI) ||
214               !IARDY->decode(pArithDecoder, &RDYI)) {
215             goto failed;
216           }
217           if (IDI >= SBNUMSYMS) {
218             goto failed;
219           }
220           SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS);
221           JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*));
222           JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS,
223                        NSYMSDECODED * sizeof(CJBig2_Image*));
224           if (!SBSYMS[IDI]) {
225             FX_Free(SBSYMS);
226             goto failed;
227           }
228           nonstd::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc());
229           pGRRD->GRW = SYMWIDTH;
230           pGRRD->GRH = HCHEIGHT;
231           pGRRD->GRTEMPLATE = SDRTEMPLATE;
232           pGRRD->GRREFERENCE = SBSYMS[IDI];
233           pGRRD->GRREFERENCEDX = RDXI;
234           pGRRD->GRREFERENCEDY = RDYI;
235           pGRRD->TPGRON = 0;
236           pGRRD->GRAT[0] = SDRAT[0];
237           pGRRD->GRAT[1] = SDRAT[1];
238           pGRRD->GRAT[2] = SDRAT[2];
239           pGRRD->GRAT[3] = SDRAT[3];
240           BS = pGRRD->decode(pArithDecoder, grContext);
241           if (!BS) {
242             FX_Free(SBSYMS);
243             goto failed;
244           }
245           FX_Free(SBSYMS);
246         }
247       }
248       SDNEWSYMS[NSYMSDECODED] = BS;
249       BS = nullptr;
250       NSYMSDECODED = NSYMSDECODED + 1;
251     }
252   }
253   EXINDEX = 0;
254   CUREXFLAG = 0;
255   EXFLAGS = FX_Alloc(FX_BOOL, SDNUMINSYMS + SDNUMNEWSYMS);
256   while (EXINDEX < SDNUMINSYMS + SDNUMNEWSYMS) {
257     if (!IAEX->decode(pArithDecoder, (int*)&EXRUNLENGTH)) {
258       FX_Free(EXFLAGS);
259       goto failed;
260     }
261     if (EXINDEX + EXRUNLENGTH > SDNUMINSYMS + SDNUMNEWSYMS) {
262       FX_Free(EXFLAGS);
263       goto failed;
264     }
265     if (EXRUNLENGTH != 0) {
266       for (I = EXINDEX; I < EXINDEX + EXRUNLENGTH; I++) {
267         EXFLAGS[I] = CUREXFLAG;
268       }
269     }
270     EXINDEX = EXINDEX + EXRUNLENGTH;
271     CUREXFLAG = !CUREXFLAG;
272   }
273   pDict.reset(new CJBig2_SymbolDict);
274   pDict->SDNUMEXSYMS = SDNUMEXSYMS;
275   pDict->SDEXSYMS = FX_Alloc(CJBig2_Image*, SDNUMEXSYMS);
276   I = J = 0;
277   for (I = 0; I < SDNUMINSYMS + SDNUMNEWSYMS; I++) {
278     if (EXFLAGS[I] && J < SDNUMEXSYMS) {
279       if (I < SDNUMINSYMS) {
280         pDict->SDEXSYMS[J] = new CJBig2_Image(*SDINSYMS[I]);
281       } else {
282         pDict->SDEXSYMS[J] = SDNEWSYMS[I - SDNUMINSYMS];
283       }
284       J = J + 1;
285     } else if (!EXFLAGS[I] && I >= SDNUMINSYMS) {
286       delete SDNEWSYMS[I - SDNUMINSYMS];
287     }
288   }
289   if (J < SDNUMEXSYMS) {
290     pDict->SDNUMEXSYMS = J;
291   }
292   FX_Free(EXFLAGS);
293   FX_Free(SDNEWSYMS);
294   return pDict.release();
295 failed:
296   for (I = 0; I < NSYMSDECODED; I++) {
297     if (SDNEWSYMS[I]) {
298       delete SDNEWSYMS[I];
299       SDNEWSYMS[I] = nullptr;
300     }
301   }
302   FX_Free(SDNEWSYMS);
303   return nullptr;
304 }
305
306 CJBig2_SymbolDict* CJBig2_SDDProc::decode_Huffman(CJBig2_BitStream* pStream,
307                                                   JBig2ArithCtx* gbContext,
308                                                   JBig2ArithCtx* grContext,
309                                                   IFX_Pause* pPause) {
310   CJBig2_Image** SDNEWSYMS;
311   FX_DWORD* SDNEWSYMWIDTHS;
312   FX_DWORD HCHEIGHT, NSYMSDECODED;
313   int32_t HCDH;
314   FX_DWORD SYMWIDTH, TOTWIDTH, HCFIRSTSYM;
315   int32_t DW;
316   CJBig2_Image* BS, *BHC;
317   FX_DWORD I, J, REFAGGNINST;
318   FX_BOOL* EXFLAGS;
319   FX_DWORD EXINDEX;
320   FX_BOOL CUREXFLAG;
321   FX_DWORD EXRUNLENGTH;
322   int32_t nVal, nBits;
323   FX_DWORD nTmp;
324   FX_DWORD SBNUMSYMS;
325   uint8_t SBSYMCODELEN;
326   JBig2HuffmanCode* SBSYMCODES;
327   FX_DWORD IDI;
328   int32_t RDXI, RDYI;
329   FX_DWORD BMSIZE;
330   FX_DWORD stride;
331   CJBig2_Image** SBSYMS;
332   nonstd::unique_ptr<CJBig2_HuffmanDecoder> pHuffmanDecoder(
333       new CJBig2_HuffmanDecoder(pStream));
334   SDNEWSYMS = FX_Alloc(CJBig2_Image*, SDNUMNEWSYMS);
335   FXSYS_memset(SDNEWSYMS, 0, SDNUMNEWSYMS * sizeof(CJBig2_Image*));
336   SDNEWSYMWIDTHS = nullptr;
337   BHC = nullptr;
338   if (SDREFAGG == 0) {
339     SDNEWSYMWIDTHS = FX_Alloc(FX_DWORD, SDNUMNEWSYMS);
340     FXSYS_memset(SDNEWSYMWIDTHS, 0, SDNUMNEWSYMS * sizeof(FX_DWORD));
341   }
342   nonstd::unique_ptr<CJBig2_SymbolDict> pDict(new CJBig2_SymbolDict());
343   nonstd::unique_ptr<CJBig2_HuffmanTable> pTable;
344
345   HCHEIGHT = 0;
346   NSYMSDECODED = 0;
347   BS = nullptr;
348   while (NSYMSDECODED < SDNUMNEWSYMS) {
349     if (pHuffmanDecoder->decodeAValue(SDHUFFDH, &HCDH) != 0) {
350       goto failed;
351     }
352     HCHEIGHT = HCHEIGHT + HCDH;
353     if ((int)HCHEIGHT < 0 || (int)HCHEIGHT > JBIG2_MAX_IMAGE_SIZE) {
354       goto failed;
355     }
356     SYMWIDTH = 0;
357     TOTWIDTH = 0;
358     HCFIRSTSYM = NSYMSDECODED;
359     for (;;) {
360       nVal = pHuffmanDecoder->decodeAValue(SDHUFFDW, &DW);
361       if (nVal == JBIG2_OOB) {
362         break;
363       } else if (nVal != 0) {
364         goto failed;
365       } else {
366         if (NSYMSDECODED >= SDNUMNEWSYMS) {
367           goto failed;
368         }
369         SYMWIDTH = SYMWIDTH + DW;
370         if ((int)SYMWIDTH < 0 || (int)SYMWIDTH > JBIG2_MAX_IMAGE_SIZE) {
371           goto failed;
372         } else if (HCHEIGHT == 0 || SYMWIDTH == 0) {
373           TOTWIDTH = TOTWIDTH + SYMWIDTH;
374           SDNEWSYMS[NSYMSDECODED] = nullptr;
375           NSYMSDECODED = NSYMSDECODED + 1;
376           continue;
377         }
378         TOTWIDTH = TOTWIDTH + SYMWIDTH;
379       }
380       if (SDREFAGG == 1) {
381         if (pHuffmanDecoder->decodeAValue(SDHUFFAGGINST, (int*)&REFAGGNINST) !=
382             0) {
383           goto failed;
384         }
385         BS = nullptr;
386         if (REFAGGNINST > 1) {
387           nonstd::unique_ptr<CJBig2_TRDProc> pDecoder(new CJBig2_TRDProc());
388           pDecoder->SBHUFF = SDHUFF;
389           pDecoder->SBREFINE = 1;
390           pDecoder->SBW = SYMWIDTH;
391           pDecoder->SBH = HCHEIGHT;
392           pDecoder->SBNUMINSTANCES = REFAGGNINST;
393           pDecoder->SBSTRIPS = 1;
394           pDecoder->SBNUMSYMS = SDNUMINSYMS + NSYMSDECODED;
395           SBNUMSYMS = pDecoder->SBNUMSYMS;
396           SBSYMCODES = FX_Alloc(JBig2HuffmanCode, SBNUMSYMS);
397           nTmp = 1;
398           while ((FX_DWORD)(1 << nTmp) < SBNUMSYMS) {
399             nTmp++;
400           }
401           for (I = 0; I < SBNUMSYMS; I++) {
402             SBSYMCODES[I].codelen = nTmp;
403             SBSYMCODES[I].code = I;
404           }
405           pDecoder->SBSYMCODES = SBSYMCODES;
406           SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS);
407           JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*));
408           JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS,
409                        NSYMSDECODED * sizeof(CJBig2_Image*));
410           pDecoder->SBSYMS = SBSYMS;
411           pDecoder->SBDEFPIXEL = 0;
412           pDecoder->SBCOMBOP = JBIG2_COMPOSE_OR;
413           pDecoder->TRANSPOSED = 0;
414           pDecoder->REFCORNER = JBIG2_CORNER_TOPLEFT;
415           pDecoder->SBDSOFFSET = 0;
416           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFFS(
417               new CJBig2_HuffmanTable(HuffmanTable_B6,
418                                       FX_ArraySize(HuffmanTable_B6),
419                                       HuffmanTable_HTOOB_B6));
420           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFDS(
421               new CJBig2_HuffmanTable(HuffmanTable_B8,
422                                       FX_ArraySize(HuffmanTable_B8),
423                                       HuffmanTable_HTOOB_B8));
424           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFDT(
425               new CJBig2_HuffmanTable(HuffmanTable_B11,
426                                       FX_ArraySize(HuffmanTable_B11),
427                                       HuffmanTable_HTOOB_B11));
428           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDW(
429               new CJBig2_HuffmanTable(HuffmanTable_B15,
430                                       FX_ArraySize(HuffmanTable_B15),
431                                       HuffmanTable_HTOOB_B15));
432           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDH(
433               new CJBig2_HuffmanTable(HuffmanTable_B15,
434                                       FX_ArraySize(HuffmanTable_B15),
435                                       HuffmanTable_HTOOB_B15));
436           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDX(
437               new CJBig2_HuffmanTable(HuffmanTable_B15,
438                                       FX_ArraySize(HuffmanTable_B15),
439                                       HuffmanTable_HTOOB_B15));
440           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDY(
441               new CJBig2_HuffmanTable(HuffmanTable_B15,
442                                       FX_ArraySize(HuffmanTable_B15),
443                                       HuffmanTable_HTOOB_B15));
444           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRSIZE(
445               new CJBig2_HuffmanTable(HuffmanTable_B1,
446                                       FX_ArraySize(HuffmanTable_B1),
447                                       HuffmanTable_HTOOB_B1));
448           pDecoder->SBHUFFFS = SBHUFFFS.get();
449           pDecoder->SBHUFFDS = SBHUFFDS.get();
450           pDecoder->SBHUFFDT = SBHUFFDT.get();
451           pDecoder->SBHUFFRDW = SBHUFFRDW.get();
452           pDecoder->SBHUFFRDH = SBHUFFRDH.get();
453           pDecoder->SBHUFFRDX = SBHUFFRDX.get();
454           pDecoder->SBHUFFRDY = SBHUFFRDY.get();
455           pDecoder->SBHUFFRSIZE = SBHUFFRSIZE.get();
456           pDecoder->SBRTEMPLATE = SDRTEMPLATE;
457           pDecoder->SBRAT[0] = SDRAT[0];
458           pDecoder->SBRAT[1] = SDRAT[1];
459           pDecoder->SBRAT[2] = SDRAT[2];
460           pDecoder->SBRAT[3] = SDRAT[3];
461           BS = pDecoder->decode_Huffman(pStream, grContext);
462           if (!BS) {
463             FX_Free(SBSYMCODES);
464             FX_Free(SBSYMS);
465             goto failed;
466           }
467           FX_Free(SBSYMCODES);
468           FX_Free(SBSYMS);
469         } else if (REFAGGNINST == 1) {
470           SBNUMSYMS = SDNUMINSYMS + SDNUMNEWSYMS;
471           nTmp = 1;
472           while ((FX_DWORD)(1 << nTmp) < SBNUMSYMS) {
473             nTmp++;
474           }
475           SBSYMCODELEN = (uint8_t)nTmp;
476           SBSYMCODES = FX_Alloc(JBig2HuffmanCode, SBNUMSYMS);
477           for (I = 0; I < SBNUMSYMS; I++) {
478             SBSYMCODES[I].codelen = SBSYMCODELEN;
479             SBSYMCODES[I].code = I;
480           }
481           nVal = 0;
482           nBits = 0;
483           for (;;) {
484             if (pStream->read1Bit(&nTmp) != 0) {
485               FX_Free(SBSYMCODES);
486               goto failed;
487             }
488             nVal = (nVal << 1) | nTmp;
489             for (IDI = 0; IDI < SBNUMSYMS; IDI++) {
490               if ((nVal == SBSYMCODES[IDI].code) &&
491                   (nBits == SBSYMCODES[IDI].codelen)) {
492                 break;
493               }
494             }
495             if (IDI < SBNUMSYMS) {
496               break;
497             }
498           }
499           FX_Free(SBSYMCODES);
500           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDX(
501               new CJBig2_HuffmanTable(HuffmanTable_B15,
502                                       FX_ArraySize(HuffmanTable_B15),
503                                       HuffmanTable_HTOOB_B15));
504           nonstd::unique_ptr<CJBig2_HuffmanTable> SBHUFFRSIZE(
505               new CJBig2_HuffmanTable(HuffmanTable_B1,
506                                       FX_ArraySize(HuffmanTable_B1),
507                                       HuffmanTable_HTOOB_B1));
508           if ((pHuffmanDecoder->decodeAValue(SBHUFFRDX.get(), &RDXI) != 0) ||
509               (pHuffmanDecoder->decodeAValue(SBHUFFRDX.get(), &RDYI) != 0) ||
510               (pHuffmanDecoder->decodeAValue(SBHUFFRSIZE.get(), &nVal) != 0)) {
511             goto failed;
512           }
513           pStream->alignByte();
514           nTmp = pStream->getOffset();
515           SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS);
516           JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*));
517           JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS,
518                        NSYMSDECODED * sizeof(CJBig2_Image*));
519           nonstd::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc());
520           pGRRD->GRW = SYMWIDTH;
521           pGRRD->GRH = HCHEIGHT;
522           pGRRD->GRTEMPLATE = SDRTEMPLATE;
523           pGRRD->GRREFERENCE = SBSYMS[IDI];
524           pGRRD->GRREFERENCEDX = RDXI;
525           pGRRD->GRREFERENCEDY = RDYI;
526           pGRRD->TPGRON = 0;
527           pGRRD->GRAT[0] = SDRAT[0];
528           pGRRD->GRAT[1] = SDRAT[1];
529           pGRRD->GRAT[2] = SDRAT[2];
530           pGRRD->GRAT[3] = SDRAT[3];
531           nonstd::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
532               new CJBig2_ArithDecoder(pStream));
533           BS = pGRRD->decode(pArithDecoder.get(), grContext);
534           if (!BS) {
535             FX_Free(SBSYMS);
536             goto failed;
537           }
538           pStream->alignByte();
539           pStream->offset(2);
540           if ((FX_DWORD)nVal != (pStream->getOffset() - nTmp)) {
541             delete BS;
542             FX_Free(SBSYMS);
543             goto failed;
544           }
545           FX_Free(SBSYMS);
546         }
547         SDNEWSYMS[NSYMSDECODED] = BS;
548       }
549       if (SDREFAGG == 0) {
550         SDNEWSYMWIDTHS[NSYMSDECODED] = SYMWIDTH;
551       }
552       NSYMSDECODED = NSYMSDECODED + 1;
553     }
554     if (SDREFAGG == 0) {
555       if (pHuffmanDecoder->decodeAValue(SDHUFFBMSIZE, (int32_t*)&BMSIZE) != 0) {
556         goto failed;
557       }
558       pStream->alignByte();
559       if (BMSIZE == 0) {
560         stride = (TOTWIDTH + 7) >> 3;
561         if (pStream->getByteLeft() >= stride * HCHEIGHT) {
562           BHC = new CJBig2_Image(TOTWIDTH, HCHEIGHT);
563           for (I = 0; I < HCHEIGHT; I++) {
564             JBIG2_memcpy(BHC->m_pData + I * BHC->m_nStride,
565                          pStream->getPointer(), stride);
566             pStream->offset(stride);
567           }
568         } else {
569           goto failed;
570         }
571       } else {
572         nonstd::unique_ptr<CJBig2_GRDProc> pGRD(new CJBig2_GRDProc());
573         pGRD->MMR = 1;
574         pGRD->GBW = TOTWIDTH;
575         pGRD->GBH = HCHEIGHT;
576         FXCODEC_STATUS status = pGRD->Start_decode_MMR(&BHC, pStream, nullptr);
577         while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
578           pGRD->Continue_decode(pPause);
579         }
580         pStream->alignByte();
581       }
582       nTmp = 0;
583       if (!BHC) {
584         continue;
585       }
586       for (I = HCFIRSTSYM; I < NSYMSDECODED; I++) {
587         SDNEWSYMS[I] = BHC->subImage(nTmp, 0, SDNEWSYMWIDTHS[I], HCHEIGHT);
588         nTmp += SDNEWSYMWIDTHS[I];
589       }
590       delete BHC;
591       BHC = nullptr;
592     }
593   }
594   EXINDEX = 0;
595   CUREXFLAG = 0;
596   pTable.reset(new CJBig2_HuffmanTable(
597       HuffmanTable_B1, FX_ArraySize(HuffmanTable_B1), HuffmanTable_HTOOB_B1));
598   EXFLAGS = FX_Alloc(FX_BOOL, SDNUMINSYMS + SDNUMNEWSYMS);
599   while (EXINDEX < SDNUMINSYMS + SDNUMNEWSYMS) {
600     if (pHuffmanDecoder->decodeAValue(pTable.get(), (int*)&EXRUNLENGTH) != 0) {
601       FX_Free(EXFLAGS);
602       goto failed;
603     }
604     if (EXINDEX + EXRUNLENGTH > SDNUMINSYMS + SDNUMNEWSYMS) {
605       FX_Free(EXFLAGS);
606       goto failed;
607     }
608     if (EXRUNLENGTH != 0) {
609       for (I = EXINDEX; I < EXINDEX + EXRUNLENGTH; I++) {
610         EXFLAGS[I] = CUREXFLAG;
611       }
612     }
613     EXINDEX = EXINDEX + EXRUNLENGTH;
614     CUREXFLAG = !CUREXFLAG;
615   }
616   pDict->SDNUMEXSYMS = SDNUMEXSYMS;
617   pDict->SDEXSYMS = FX_Alloc(CJBig2_Image*, SDNUMEXSYMS);
618   I = J = 0;
619   for (I = 0; I < SDNUMINSYMS + SDNUMNEWSYMS; I++) {
620     if (EXFLAGS[I] && J < SDNUMEXSYMS) {
621       if (I < SDNUMINSYMS) {
622         pDict->SDEXSYMS[J] = new CJBig2_Image(*SDINSYMS[I]);
623       } else {
624         pDict->SDEXSYMS[J] = SDNEWSYMS[I - SDNUMINSYMS];
625       }
626       J = J + 1;
627     } else if (!EXFLAGS[I] && I >= SDNUMINSYMS) {
628       delete SDNEWSYMS[I - SDNUMINSYMS];
629     }
630   }
631   if (J < SDNUMEXSYMS) {
632     pDict->SDNUMEXSYMS = J;
633   }
634   FX_Free(EXFLAGS);
635   FX_Free(SDNEWSYMS);
636   if (SDREFAGG == 0) {
637     FX_Free(SDNEWSYMWIDTHS);
638   }
639   return pDict.release();
640 failed:
641   for (I = 0; I < NSYMSDECODED; I++) {
642     delete SDNEWSYMS[I];
643   }
644   FX_Free(SDNEWSYMS);
645   if (SDREFAGG == 0) {
646     FX_Free(SDNEWSYMWIDTHS);
647   }
648   return nullptr;
649 }