Convert some unneeded gotos into returns.
[pdfium.git] / core / src / fxcodec / jbig2 / JBig2_Context.cpp
1 // Copyright 2014 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 <list>
8 #include "JBig2_Context.h"
9
10 // Implement a very small least recently used (LRU) cache. It is very
11 // common for a JBIG2 dictionary to span multiple pages in a PDF file,
12 // and we do not want to decode the same dictionary over and over
13 // again. We key off of the memory location of the dictionary. The
14 // list keeps track of the freshness of entries, with freshest ones
15 // at the front. Even a tiny cache size like 2 makes a dramatic
16 // difference for typical JBIG2 documents.
17 const int kSymbolDictCacheMaxSize = 2;
18
19 CJBig2_Context* CJBig2_Context::CreateContext(
20     const uint8_t* pGlobalData,
21     FX_DWORD dwGlobalLength,
22     const uint8_t* pData,
23     FX_DWORD dwLength,
24     int32_t nStreamType,
25     std::list<CJBig2_CachePair>* pSymbolDictCache,
26     IFX_Pause* pPause) {
27   return new CJBig2_Context(pGlobalData, dwGlobalLength, pData, dwLength,
28                             nStreamType, pSymbolDictCache, pPause);
29 }
30 void CJBig2_Context::DestroyContext(CJBig2_Context* pContext) {
31   delete pContext;
32 }
33 CJBig2_Context::CJBig2_Context(const uint8_t* pGlobalData,
34                                FX_DWORD dwGlobalLength,
35                                const uint8_t* pData,
36                                FX_DWORD dwLength,
37                                int32_t nStreamType,
38                                std::list<CJBig2_CachePair>* pSymbolDictCache,
39                                IFX_Pause* pPause) {
40   if (pGlobalData && (dwGlobalLength > 0)) {
41     m_pGlobalContext =
42         new CJBig2_Context(NULL, 0, pGlobalData, dwGlobalLength,
43                            JBIG2_EMBED_STREAM, pSymbolDictCache, pPause);
44   } else {
45     m_pGlobalContext = NULL;
46   }
47   m_pStream = new CJBig2_BitStream(pData, dwLength);
48   m_nStreamType = nStreamType;
49   m_nState = JBIG2_OUT_OF_PAGE;
50   m_pPage = NULL;
51   m_bBufSpecified = FALSE;
52   m_pPause = pPause;
53   m_nSegmentDecoded = 0;
54   m_PauseStep = 10;
55   m_pArithDecoder = NULL;
56   m_pGRD = NULL;
57   m_gbContext = NULL;
58   m_dwOffset = 0;
59   m_ProcessiveStatus = FXCODEC_STATUS_FRAME_READY;
60   m_pSymbolDictCache = pSymbolDictCache;
61 }
62 CJBig2_Context::~CJBig2_Context() {
63   delete m_pArithDecoder;
64   m_pArithDecoder = NULL;
65   delete m_pGRD;
66   m_pGRD = NULL;
67   FX_Free(m_gbContext);
68   m_gbContext = NULL;
69   delete m_pGlobalContext;
70   m_pGlobalContext = NULL;
71   if (m_bBufSpecified) {
72     delete m_pPage;
73   }
74   m_pPage = NULL;
75   delete m_pStream;
76   m_pStream = NULL;
77 }
78
79 int32_t CJBig2_Context::decodeFile(IFX_Pause* pPause) {
80   if (m_pStream->getByteLeft() < 8)
81     return JBIG2_ERROR_TOO_SHORT;
82
83   const uint8_t fileID[] = {0x97, 0x4A, 0x42, 0x32, 0x0D, 0x0A, 0x1A, 0x0A};
84   if (JBIG2_memcmp(m_pStream->getPointer(), fileID, 8) != 0)
85     return JBIG2_ERROR_FILE_FORMAT;
86
87   m_pStream->offset(8);
88
89   uint8_t cFlags;
90   if (m_pStream->read1Byte(&cFlags) != 0)
91     return JBIG2_ERROR_TOO_SHORT;
92
93   if (!(cFlags & 0x02)) {
94     FX_DWORD dwTemp;
95     if (m_pStream->readInteger(&dwTemp) != 0)
96       return JBIG2_ERROR_TOO_SHORT;
97
98     if (dwTemp > 0) {
99       m_PageInfoList.clear();
100       m_PageInfoList.resize(dwTemp);
101     }
102   }
103
104   if (cFlags & 0x01) {
105     m_nStreamType = JBIG2_SQUENTIAL_STREAM;
106     return decode_SquentialOrgnazation(pPause);
107   }
108
109   m_nStreamType = JBIG2_RANDOM_STREAM;
110   return decode_RandomOrgnazation_FirstPage(pPause);
111 }
112
113 int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) {
114   int32_t nRet;
115   if (m_pStream->getByteLeft() <= 0)
116     return JBIG2_END_OF_FILE;
117
118   while (m_pStream->getByteLeft() >= JBIG2_MIN_SEGMENT_SIZE) {
119     if (!m_pSegment) {
120       m_pSegment.reset(new CJBig2_Segment);
121       nRet = parseSegmentHeader(m_pSegment.get());
122       if (nRet != JBIG2_SUCCESS) {
123         m_pSegment.reset();
124         return nRet;
125       }
126       m_dwOffset = m_pStream->getOffset();
127     }
128     nRet = parseSegmentData(m_pSegment.get(), pPause);
129     if (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
130       m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
131       m_PauseStep = 2;
132       return JBIG2_SUCCESS;
133     }
134     if ((nRet == JBIG2_END_OF_PAGE) || (nRet == JBIG2_END_OF_FILE)) {
135       m_pSegment.reset();
136       return JBIG2_SUCCESS;
137     }
138     if (nRet != JBIG2_SUCCESS) {
139       m_pSegment.reset();
140       return nRet;
141     }
142     if (m_pSegment->m_dwData_length != 0xffffffff) {
143       m_dwOffset = m_dwOffset + m_pSegment->m_dwData_length;
144       m_pStream->setOffset(m_dwOffset);
145     } else {
146       m_pStream->offset(4);
147     }
148     m_SegmentList.push_back(m_pSegment.release());
149     if (m_pStream->getByteLeft() > 0 && m_pPage && pPause &&
150         pPause->NeedToPauseNow()) {
151       m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
152       m_PauseStep = 2;
153       return JBIG2_SUCCESS;
154     }
155   }
156   return JBIG2_SUCCESS;
157 }
158 int32_t CJBig2_Context::decode_EmbedOrgnazation(IFX_Pause* pPause) {
159   return decode_SquentialOrgnazation(pPause);
160 }
161 int32_t CJBig2_Context::decode_RandomOrgnazation_FirstPage(IFX_Pause* pPause) {
162   int32_t nRet;
163   while (m_pStream->getByteLeft() > JBIG2_MIN_SEGMENT_SIZE) {
164     nonstd::unique_ptr<CJBig2_Segment> pSegment(new CJBig2_Segment);
165     nRet = parseSegmentHeader(pSegment.get());
166     if (nRet != JBIG2_SUCCESS) {
167       return nRet;
168     } else if (pSegment->m_cFlags.s.type == 51) {
169       break;
170     }
171     m_SegmentList.push_back(pSegment.release());
172     if (pPause && m_pPause && pPause->NeedToPauseNow()) {
173       m_PauseStep = 3;
174       m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
175       return JBIG2_SUCCESS;
176     }
177   }
178   m_nSegmentDecoded = 0;
179   return decode_RandomOrgnazation(pPause);
180 }
181 int32_t CJBig2_Context::decode_RandomOrgnazation(IFX_Pause* pPause) {
182   for (; m_nSegmentDecoded < m_SegmentList.size(); ++m_nSegmentDecoded) {
183     int32_t nRet =
184         parseSegmentData(m_SegmentList.get(m_nSegmentDecoded), pPause);
185     if ((nRet == JBIG2_END_OF_PAGE) || (nRet == JBIG2_END_OF_FILE))
186       return JBIG2_SUCCESS;
187
188     if (nRet != JBIG2_SUCCESS)
189       return nRet;
190
191     if (m_pPage && pPause && pPause->NeedToPauseNow()) {
192       m_PauseStep = 4;
193       m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
194       return JBIG2_SUCCESS;
195     }
196   }
197   return JBIG2_SUCCESS;
198 }
199 int32_t CJBig2_Context::getFirstPage(uint8_t* pBuf,
200                                      int32_t width,
201                                      int32_t height,
202                                      int32_t stride,
203                                      IFX_Pause* pPause) {
204   int32_t nRet = 0;
205   if (m_pGlobalContext) {
206     nRet = m_pGlobalContext->decode_EmbedOrgnazation(pPause);
207     if (nRet != JBIG2_SUCCESS) {
208       m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
209       return nRet;
210     }
211   }
212   m_bFirstPage = TRUE;
213   m_PauseStep = 0;
214   delete m_pPage;
215   m_pPage = new CJBig2_Image(width, height, stride, pBuf);
216   m_bBufSpecified = TRUE;
217   if (m_pPage && pPause && pPause->NeedToPauseNow()) {
218     m_PauseStep = 1;
219     m_ProcessiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
220     return nRet;
221   }
222   int ret = Continue(pPause);
223   return ret;
224 }
225 int32_t CJBig2_Context::Continue(IFX_Pause* pPause) {
226   m_ProcessiveStatus = FXCODEC_STATUS_DECODE_READY;
227   int32_t nRet;
228   if (m_PauseStep <= 1) {
229     switch (m_nStreamType) {
230       case JBIG2_FILE_STREAM:
231         nRet = decodeFile(pPause);
232         break;
233       case JBIG2_SQUENTIAL_STREAM:
234         nRet = decode_SquentialOrgnazation(pPause);
235         break;
236       case JBIG2_RANDOM_STREAM:
237         if (m_bFirstPage) {
238           nRet = decode_RandomOrgnazation_FirstPage(pPause);
239         } else {
240           nRet = decode_RandomOrgnazation(pPause);
241         }
242         break;
243       case JBIG2_EMBED_STREAM:
244         nRet = decode_EmbedOrgnazation(pPause);
245         break;
246       default:
247         m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
248         return JBIG2_ERROR_STREAM_TYPE;
249     }
250   } else if (m_PauseStep == 2) {
251     nRet = decode_SquentialOrgnazation(pPause);
252   } else if (m_PauseStep == 3) {
253     nRet = decode_RandomOrgnazation_FirstPage(pPause);
254   } else if (m_PauseStep == 4) {
255     nRet = decode_RandomOrgnazation(pPause);
256   } else if (m_PauseStep == 5) {
257     m_ProcessiveStatus = FXCODEC_STATUS_DECODE_FINISH;
258     return JBIG2_SUCCESS;
259   }
260   if (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
261     return nRet;
262   }
263   m_PauseStep = 5;
264   if (!m_bBufSpecified && nRet == JBIG2_SUCCESS) {
265     m_ProcessiveStatus = FXCODEC_STATUS_DECODE_FINISH;
266     return JBIG2_SUCCESS;
267   }
268   if (nRet == JBIG2_SUCCESS) {
269     m_ProcessiveStatus = FXCODEC_STATUS_DECODE_FINISH;
270   } else {
271     m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
272   }
273   return nRet;
274 }
275 int32_t CJBig2_Context::getFirstPage(CJBig2_Image** image, IFX_Pause* pPause) {
276   int32_t nRet;
277   m_bFirstPage = TRUE;
278   m_PauseStep = 0;
279   if (m_pGlobalContext) {
280     nRet = m_pGlobalContext->decode_EmbedOrgnazation(pPause);
281     if (nRet != JBIG2_SUCCESS) {
282       return nRet;
283     }
284   }
285   m_bBufSpecified = FALSE;
286   return Continue(pPause);
287 }
288 CJBig2_Segment* CJBig2_Context::findSegmentByNumber(FX_DWORD dwNumber) {
289   CJBig2_Segment* pSeg;
290   if (m_pGlobalContext) {
291     pSeg = m_pGlobalContext->findSegmentByNumber(dwNumber);
292     if (pSeg) {
293       return pSeg;
294     }
295   }
296   for (size_t i = 0; i < m_SegmentList.size(); ++i) {
297     pSeg = m_SegmentList.get(i);
298     if (pSeg->m_dwNumber == dwNumber) {
299       return pSeg;
300     }
301   }
302   return nullptr;
303 }
304 CJBig2_Segment* CJBig2_Context::findReferredSegmentByTypeAndIndex(
305     CJBig2_Segment* pSegment,
306     uint8_t cType,
307     int32_t nIndex) {
308   CJBig2_Segment* pSeg;
309   int32_t i, count;
310   count = 0;
311   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
312     pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
313     if (pSeg && pSeg->m_cFlags.s.type == cType) {
314       if (count == nIndex) {
315         return pSeg;
316       } else {
317         count++;
318       }
319     }
320   }
321   return NULL;
322 }
323 int32_t CJBig2_Context::parseSegmentHeader(CJBig2_Segment* pSegment) {
324   if ((m_pStream->readInteger(&pSegment->m_dwNumber) != 0) ||
325       (m_pStream->read1Byte(&pSegment->m_cFlags.c) != 0)) {
326     return JBIG2_ERROR_TOO_SHORT;
327   }
328
329   FX_DWORD dwTemp;
330   uint8_t cTemp = m_pStream->getCurByte();
331   if ((cTemp >> 5) == 7) {
332     if (m_pStream->readInteger(
333             (FX_DWORD*)&pSegment->m_nReferred_to_segment_count) != 0) {
334       return JBIG2_ERROR_TOO_SHORT;
335     }
336     pSegment->m_nReferred_to_segment_count &= 0x1fffffff;
337     if (pSegment->m_nReferred_to_segment_count >
338         JBIG2_MAX_REFERRED_SEGMENT_COUNT) {
339       return JBIG2_ERROR_LIMIT;
340     }
341     dwTemp = 5 + 4 + (pSegment->m_nReferred_to_segment_count + 1) / 8;
342   } else {
343     if (m_pStream->read1Byte(&cTemp) != 0)
344       return JBIG2_ERROR_TOO_SHORT;
345
346     pSegment->m_nReferred_to_segment_count = cTemp >> 5;
347     dwTemp = 5 + 1;
348   }
349   uint8_t cSSize =
350       pSegment->m_dwNumber > 65536 ? 4 : pSegment->m_dwNumber > 256 ? 2 : 1;
351   uint8_t cPSize = pSegment->m_cFlags.s.page_association_size ? 4 : 1;
352   if (pSegment->m_nReferred_to_segment_count) {
353     pSegment->m_pReferred_to_segment_numbers =
354         FX_Alloc(FX_DWORD, pSegment->m_nReferred_to_segment_count);
355     for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
356       switch (cSSize) {
357         case 1:
358           if (m_pStream->read1Byte(&cTemp) != 0)
359             return JBIG2_ERROR_TOO_SHORT;
360
361           pSegment->m_pReferred_to_segment_numbers[i] = cTemp;
362           break;
363         case 2:
364           FX_WORD wTemp;
365           if (m_pStream->readShortInteger(&wTemp) != 0)
366             return JBIG2_ERROR_TOO_SHORT;
367
368           pSegment->m_pReferred_to_segment_numbers[i] = wTemp;
369           break;
370         case 4:
371           if (m_pStream->readInteger(&dwTemp) != 0)
372             return JBIG2_ERROR_TOO_SHORT;
373
374           pSegment->m_pReferred_to_segment_numbers[i] = dwTemp;
375           break;
376       }
377       if (pSegment->m_pReferred_to_segment_numbers[i] >= pSegment->m_dwNumber)
378         return JBIG2_ERROR_TOO_SHORT;
379     }
380   }
381   if (cPSize == 1) {
382     if (m_pStream->read1Byte(&cTemp) != 0)
383       return JBIG2_ERROR_TOO_SHORT;
384     pSegment->m_dwPage_association = cTemp;
385   } else {
386     if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) {
387       return JBIG2_ERROR_TOO_SHORT;
388     }
389   }
390   if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0)
391     return JBIG2_ERROR_TOO_SHORT;
392
393   pSegment->m_pData = m_pStream->getPointer();
394   pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED;
395   return JBIG2_SUCCESS;
396 }
397
398 int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment,
399                                          IFX_Pause* pPause) {
400   int32_t ret = ProcessiveParseSegmentData(pSegment, pPause);
401   while (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE &&
402          m_pStream->getByteLeft() > 0) {
403     ret = ProcessiveParseSegmentData(pSegment, pPause);
404   }
405   return ret;
406 }
407
408 int32_t CJBig2_Context::ProcessiveParseSegmentData(CJBig2_Segment* pSegment,
409                                                    IFX_Pause* pPause) {
410   switch (pSegment->m_cFlags.s.type) {
411     case 0:
412       return parseSymbolDict(pSegment, pPause);
413     case 4:
414     case 6:
415     case 7:
416       if (m_nState == JBIG2_OUT_OF_PAGE)
417         return JBIG2_ERROR_FATAL;
418       return parseTextRegion(pSegment);
419     case 16:
420       return parsePatternDict(pSegment, pPause);
421     case 20:
422     case 22:
423     case 23:
424       if (m_nState == JBIG2_OUT_OF_PAGE)
425         return JBIG2_ERROR_FATAL;
426       return parseHalftoneRegion(pSegment, pPause);
427     case 36:
428     case 38:
429     case 39:
430       if (m_nState == JBIG2_OUT_OF_PAGE)
431         return JBIG2_ERROR_FATAL;
432       return parseGenericRegion(pSegment, pPause);
433     case 40:
434     case 42:
435     case 43:
436       if (m_nState == JBIG2_OUT_OF_PAGE)
437         return JBIG2_ERROR_FATAL;
438       return parseGenericRefinementRegion(pSegment);
439     case 48: {
440       FX_WORD wTemp;
441       nonstd::unique_ptr<JBig2PageInfo> pPageInfo(new JBig2PageInfo);
442       if ((m_pStream->readInteger(&pPageInfo->m_dwWidth) != 0) ||
443           (m_pStream->readInteger(&pPageInfo->m_dwHeight) != 0) ||
444           (m_pStream->readInteger(&pPageInfo->m_dwResolutionX) != 0) ||
445           (m_pStream->readInteger(&pPageInfo->m_dwResolutionY) != 0) ||
446           (m_pStream->read1Byte(&pPageInfo->m_cFlags) != 0) ||
447           (m_pStream->readShortInteger(&wTemp) != 0)) {
448         return JBIG2_ERROR_TOO_SHORT;
449       }
450       pPageInfo->m_bIsStriped = ((wTemp >> 15) & 1) ? TRUE : FALSE;
451       pPageInfo->m_wMaxStripeSize = wTemp & 0x7fff;
452       bool bMaxHeight = (pPageInfo->m_dwHeight == 0xffffffff);
453       if (bMaxHeight && pPageInfo->m_bIsStriped != TRUE)
454         pPageInfo->m_bIsStriped = TRUE;
455
456       if (!m_bBufSpecified) {
457         delete m_pPage;
458         FX_DWORD height =
459             bMaxHeight ? pPageInfo->m_wMaxStripeSize : pPageInfo->m_dwHeight;
460         m_pPage = new CJBig2_Image(pPageInfo->m_dwWidth, height);
461       }
462
463       if (!m_pPage->m_pData) {
464         m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
465         return JBIG2_ERROR_TOO_SHORT;
466       }
467
468       m_pPage->fill((pPageInfo->m_cFlags & 4) ? 1 : 0);
469       m_PageInfoList.push_back(pPageInfo.release());
470       m_nState = JBIG2_IN_PAGE;
471     } break;
472     case 49:
473       m_nState = JBIG2_OUT_OF_PAGE;
474       return JBIG2_END_OF_PAGE;
475       break;
476     case 50:
477       m_pStream->offset(pSegment->m_dwData_length);
478       break;
479     case 51:
480       return JBIG2_END_OF_FILE;
481     case 52:
482       m_pStream->offset(pSegment->m_dwData_length);
483       break;
484     case 53:
485       return parseTable(pSegment);
486     case 62:
487       m_pStream->offset(pSegment->m_dwData_length);
488       break;
489     default:
490       break;
491   }
492   return JBIG2_SUCCESS;
493 }
494
495 int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment,
496                                         IFX_Pause* pPause) {
497   FX_DWORD dwTemp;
498   FX_WORD wFlags;
499   uint8_t cSDHUFFDH, cSDHUFFDW, cSDHUFFBMSIZE, cSDHUFFAGGINST;
500   CJBig2_HuffmanTable *Table_B1 = NULL, *Table_B2 = NULL, *Table_B3 = NULL,
501                       *Table_B4 = NULL, *Table_B5 = NULL;
502   int32_t i, nIndex, nRet;
503   CJBig2_Segment *pSeg = NULL, *pLRSeg = NULL;
504   FX_BOOL bUsed;
505   CJBig2_Image** SDINSYMS = NULL;
506   JBig2ArithCtx *gbContext = NULL, *grContext = NULL;
507   CJBig2_ArithDecoder* pArithDecoder;
508   CJBig2_SDDProc* pSymbolDictDecoder = new CJBig2_SDDProc();
509   const uint8_t* key = pSegment->m_pData;
510   FX_BOOL cache_hit = false;
511   if (m_pStream->readShortInteger(&wFlags) != 0) {
512     nRet = JBIG2_ERROR_TOO_SHORT;
513     goto failed;
514   }
515   pSymbolDictDecoder->SDHUFF = wFlags & 0x0001;
516   pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001;
517   pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003;
518   pSymbolDictDecoder->SDRTEMPLATE = (wFlags >> 12) & 0x0003;
519   cSDHUFFDH = (wFlags >> 2) & 0x0003;
520   cSDHUFFDW = (wFlags >> 4) & 0x0003;
521   cSDHUFFBMSIZE = (wFlags >> 6) & 0x0001;
522   cSDHUFFAGGINST = (wFlags >> 7) & 0x0001;
523   if (pSymbolDictDecoder->SDHUFF == 0) {
524     if (pSymbolDictDecoder->SDTEMPLATE == 0) {
525       dwTemp = 8;
526     } else {
527       dwTemp = 2;
528     }
529     for (i = 0; i < (int32_t)dwTemp; i++) {
530       if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDAT[i]) != 0) {
531         nRet = JBIG2_ERROR_TOO_SHORT;
532         goto failed;
533       }
534     }
535   }
536   if ((pSymbolDictDecoder->SDREFAGG == 1) &&
537       (pSymbolDictDecoder->SDRTEMPLATE == 0)) {
538     for (i = 0; i < 4; i++) {
539       if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDRAT[i]) != 0) {
540         nRet = JBIG2_ERROR_TOO_SHORT;
541         goto failed;
542       }
543     }
544   }
545   if ((m_pStream->readInteger(&pSymbolDictDecoder->SDNUMEXSYMS) != 0) ||
546       (m_pStream->readInteger(&pSymbolDictDecoder->SDNUMNEWSYMS) != 0)) {
547     nRet = JBIG2_ERROR_TOO_SHORT;
548     goto failed;
549   }
550   if (pSymbolDictDecoder->SDNUMEXSYMS > JBIG2_MAX_EXPORT_SYSMBOLS ||
551       pSymbolDictDecoder->SDNUMNEWSYMS > JBIG2_MAX_NEW_SYSMBOLS) {
552     nRet = JBIG2_ERROR_LIMIT;
553     goto failed;
554   }
555   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
556     if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i])) {
557       nRet = JBIG2_ERROR_FATAL;
558       goto failed;
559     }
560   }
561   pSymbolDictDecoder->SDNUMINSYMS = 0;
562   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
563     pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
564     if (pSeg->m_cFlags.s.type == 0) {
565       pSymbolDictDecoder->SDNUMINSYMS += pSeg->m_Result.sd->SDNUMEXSYMS;
566       pLRSeg = pSeg;
567     }
568   }
569   if (pSymbolDictDecoder->SDNUMINSYMS == 0) {
570     SDINSYMS = NULL;
571   } else {
572     SDINSYMS = FX_Alloc(CJBig2_Image*, pSymbolDictDecoder->SDNUMINSYMS);
573     dwTemp = 0;
574     for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
575       pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
576       if (pSeg->m_cFlags.s.type == 0) {
577         JBIG2_memcpy(SDINSYMS + dwTemp, pSeg->m_Result.sd->SDEXSYMS,
578                      pSeg->m_Result.sd->SDNUMEXSYMS * sizeof(CJBig2_Image*));
579         dwTemp += pSeg->m_Result.sd->SDNUMEXSYMS;
580       }
581     }
582   }
583   pSymbolDictDecoder->SDINSYMS = SDINSYMS;
584   if (pSymbolDictDecoder->SDHUFF == 1) {
585     if ((cSDHUFFDH == 2) || (cSDHUFFDW == 2)) {
586       nRet = JBIG2_ERROR_FATAL;
587       goto failed;
588     }
589     nIndex = 0;
590     if (cSDHUFFDH == 0) {
591       Table_B4 = new CJBig2_HuffmanTable(HuffmanTable_B4,
592                                          FX_ArraySize(HuffmanTable_B4),
593                                          HuffmanTable_HTOOB_B4);
594       pSymbolDictDecoder->SDHUFFDH = Table_B4;
595     } else if (cSDHUFFDH == 1) {
596       Table_B5 = new CJBig2_HuffmanTable(HuffmanTable_B5,
597                                          FX_ArraySize(HuffmanTable_B5),
598                                          HuffmanTable_HTOOB_B5);
599       pSymbolDictDecoder->SDHUFFDH = Table_B5;
600     } else {
601       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
602       if (!pSeg) {
603         nRet = JBIG2_ERROR_FATAL;
604         goto failed;
605       }
606       pSymbolDictDecoder->SDHUFFDH = pSeg->m_Result.ht;
607     }
608     if (cSDHUFFDW == 0) {
609       Table_B2 = new CJBig2_HuffmanTable(HuffmanTable_B2,
610                                          FX_ArraySize(HuffmanTable_B2),
611                                          HuffmanTable_HTOOB_B2);
612       pSymbolDictDecoder->SDHUFFDW = Table_B2;
613     } else if (cSDHUFFDW == 1) {
614       Table_B3 = new CJBig2_HuffmanTable(HuffmanTable_B3,
615                                          FX_ArraySize(HuffmanTable_B3),
616                                          HuffmanTable_HTOOB_B3);
617       pSymbolDictDecoder->SDHUFFDW = Table_B3;
618     } else {
619       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
620       if (!pSeg) {
621         nRet = JBIG2_ERROR_FATAL;
622         goto failed;
623       }
624       pSymbolDictDecoder->SDHUFFDW = pSeg->m_Result.ht;
625     }
626     if (cSDHUFFBMSIZE == 0) {
627       Table_B1 = new CJBig2_HuffmanTable(HuffmanTable_B1,
628                                          FX_ArraySize(HuffmanTable_B1),
629                                          HuffmanTable_HTOOB_B1);
630       pSymbolDictDecoder->SDHUFFBMSIZE = Table_B1;
631     } else {
632       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
633       if (!pSeg) {
634         nRet = JBIG2_ERROR_FATAL;
635         goto failed;
636       }
637       pSymbolDictDecoder->SDHUFFBMSIZE = pSeg->m_Result.ht;
638     }
639     if (pSymbolDictDecoder->SDREFAGG == 1) {
640       if (cSDHUFFAGGINST == 0) {
641         if (!Table_B1) {
642           Table_B1 = new CJBig2_HuffmanTable(HuffmanTable_B1,
643                                              FX_ArraySize(HuffmanTable_B1),
644                                              HuffmanTable_HTOOB_B1);
645         }
646         pSymbolDictDecoder->SDHUFFAGGINST = Table_B1;
647       } else {
648         pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
649         if (!pSeg) {
650           nRet = JBIG2_ERROR_FATAL;
651           goto failed;
652         }
653         pSymbolDictDecoder->SDHUFFAGGINST = pSeg->m_Result.ht;
654       }
655     }
656   }
657   if ((wFlags & 0x0100) && pLRSeg && pLRSeg->m_Result.sd->m_bContextRetained) {
658     if (pSymbolDictDecoder->SDHUFF == 0) {
659       dwTemp = pSymbolDictDecoder->SDTEMPLATE == 0
660                    ? 65536
661                    : pSymbolDictDecoder->SDTEMPLATE == 1 ? 8192 : 1024;
662       gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
663       JBIG2_memcpy(gbContext, pLRSeg->m_Result.sd->m_gbContext,
664                    sizeof(JBig2ArithCtx) * dwTemp);
665     }
666     if (pSymbolDictDecoder->SDREFAGG == 1) {
667       dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13;
668       grContext = FX_Alloc(JBig2ArithCtx, dwTemp);
669       JBIG2_memcpy(grContext, pLRSeg->m_Result.sd->m_grContext,
670                    sizeof(JBig2ArithCtx) * dwTemp);
671     }
672   } else {
673     if (pSymbolDictDecoder->SDHUFF == 0) {
674       dwTemp = pSymbolDictDecoder->SDTEMPLATE == 0
675                    ? 65536
676                    : pSymbolDictDecoder->SDTEMPLATE == 1 ? 8192 : 1024;
677       gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
678       JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
679     }
680     if (pSymbolDictDecoder->SDREFAGG == 1) {
681       dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13;
682       grContext = FX_Alloc(JBig2ArithCtx, dwTemp);
683       JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
684     }
685   }
686   pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER;
687   for (std::list<CJBig2_CachePair>::iterator it = m_pSymbolDictCache->begin();
688        it != m_pSymbolDictCache->end(); ++it) {
689     if (it->first == key) {
690       pSegment->m_Result.sd = it->second->DeepCopy();
691       m_pSymbolDictCache->push_front(*it);
692       m_pSymbolDictCache->erase(it);
693       cache_hit = true;
694       break;
695     }
696   }
697   if (!cache_hit) {
698     if (pSymbolDictDecoder->SDHUFF == 0) {
699       pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
700       pSegment->m_Result.sd =
701           pSymbolDictDecoder->decode_Arith(pArithDecoder, gbContext, grContext);
702       delete pArithDecoder;
703       if (pSegment->m_Result.sd == NULL) {
704         nRet = JBIG2_ERROR_FATAL;
705         goto failed;
706       }
707       m_pStream->alignByte();
708       m_pStream->offset(2);
709     } else {
710       pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(
711           m_pStream, gbContext, grContext, pPause);
712       if (pSegment->m_Result.sd == NULL) {
713         nRet = JBIG2_ERROR_FATAL;
714         goto failed;
715       }
716       m_pStream->alignByte();
717     }
718     CJBig2_SymbolDict* value = pSegment->m_Result.sd->DeepCopy();
719     if (value && kSymbolDictCacheMaxSize > 0) {
720       while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) {
721         delete m_pSymbolDictCache->back().second;
722         m_pSymbolDictCache->pop_back();
723       }
724       m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value));
725     }
726   }
727   if (wFlags & 0x0200) {
728     pSegment->m_Result.sd->m_bContextRetained = TRUE;
729     if (pSymbolDictDecoder->SDHUFF == 0) {
730       pSegment->m_Result.sd->m_gbContext = gbContext;
731     }
732     if (pSymbolDictDecoder->SDREFAGG == 1) {
733       pSegment->m_Result.sd->m_grContext = grContext;
734     }
735     bUsed = TRUE;
736   } else {
737     bUsed = FALSE;
738   }
739   delete pSymbolDictDecoder;
740   FX_Free(SDINSYMS);
741   delete Table_B1;
742   delete Table_B2;
743   delete Table_B3;
744   delete Table_B4;
745   delete Table_B5;
746   if (bUsed == FALSE) {
747     FX_Free(gbContext);
748     FX_Free(grContext);
749   }
750   return JBIG2_SUCCESS;
751 failed:
752   delete pSymbolDictDecoder;
753   FX_Free(SDINSYMS);
754   delete Table_B1;
755   delete Table_B2;
756   delete Table_B3;
757   delete Table_B4;
758   delete Table_B5;
759   FX_Free(gbContext);
760   FX_Free(grContext);
761   return nRet;
762 }
763
764 int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) {
765   FX_DWORD dwTemp;
766   FX_WORD wFlags;
767   int32_t i, nIndex, nRet;
768   JBig2RegionInfo ri;
769   CJBig2_Segment* pSeg;
770   CJBig2_Image** SBSYMS = NULL;
771   JBig2HuffmanCode* SBSYMCODES = NULL;
772   uint8_t cSBHUFFFS, cSBHUFFDS, cSBHUFFDT, cSBHUFFRDW, cSBHUFFRDH, cSBHUFFRDX,
773       cSBHUFFRDY, cSBHUFFRSIZE;
774   CJBig2_HuffmanTable *Table_B1 = NULL, *Table_B6 = NULL, *Table_B7 = NULL,
775                       *Table_B8 = NULL, *Table_B9 = NULL, *Table_B10 = NULL,
776                       *Table_B11 = NULL, *Table_B12 = NULL, *Table_B13 = NULL,
777                       *Table_B14 = NULL, *Table_B15 = NULL;
778   JBig2ArithCtx* grContext = NULL;
779   CJBig2_ArithDecoder* pArithDecoder;
780   CJBig2_TRDProc* pTRD = new CJBig2_TRDProc();
781   if ((parseRegionInfo(&ri) != JBIG2_SUCCESS) ||
782       (m_pStream->readShortInteger(&wFlags) != 0)) {
783     nRet = JBIG2_ERROR_TOO_SHORT;
784     goto failed;
785   }
786   pTRD->SBW = ri.width;
787   pTRD->SBH = ri.height;
788   pTRD->SBHUFF = wFlags & 0x0001;
789   pTRD->SBREFINE = (wFlags >> 1) & 0x0001;
790   dwTemp = (wFlags >> 2) & 0x0003;
791   pTRD->SBSTRIPS = 1 << dwTemp;
792   pTRD->REFCORNER = (JBig2Corner)((wFlags >> 4) & 0x0003);
793   pTRD->TRANSPOSED = (wFlags >> 6) & 0x0001;
794   pTRD->SBCOMBOP = (JBig2ComposeOp)((wFlags >> 7) & 0x0003);
795   pTRD->SBDEFPIXEL = (wFlags >> 9) & 0x0001;
796   pTRD->SBDSOFFSET = (wFlags >> 10) & 0x001f;
797   if (pTRD->SBDSOFFSET >= 0x0010) {
798     pTRD->SBDSOFFSET = pTRD->SBDSOFFSET - 0x0020;
799   }
800   pTRD->SBRTEMPLATE = (wFlags >> 15) & 0x0001;
801   if (pTRD->SBHUFF == 1) {
802     if (m_pStream->readShortInteger(&wFlags) != 0) {
803       nRet = JBIG2_ERROR_TOO_SHORT;
804       goto failed;
805     }
806     cSBHUFFFS = wFlags & 0x0003;
807     cSBHUFFDS = (wFlags >> 2) & 0x0003;
808     cSBHUFFDT = (wFlags >> 4) & 0x0003;
809     cSBHUFFRDW = (wFlags >> 6) & 0x0003;
810     cSBHUFFRDH = (wFlags >> 8) & 0x0003;
811     cSBHUFFRDX = (wFlags >> 10) & 0x0003;
812     cSBHUFFRDY = (wFlags >> 12) & 0x0003;
813     cSBHUFFRSIZE = (wFlags >> 14) & 0x0001;
814   }
815   if ((pTRD->SBREFINE == 1) && (pTRD->SBRTEMPLATE == 0)) {
816     for (i = 0; i < 4; i++) {
817       if (m_pStream->read1Byte((uint8_t*)&pTRD->SBRAT[i]) != 0) {
818         nRet = JBIG2_ERROR_TOO_SHORT;
819         goto failed;
820       }
821     }
822   }
823   if (m_pStream->readInteger(&pTRD->SBNUMINSTANCES) != 0) {
824     nRet = JBIG2_ERROR_TOO_SHORT;
825     goto failed;
826   }
827   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
828     if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i])) {
829       nRet = JBIG2_ERROR_FATAL;
830       goto failed;
831     }
832   }
833   pTRD->SBNUMSYMS = 0;
834   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
835     pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
836     if (pSeg->m_cFlags.s.type == 0) {
837       pTRD->SBNUMSYMS += pSeg->m_Result.sd->SDNUMEXSYMS;
838     }
839   }
840   if (pTRD->SBNUMSYMS > 0) {
841     SBSYMS = FX_Alloc(CJBig2_Image*, pTRD->SBNUMSYMS);
842     dwTemp = 0;
843     for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
844       pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
845       if (pSeg->m_cFlags.s.type == 0) {
846         JBIG2_memcpy(SBSYMS + dwTemp, pSeg->m_Result.sd->SDEXSYMS,
847                      pSeg->m_Result.sd->SDNUMEXSYMS * sizeof(CJBig2_Image*));
848         dwTemp += pSeg->m_Result.sd->SDNUMEXSYMS;
849       }
850     }
851     pTRD->SBSYMS = SBSYMS;
852   } else {
853     pTRD->SBSYMS = NULL;
854   }
855   if (pTRD->SBHUFF == 1) {
856     SBSYMCODES = decodeSymbolIDHuffmanTable(m_pStream, pTRD->SBNUMSYMS);
857     if (SBSYMCODES == NULL) {
858       nRet = JBIG2_ERROR_FATAL;
859       goto failed;
860     }
861     m_pStream->alignByte();
862     pTRD->SBSYMCODES = SBSYMCODES;
863   } else {
864     dwTemp = 0;
865     while ((FX_DWORD)(1 << dwTemp) < pTRD->SBNUMSYMS) {
866       dwTemp++;
867     }
868     pTRD->SBSYMCODELEN = (uint8_t)dwTemp;
869   }
870   if (pTRD->SBHUFF == 1) {
871     if ((cSBHUFFFS == 2) || (cSBHUFFRDW == 2) || (cSBHUFFRDH == 2) ||
872         (cSBHUFFRDX == 2) || (cSBHUFFRDY == 2)) {
873       nRet = JBIG2_ERROR_FATAL;
874       goto failed;
875     }
876     nIndex = 0;
877     if (cSBHUFFFS == 0) {
878       Table_B6 = new CJBig2_HuffmanTable(HuffmanTable_B6,
879                                          FX_ArraySize(HuffmanTable_B6),
880                                          HuffmanTable_HTOOB_B6);
881       pTRD->SBHUFFFS = Table_B6;
882     } else if (cSBHUFFFS == 1) {
883       Table_B7 = new CJBig2_HuffmanTable(HuffmanTable_B7,
884                                          FX_ArraySize(HuffmanTable_B7),
885                                          HuffmanTable_HTOOB_B7);
886       pTRD->SBHUFFFS = Table_B7;
887     } else {
888       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
889       if (!pSeg) {
890         nRet = JBIG2_ERROR_FATAL;
891         goto failed;
892       }
893       pTRD->SBHUFFFS = pSeg->m_Result.ht;
894     }
895     if (cSBHUFFDS == 0) {
896       Table_B8 = new CJBig2_HuffmanTable(HuffmanTable_B8,
897                                          FX_ArraySize(HuffmanTable_B8),
898                                          HuffmanTable_HTOOB_B8);
899       pTRD->SBHUFFDS = Table_B8;
900     } else if (cSBHUFFDS == 1) {
901       Table_B9 = new CJBig2_HuffmanTable(HuffmanTable_B9,
902                                          FX_ArraySize(HuffmanTable_B9),
903                                          HuffmanTable_HTOOB_B9);
904       pTRD->SBHUFFDS = Table_B9;
905     } else if (cSBHUFFDS == 2) {
906       Table_B10 = new CJBig2_HuffmanTable(HuffmanTable_B10,
907                                           FX_ArraySize(HuffmanTable_B10),
908                                           HuffmanTable_HTOOB_B10);
909       pTRD->SBHUFFDS = Table_B10;
910     } else {
911       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
912       if (!pSeg) {
913         nRet = JBIG2_ERROR_FATAL;
914         goto failed;
915       }
916       pTRD->SBHUFFDS = pSeg->m_Result.ht;
917     }
918     if (cSBHUFFDT == 0) {
919       Table_B11 = new CJBig2_HuffmanTable(HuffmanTable_B11,
920                                           FX_ArraySize(HuffmanTable_B11),
921                                           HuffmanTable_HTOOB_B11);
922       pTRD->SBHUFFDT = Table_B11;
923     } else if (cSBHUFFDT == 1) {
924       Table_B12 = new CJBig2_HuffmanTable(HuffmanTable_B12,
925                                           FX_ArraySize(HuffmanTable_B12),
926                                           HuffmanTable_HTOOB_B12);
927       pTRD->SBHUFFDT = Table_B12;
928     } else if (cSBHUFFDT == 2) {
929       Table_B13 = new CJBig2_HuffmanTable(HuffmanTable_B13,
930                                           FX_ArraySize(HuffmanTable_B13),
931                                           HuffmanTable_HTOOB_B13);
932       pTRD->SBHUFFDT = Table_B13;
933     } else {
934       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
935       if (!pSeg) {
936         nRet = JBIG2_ERROR_FATAL;
937         goto failed;
938       }
939       pTRD->SBHUFFDT = pSeg->m_Result.ht;
940     }
941     if (cSBHUFFRDW == 0) {
942       Table_B14 = new CJBig2_HuffmanTable(HuffmanTable_B14,
943                                           FX_ArraySize(HuffmanTable_B14),
944                                           HuffmanTable_HTOOB_B14);
945       pTRD->SBHUFFRDW = Table_B14;
946     } else if (cSBHUFFRDW == 1) {
947       Table_B15 = new CJBig2_HuffmanTable(HuffmanTable_B15,
948                                           FX_ArraySize(HuffmanTable_B15),
949                                           HuffmanTable_HTOOB_B15);
950       pTRD->SBHUFFRDW = Table_B15;
951     } else {
952       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
953       if (!pSeg) {
954         nRet = JBIG2_ERROR_FATAL;
955         goto failed;
956       }
957       pTRD->SBHUFFRDW = pSeg->m_Result.ht;
958     }
959     if (cSBHUFFRDH == 0) {
960       if (!Table_B14) {
961         Table_B14 = new CJBig2_HuffmanTable(HuffmanTable_B14,
962                                             FX_ArraySize(HuffmanTable_B14),
963                                             HuffmanTable_HTOOB_B14);
964       }
965       pTRD->SBHUFFRDH = Table_B14;
966     } else if (cSBHUFFRDH == 1) {
967       if (!Table_B15) {
968         Table_B15 = new CJBig2_HuffmanTable(HuffmanTable_B15,
969                                             FX_ArraySize(HuffmanTable_B15),
970                                             HuffmanTable_HTOOB_B15);
971       }
972       pTRD->SBHUFFRDH = Table_B15;
973     } else {
974       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
975       if (!pSeg) {
976         nRet = JBIG2_ERROR_FATAL;
977         goto failed;
978       }
979       pTRD->SBHUFFRDH = pSeg->m_Result.ht;
980     }
981     if (cSBHUFFRDX == 0) {
982       if (!Table_B14) {
983         Table_B14 = new CJBig2_HuffmanTable(HuffmanTable_B14,
984                                             FX_ArraySize(HuffmanTable_B14),
985                                             HuffmanTable_HTOOB_B14);
986       }
987       pTRD->SBHUFFRDX = Table_B14;
988     } else if (cSBHUFFRDX == 1) {
989       if (!Table_B15) {
990         Table_B15 = new CJBig2_HuffmanTable(HuffmanTable_B15,
991                                             FX_ArraySize(HuffmanTable_B15),
992                                             HuffmanTable_HTOOB_B15);
993       }
994       pTRD->SBHUFFRDX = Table_B15;
995     } else {
996       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
997       if (!pSeg) {
998         nRet = JBIG2_ERROR_FATAL;
999         goto failed;
1000       }
1001       pTRD->SBHUFFRDX = pSeg->m_Result.ht;
1002     }
1003     if (cSBHUFFRDY == 0) {
1004       if (!Table_B14) {
1005         Table_B14 = new CJBig2_HuffmanTable(HuffmanTable_B14,
1006                                             FX_ArraySize(HuffmanTable_B14),
1007                                             HuffmanTable_HTOOB_B14);
1008       }
1009       pTRD->SBHUFFRDY = Table_B14;
1010     } else if (cSBHUFFRDY == 1) {
1011       if (!Table_B15) {
1012         Table_B15 = new CJBig2_HuffmanTable(HuffmanTable_B15,
1013                                             FX_ArraySize(HuffmanTable_B15),
1014                                             HuffmanTable_HTOOB_B15);
1015       }
1016       pTRD->SBHUFFRDY = Table_B15;
1017     } else {
1018       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1019       if (!pSeg) {
1020         nRet = JBIG2_ERROR_FATAL;
1021         goto failed;
1022       }
1023       pTRD->SBHUFFRDY = pSeg->m_Result.ht;
1024     }
1025     if (cSBHUFFRSIZE == 0) {
1026       Table_B1 = new CJBig2_HuffmanTable(HuffmanTable_B1,
1027                                          FX_ArraySize(HuffmanTable_B1),
1028                                          HuffmanTable_HTOOB_B1);
1029       pTRD->SBHUFFRSIZE = Table_B1;
1030     } else {
1031       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1032       if (!pSeg) {
1033         nRet = JBIG2_ERROR_FATAL;
1034         goto failed;
1035       }
1036       pTRD->SBHUFFRSIZE = pSeg->m_Result.ht;
1037     }
1038   }
1039   if (pTRD->SBREFINE == 1) {
1040     dwTemp = pTRD->SBRTEMPLATE ? 1 << 10 : 1 << 13;
1041     grContext = FX_Alloc(JBig2ArithCtx, dwTemp);
1042     JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1043   }
1044   if (pTRD->SBHUFF == 0) {
1045     pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
1046     pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1047     pSegment->m_Result.im = pTRD->decode_Arith(pArithDecoder, grContext);
1048     delete pArithDecoder;
1049     if (pSegment->m_Result.im == NULL) {
1050       nRet = JBIG2_ERROR_FATAL;
1051       goto failed;
1052     }
1053     m_pStream->alignByte();
1054     m_pStream->offset(2);
1055   } else {
1056     pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1057     pSegment->m_Result.im = pTRD->decode_Huffman(m_pStream, grContext);
1058     if (pSegment->m_Result.im == NULL) {
1059       nRet = JBIG2_ERROR_FATAL;
1060       goto failed;
1061     }
1062     m_pStream->alignByte();
1063   }
1064   if (pSegment->m_cFlags.s.type != 4) {
1065     if (!m_bBufSpecified) {
1066       JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1067       if ((pPageInfo->m_bIsStriped == 1) &&
1068           (ri.y + ri.height > m_pPage->m_nHeight)) {
1069         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1070       }
1071     }
1072     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1073                          (JBig2ComposeOp)(ri.flags & 0x03));
1074     delete pSegment->m_Result.im;
1075     pSegment->m_Result.im = NULL;
1076   }
1077   delete pTRD;
1078   FX_Free(SBSYMS);
1079   FX_Free(SBSYMCODES);
1080   FX_Free(grContext);
1081   delete Table_B1;
1082   delete Table_B6;
1083   delete Table_B7;
1084   delete Table_B8;
1085   delete Table_B9;
1086   delete Table_B10;
1087   delete Table_B11;
1088   delete Table_B12;
1089   delete Table_B13;
1090   delete Table_B14;
1091   delete Table_B15;
1092   return JBIG2_SUCCESS;
1093 failed:
1094   delete pTRD;
1095   FX_Free(SBSYMS);
1096   FX_Free(SBSYMCODES);
1097   FX_Free(grContext);
1098   delete Table_B1;
1099   delete Table_B6;
1100   delete Table_B7;
1101   delete Table_B8;
1102   delete Table_B9;
1103   delete Table_B10;
1104   delete Table_B11;
1105   delete Table_B12;
1106   delete Table_B13;
1107   delete Table_B14;
1108   delete Table_B15;
1109   return nRet;
1110 }
1111
1112 int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment,
1113                                          IFX_Pause* pPause) {
1114   FX_DWORD dwTemp;
1115   uint8_t cFlags;
1116   JBig2ArithCtx* gbContext;
1117   CJBig2_ArithDecoder* pArithDecoder;
1118   int32_t nRet;
1119   CJBig2_PDDProc* pPDD = new CJBig2_PDDProc();
1120   if ((m_pStream->read1Byte(&cFlags) != 0) ||
1121       (m_pStream->read1Byte(&pPDD->HDPW) != 0) ||
1122       (m_pStream->read1Byte(&pPDD->HDPH) != 0) ||
1123       (m_pStream->readInteger(&pPDD->GRAYMAX) != 0)) {
1124     nRet = JBIG2_ERROR_TOO_SHORT;
1125     goto failed;
1126   }
1127   if (pPDD->GRAYMAX > JBIG2_MAX_PATTERN_INDEX) {
1128     nRet = JBIG2_ERROR_LIMIT;
1129     goto failed;
1130   }
1131   pPDD->HDMMR = cFlags & 0x01;
1132   pPDD->HDTEMPLATE = (cFlags >> 1) & 0x03;
1133   pSegment->m_nResultType = JBIG2_PATTERN_DICT_POINTER;
1134   if (pPDD->HDMMR == 0) {
1135     dwTemp =
1136         pPDD->HDTEMPLATE == 0 ? 65536 : pPDD->HDTEMPLATE == 1 ? 8192 : 1024;
1137     gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
1138     JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1139     pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
1140     pSegment->m_Result.pd =
1141         pPDD->decode_Arith(pArithDecoder, gbContext, pPause);
1142     delete pArithDecoder;
1143     if (pSegment->m_Result.pd == NULL) {
1144       FX_Free(gbContext);
1145       nRet = JBIG2_ERROR_FATAL;
1146       goto failed;
1147     }
1148     FX_Free(gbContext);
1149     m_pStream->alignByte();
1150     m_pStream->offset(2);
1151   } else {
1152     pSegment->m_Result.pd = pPDD->decode_MMR(m_pStream, pPause);
1153     if (pSegment->m_Result.pd == NULL) {
1154       nRet = JBIG2_ERROR_FATAL;
1155       goto failed;
1156     }
1157     m_pStream->alignByte();
1158   }
1159   delete pPDD;
1160   return JBIG2_SUCCESS;
1161 failed:
1162   delete pPDD;
1163   return nRet;
1164 }
1165 int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment,
1166                                             IFX_Pause* pPause) {
1167   FX_DWORD dwTemp;
1168   uint8_t cFlags;
1169   JBig2RegionInfo ri;
1170   CJBig2_Segment* pSeg;
1171   CJBig2_PatternDict* pPatternDict;
1172   JBig2ArithCtx* gbContext;
1173   CJBig2_ArithDecoder* pArithDecoder;
1174   int32_t nRet;
1175   CJBig2_HTRDProc* pHRD = new CJBig2_HTRDProc();
1176   if ((parseRegionInfo(&ri) != JBIG2_SUCCESS) ||
1177       (m_pStream->read1Byte(&cFlags) != 0) ||
1178       (m_pStream->readInteger(&pHRD->HGW) != 0) ||
1179       (m_pStream->readInteger(&pHRD->HGH) != 0) ||
1180       (m_pStream->readInteger((FX_DWORD*)&pHRD->HGX) != 0) ||
1181       (m_pStream->readInteger((FX_DWORD*)&pHRD->HGY) != 0) ||
1182       (m_pStream->readShortInteger(&pHRD->HRX) != 0) ||
1183       (m_pStream->readShortInteger(&pHRD->HRY) != 0)) {
1184     nRet = JBIG2_ERROR_TOO_SHORT;
1185     goto failed;
1186   }
1187   pHRD->HBW = ri.width;
1188   pHRD->HBH = ri.height;
1189   pHRD->HMMR = cFlags & 0x01;
1190   pHRD->HTEMPLATE = (cFlags >> 1) & 0x03;
1191   pHRD->HENABLESKIP = (cFlags >> 3) & 0x01;
1192   pHRD->HCOMBOP = (JBig2ComposeOp)((cFlags >> 4) & 0x07);
1193   pHRD->HDEFPIXEL = (cFlags >> 7) & 0x01;
1194   if (pSegment->m_nReferred_to_segment_count != 1) {
1195     nRet = JBIG2_ERROR_FATAL;
1196     goto failed;
1197   }
1198   pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
1199   if ((pSeg == NULL) || (pSeg->m_cFlags.s.type != 16)) {
1200     nRet = JBIG2_ERROR_FATAL;
1201     goto failed;
1202   }
1203   pPatternDict = pSeg->m_Result.pd;
1204   if ((pPatternDict == NULL) || (pPatternDict->NUMPATS == 0)) {
1205     nRet = JBIG2_ERROR_FATAL;
1206     goto failed;
1207   }
1208   pHRD->HNUMPATS = pPatternDict->NUMPATS;
1209   pHRD->HPATS = pPatternDict->HDPATS;
1210   pHRD->HPW = pPatternDict->HDPATS[0]->m_nWidth;
1211   pHRD->HPH = pPatternDict->HDPATS[0]->m_nHeight;
1212   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1213   if (pHRD->HMMR == 0) {
1214     dwTemp = pHRD->HTEMPLATE == 0 ? 65536 : pHRD->HTEMPLATE == 1 ? 8192 : 1024;
1215     gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
1216     JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1217     pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
1218     pSegment->m_Result.im =
1219         pHRD->decode_Arith(pArithDecoder, gbContext, pPause);
1220     delete pArithDecoder;
1221     if (pSegment->m_Result.im == NULL) {
1222       FX_Free(gbContext);
1223       nRet = JBIG2_ERROR_FATAL;
1224       goto failed;
1225     }
1226     FX_Free(gbContext);
1227     m_pStream->alignByte();
1228     m_pStream->offset(2);
1229   } else {
1230     pSegment->m_Result.im = pHRD->decode_MMR(m_pStream, pPause);
1231     if (pSegment->m_Result.im == NULL) {
1232       nRet = JBIG2_ERROR_FATAL;
1233       goto failed;
1234     }
1235     m_pStream->alignByte();
1236   }
1237   if (pSegment->m_cFlags.s.type != 20) {
1238     if (!m_bBufSpecified) {
1239       JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1240       if ((pPageInfo->m_bIsStriped == 1) &&
1241           (ri.y + ri.height > m_pPage->m_nHeight)) {
1242         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1243       }
1244     }
1245     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1246                          (JBig2ComposeOp)(ri.flags & 0x03));
1247     delete pSegment->m_Result.im;
1248     pSegment->m_Result.im = NULL;
1249   }
1250   delete pHRD;
1251   return JBIG2_SUCCESS;
1252 failed:
1253   delete pHRD;
1254   return nRet;
1255 }
1256
1257 int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment,
1258                                            IFX_Pause* pPause) {
1259   FX_DWORD dwTemp;
1260   uint8_t cFlags;
1261   int32_t i, nRet;
1262   if (m_pGRD == NULL) {
1263     m_pGRD = new CJBig2_GRDProc();
1264     if ((parseRegionInfo(&m_ri) != JBIG2_SUCCESS) ||
1265         (m_pStream->read1Byte(&cFlags) != 0)) {
1266       nRet = JBIG2_ERROR_TOO_SHORT;
1267       goto failed;
1268     }
1269     if (m_ri.height < 0 || m_ri.width < 0) {
1270       nRet = JBIG2_FAILED;
1271       goto failed;
1272     }
1273     m_pGRD->GBW = m_ri.width;
1274     m_pGRD->GBH = m_ri.height;
1275     m_pGRD->MMR = cFlags & 0x01;
1276     m_pGRD->GBTEMPLATE = (cFlags >> 1) & 0x03;
1277     m_pGRD->TPGDON = (cFlags >> 3) & 0x01;
1278     if (m_pGRD->MMR == 0) {
1279       if (m_pGRD->GBTEMPLATE == 0) {
1280         for (i = 0; i < 8; i++) {
1281           if (m_pStream->read1Byte((uint8_t*)&m_pGRD->GBAT[i]) != 0) {
1282             nRet = JBIG2_ERROR_TOO_SHORT;
1283             goto failed;
1284           }
1285         }
1286       } else {
1287         for (i = 0; i < 2; i++) {
1288           if (m_pStream->read1Byte((uint8_t*)&m_pGRD->GBAT[i]) != 0) {
1289             nRet = JBIG2_ERROR_TOO_SHORT;
1290             goto failed;
1291           }
1292         }
1293       }
1294     }
1295     m_pGRD->USESKIP = 0;
1296   }
1297   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1298   if (m_pGRD->MMR == 0) {
1299     dwTemp =
1300         m_pGRD->GBTEMPLATE == 0 ? 65536 : m_pGRD->GBTEMPLATE == 1 ? 8192 : 1024;
1301     if (m_gbContext == NULL) {
1302       m_gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
1303       JBIG2_memset(m_gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1304     }
1305     if (m_pArithDecoder == NULL) {
1306       m_pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
1307       m_ProcessiveStatus = m_pGRD->Start_decode_Arith(
1308           &pSegment->m_Result.im, m_pArithDecoder, m_gbContext, pPause);
1309     } else {
1310       m_ProcessiveStatus = m_pGRD->Continue_decode(pPause);
1311     }
1312     if (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
1313       if (pSegment->m_cFlags.s.type != 36) {
1314         if (!m_bBufSpecified) {
1315           JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1316           if ((pPageInfo->m_bIsStriped == 1) &&
1317               (m_ri.y + m_ri.height > m_pPage->m_nHeight)) {
1318             m_pPage->expand(m_ri.y + m_ri.height,
1319                             (pPageInfo->m_cFlags & 4) ? 1 : 0);
1320           }
1321         }
1322         FX_RECT Rect = m_pGRD->GetReplaceRect();
1323         m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
1324                              pSegment->m_Result.im,
1325                              (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
1326       }
1327       return JBIG2_SUCCESS;
1328     } else {
1329       delete m_pArithDecoder;
1330       m_pArithDecoder = NULL;
1331       if (pSegment->m_Result.im == NULL) {
1332         FX_Free(m_gbContext);
1333         nRet = JBIG2_ERROR_FATAL;
1334         m_gbContext = NULL;
1335         m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
1336         goto failed;
1337       }
1338       FX_Free(m_gbContext);
1339       m_gbContext = NULL;
1340       m_pStream->alignByte();
1341       m_pStream->offset(2);
1342     }
1343   } else {
1344     FXCODEC_STATUS status =
1345         m_pGRD->Start_decode_MMR(&pSegment->m_Result.im, m_pStream, pPause);
1346     while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
1347       m_pGRD->Continue_decode(pPause);
1348     }
1349     if (pSegment->m_Result.im == NULL) {
1350       nRet = JBIG2_ERROR_FATAL;
1351       goto failed;
1352     }
1353     m_pStream->alignByte();
1354   }
1355   if (pSegment->m_cFlags.s.type != 36) {
1356     if (!m_bBufSpecified) {
1357       JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1358       if ((pPageInfo->m_bIsStriped == 1) &&
1359           (m_ri.y + m_ri.height > m_pPage->m_nHeight)) {
1360         m_pPage->expand(m_ri.y + m_ri.height,
1361                         (pPageInfo->m_cFlags & 4) ? 1 : 0);
1362       }
1363     }
1364     FX_RECT Rect = m_pGRD->GetReplaceRect();
1365     m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
1366                          pSegment->m_Result.im,
1367                          (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
1368     delete pSegment->m_Result.im;
1369     pSegment->m_Result.im = NULL;
1370   }
1371   delete m_pGRD;
1372   m_pGRD = NULL;
1373   return JBIG2_SUCCESS;
1374 failed:
1375   delete m_pGRD;
1376   m_pGRD = NULL;
1377   return nRet;
1378 }
1379
1380 int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) {
1381   FX_DWORD dwTemp;
1382   JBig2RegionInfo ri;
1383   CJBig2_Segment* pSeg;
1384   int32_t i, nRet;
1385   uint8_t cFlags;
1386   JBig2ArithCtx* grContext;
1387   CJBig2_ArithDecoder* pArithDecoder;
1388   CJBig2_GRRDProc* pGRRD = new CJBig2_GRRDProc();
1389   if ((parseRegionInfo(&ri) != JBIG2_SUCCESS) ||
1390       (m_pStream->read1Byte(&cFlags) != 0)) {
1391     nRet = JBIG2_ERROR_TOO_SHORT;
1392     goto failed;
1393   }
1394   pGRRD->GRW = ri.width;
1395   pGRRD->GRH = ri.height;
1396   pGRRD->GRTEMPLATE = cFlags & 0x01;
1397   pGRRD->TPGRON = (cFlags >> 1) & 0x01;
1398   if (pGRRD->GRTEMPLATE == 0) {
1399     for (i = 0; i < 4; i++) {
1400       if (m_pStream->read1Byte((uint8_t*)&pGRRD->GRAT[i]) != 0) {
1401         nRet = JBIG2_ERROR_TOO_SHORT;
1402         goto failed;
1403       }
1404     }
1405   }
1406   pSeg = NULL;
1407   if (pSegment->m_nReferred_to_segment_count > 0) {
1408     for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
1409       pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
1410       if (pSeg == NULL) {
1411         nRet = JBIG2_ERROR_FATAL;
1412         goto failed;
1413       }
1414       if ((pSeg->m_cFlags.s.type == 4) || (pSeg->m_cFlags.s.type == 20) ||
1415           (pSeg->m_cFlags.s.type == 36) || (pSeg->m_cFlags.s.type == 40)) {
1416         break;
1417       }
1418     }
1419     if (i >= pSegment->m_nReferred_to_segment_count) {
1420       nRet = JBIG2_ERROR_FATAL;
1421       goto failed;
1422     }
1423     pGRRD->GRREFERENCE = pSeg->m_Result.im;
1424   } else {
1425     pGRRD->GRREFERENCE = m_pPage;
1426   }
1427   pGRRD->GRREFERENCEDX = 0;
1428   pGRRD->GRREFERENCEDY = 0;
1429   dwTemp = pGRRD->GRTEMPLATE ? 1 << 10 : 1 << 13;
1430   grContext = FX_Alloc(JBig2ArithCtx, dwTemp);
1431   JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1432   pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
1433   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1434   pSegment->m_Result.im = pGRRD->decode(pArithDecoder, grContext);
1435   delete pArithDecoder;
1436   if (pSegment->m_Result.im == NULL) {
1437     FX_Free(grContext);
1438     nRet = JBIG2_ERROR_FATAL;
1439     goto failed;
1440   }
1441   FX_Free(grContext);
1442   m_pStream->alignByte();
1443   m_pStream->offset(2);
1444   if (pSegment->m_cFlags.s.type != 40) {
1445     if (!m_bBufSpecified) {
1446       JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1447       if ((pPageInfo->m_bIsStriped == 1) &&
1448           (ri.y + ri.height > m_pPage->m_nHeight)) {
1449         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1450       }
1451     }
1452     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1453                          (JBig2ComposeOp)(ri.flags & 0x03));
1454     delete pSegment->m_Result.im;
1455     pSegment->m_Result.im = NULL;
1456   }
1457   delete pGRRD;
1458   return JBIG2_SUCCESS;
1459 failed:
1460   delete pGRRD;
1461   return nRet;
1462 }
1463 int32_t CJBig2_Context::parseTable(CJBig2_Segment* pSegment) {
1464   pSegment->m_nResultType = JBIG2_HUFFMAN_TABLE_POINTER;
1465   pSegment->m_Result.ht = new CJBig2_HuffmanTable(m_pStream);
1466   if (!pSegment->m_Result.ht->isOK()) {
1467     delete pSegment->m_Result.ht;
1468     pSegment->m_Result.ht = NULL;
1469     return JBIG2_ERROR_FATAL;
1470   }
1471   m_pStream->alignByte();
1472   return JBIG2_SUCCESS;
1473 }
1474 int32_t CJBig2_Context::parseRegionInfo(JBig2RegionInfo* pRI) {
1475   if ((m_pStream->readInteger((FX_DWORD*)&pRI->width) != 0) ||
1476       (m_pStream->readInteger((FX_DWORD*)&pRI->height) != 0) ||
1477       (m_pStream->readInteger((FX_DWORD*)&pRI->x) != 0) ||
1478       (m_pStream->readInteger((FX_DWORD*)&pRI->y) != 0) ||
1479       (m_pStream->read1Byte(&pRI->flags) != 0)) {
1480     return JBIG2_ERROR_TOO_SHORT;
1481   }
1482   return JBIG2_SUCCESS;
1483 }
1484 JBig2HuffmanCode* CJBig2_Context::decodeSymbolIDHuffmanTable(
1485     CJBig2_BitStream* pStream,
1486     FX_DWORD SBNUMSYMS) {
1487   JBig2HuffmanCode* SBSYMCODES;
1488   int32_t runcodes[35];
1489   int32_t runcodes_len[35];
1490   int32_t runcode;
1491   int32_t i;
1492   int32_t j;
1493   int32_t nVal;
1494   int32_t nBits;
1495   int32_t run;
1496   FX_DWORD nTemp;
1497   SBSYMCODES = FX_Alloc(JBig2HuffmanCode, SBNUMSYMS);
1498   for (i = 0; i < 35; i++) {
1499     if (pStream->readNBits(4, &runcodes_len[i]) != 0) {
1500       goto failed;
1501     }
1502   }
1503   huffman_assign_code(runcodes, runcodes_len, 35);
1504   i = 0;
1505   while (i < (int)SBNUMSYMS) {
1506     nVal = 0;
1507     nBits = 0;
1508     for (;;) {
1509       if (pStream->read1Bit(&nTemp) != 0) {
1510         goto failed;
1511       }
1512       nVal = (nVal << 1) | nTemp;
1513       nBits++;
1514       for (j = 0; j < 35; j++) {
1515         if ((nBits == runcodes_len[j]) && (nVal == runcodes[j])) {
1516           break;
1517         }
1518       }
1519       if (j < 35) {
1520         break;
1521       }
1522     }
1523     runcode = j;
1524     if (runcode < 32) {
1525       SBSYMCODES[i].codelen = runcode;
1526       run = 0;
1527     } else if (runcode == 32) {
1528       if (pStream->readNBits(2, &nTemp) != 0) {
1529         goto failed;
1530       }
1531       run = nTemp + 3;
1532     } else if (runcode == 33) {
1533       if (pStream->readNBits(3, &nTemp) != 0) {
1534         goto failed;
1535       }
1536       run = nTemp + 3;
1537     } else if (runcode == 34) {
1538       if (pStream->readNBits(7, &nTemp) != 0) {
1539         goto failed;
1540       }
1541       run = nTemp + 11;
1542     }
1543     if (run > 0) {
1544       if (i + run > (int)SBNUMSYMS) {
1545         goto failed;
1546       }
1547       for (j = 0; j < run; j++) {
1548         if (runcode == 32 && i > 0) {
1549           SBSYMCODES[i + j].codelen = SBSYMCODES[i - 1].codelen;
1550         } else {
1551           SBSYMCODES[i + j].codelen = 0;
1552         }
1553       }
1554       i += run;
1555     } else {
1556       i++;
1557     }
1558   }
1559   huffman_assign_code(SBSYMCODES, SBNUMSYMS);
1560   return SBSYMCODES;
1561 failed:
1562   FX_Free(SBSYMCODES);
1563   return NULL;
1564 }
1565 void CJBig2_Context::huffman_assign_code(int* CODES, int* PREFLEN, int NTEMP) {
1566   int CURLEN, LENMAX, CURCODE, CURTEMP, i;
1567   int* LENCOUNT;
1568   int* FIRSTCODE;
1569   LENMAX = 0;
1570   for (i = 0; i < NTEMP; i++) {
1571     if (PREFLEN[i] > LENMAX) {
1572       LENMAX = PREFLEN[i];
1573     }
1574   }
1575   LENCOUNT = FX_Alloc(int, LENMAX + 1);
1576   JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
1577   FIRSTCODE = FX_Alloc(int, LENMAX + 1);
1578   for (i = 0; i < NTEMP; i++) {
1579     LENCOUNT[PREFLEN[i]]++;
1580   }
1581   CURLEN = 1;
1582   FIRSTCODE[0] = 0;
1583   LENCOUNT[0] = 0;
1584   while (CURLEN <= LENMAX) {
1585     FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
1586     CURCODE = FIRSTCODE[CURLEN];
1587     CURTEMP = 0;
1588     while (CURTEMP < NTEMP) {
1589       if (PREFLEN[CURTEMP] == CURLEN) {
1590         CODES[CURTEMP] = CURCODE;
1591         CURCODE = CURCODE + 1;
1592       }
1593       CURTEMP = CURTEMP + 1;
1594     }
1595     CURLEN = CURLEN + 1;
1596   }
1597   FX_Free(LENCOUNT);
1598   FX_Free(FIRSTCODE);
1599 }
1600 void CJBig2_Context::huffman_assign_code(JBig2HuffmanCode* SBSYMCODES,
1601                                          int NTEMP) {
1602   int CURLEN, LENMAX, CURCODE, CURTEMP, i;
1603   int* LENCOUNT;
1604   int* FIRSTCODE;
1605   LENMAX = 0;
1606   for (i = 0; i < NTEMP; i++) {
1607     if (SBSYMCODES[i].codelen > LENMAX) {
1608       LENMAX = SBSYMCODES[i].codelen;
1609     }
1610   }
1611   LENCOUNT = FX_Alloc(int, (LENMAX + 1));
1612   JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
1613   FIRSTCODE = FX_Alloc(int, (LENMAX + 1));
1614   for (i = 0; i < NTEMP; i++) {
1615     LENCOUNT[SBSYMCODES[i].codelen]++;
1616   }
1617   CURLEN = 1;
1618   FIRSTCODE[0] = 0;
1619   LENCOUNT[0] = 0;
1620   while (CURLEN <= LENMAX) {
1621     FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
1622     CURCODE = FIRSTCODE[CURLEN];
1623     CURTEMP = 0;
1624     while (CURTEMP < NTEMP) {
1625       if (SBSYMCODES[CURTEMP].codelen == CURLEN) {
1626         SBSYMCODES[CURTEMP].code = CURCODE;
1627         CURCODE = CURCODE + 1;
1628       }
1629       CURTEMP = CURTEMP + 1;
1630     }
1631     CURLEN = CURLEN + 1;
1632   }
1633   FX_Free(LENCOUNT);
1634   FX_Free(FIRSTCODE);
1635 }