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