Guard against null image data in CJBig2_GRRDProc.
[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
406 int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment,
407                                          IFX_Pause* pPause) {
408   int32_t ret = ProcessiveParseSegmentData(pSegment, pPause);
409   while (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE &&
410          m_pStream->getByteLeft() > 0) {
411     ret = ProcessiveParseSegmentData(pSegment, pPause);
412   }
413   return ret;
414 }
415
416 int32_t CJBig2_Context::ProcessiveParseSegmentData(CJBig2_Segment* pSegment,
417                                                    IFX_Pause* pPause) {
418   switch (pSegment->m_cFlags.s.type) {
419     case 0:
420       return parseSymbolDict(pSegment, pPause);
421     case 4:
422     case 6:
423     case 7:
424       if (m_nState == JBIG2_OUT_OF_PAGE)
425         return JBIG2_ERROR_FATAL;
426       return parseTextRegion(pSegment);
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         return JBIG2_ERROR_FATAL;
434       return parseHalftoneRegion(pSegment, pPause);
435     case 36:
436     case 38:
437     case 39:
438       if (m_nState == JBIG2_OUT_OF_PAGE)
439         return JBIG2_ERROR_FATAL;
440       return parseGenericRegion(pSegment, pPause);
441     case 40:
442     case 42:
443     case 43:
444       if (m_nState == JBIG2_OUT_OF_PAGE)
445         return JBIG2_ERROR_FATAL;
446       return parseGenericRefinementRegion(pSegment);
447     case 48: {
448       FX_WORD wTemp;
449       nonstd::unique_ptr<JBig2PageInfo> pPageInfo(new JBig2PageInfo);
450       if ((m_pStream->readInteger(&pPageInfo->m_dwWidth) != 0) ||
451           (m_pStream->readInteger(&pPageInfo->m_dwHeight) != 0) ||
452           (m_pStream->readInteger(&pPageInfo->m_dwResolutionX) != 0) ||
453           (m_pStream->readInteger(&pPageInfo->m_dwResolutionY) != 0) ||
454           (m_pStream->read1Byte(&pPageInfo->m_cFlags) != 0) ||
455           (m_pStream->readShortInteger(&wTemp) != 0)) {
456         return JBIG2_ERROR_TOO_SHORT;
457       }
458       pPageInfo->m_bIsStriped = ((wTemp >> 15) & 1) ? TRUE : FALSE;
459       pPageInfo->m_wMaxStripeSize = wTemp & 0x7fff;
460       bool bMaxHeight = (pPageInfo->m_dwHeight == 0xffffffff);
461       if (bMaxHeight && pPageInfo->m_bIsStriped != TRUE)
462         pPageInfo->m_bIsStriped = TRUE;
463
464       if (!m_bBufSpecified) {
465         delete m_pPage;
466         FX_DWORD height =
467             bMaxHeight ? pPageInfo->m_wMaxStripeSize : pPageInfo->m_dwHeight;
468         m_pPage = new CJBig2_Image(pPageInfo->m_dwWidth, height);
469       }
470
471       if (!m_pPage->m_pData) {
472         m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
473         return JBIG2_ERROR_TOO_SHORT;
474       }
475
476       m_pPage->fill((pPageInfo->m_cFlags & 4) ? 1 : 0);
477       m_PageInfoList.push_back(pPageInfo.release());
478       m_nState = JBIG2_IN_PAGE;
479     } break;
480     case 49:
481       m_nState = JBIG2_OUT_OF_PAGE;
482       return JBIG2_END_OF_PAGE;
483       break;
484     case 50:
485       m_pStream->offset(pSegment->m_dwData_length);
486       break;
487     case 51:
488       return JBIG2_END_OF_FILE;
489     case 52:
490       m_pStream->offset(pSegment->m_dwData_length);
491       break;
492     case 53:
493       return parseTable(pSegment);
494     case 62:
495       m_pStream->offset(pSegment->m_dwData_length);
496       break;
497     default:
498       break;
499   }
500   return JBIG2_SUCCESS;
501 }
502
503 int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment,
504                                         IFX_Pause* pPause) {
505   FX_DWORD dwTemp;
506   FX_WORD wFlags;
507   uint8_t cSDHUFFDH, cSDHUFFDW, cSDHUFFBMSIZE, cSDHUFFAGGINST;
508   CJBig2_HuffmanTable *Table_B1 = NULL, *Table_B2 = NULL, *Table_B3 = NULL,
509                       *Table_B4 = NULL, *Table_B5 = NULL;
510   int32_t i, nIndex, nRet;
511   CJBig2_Segment *pSeg = NULL, *pLRSeg = NULL;
512   FX_BOOL bUsed;
513   CJBig2_Image** SDINSYMS = NULL;
514   JBig2ArithCtx *gbContext = NULL, *grContext = NULL;
515   CJBig2_ArithDecoder* pArithDecoder;
516   CJBig2_SDDProc* pSymbolDictDecoder = new CJBig2_SDDProc();
517   const uint8_t* key = pSegment->m_pData;
518   FX_BOOL cache_hit = false;
519   if (m_pStream->readShortInteger(&wFlags) != 0) {
520     nRet = JBIG2_ERROR_TOO_SHORT;
521     goto failed;
522   }
523   pSymbolDictDecoder->SDHUFF = wFlags & 0x0001;
524   pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001;
525   pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003;
526   pSymbolDictDecoder->SDRTEMPLATE = (wFlags >> 12) & 0x0003;
527   cSDHUFFDH = (wFlags >> 2) & 0x0003;
528   cSDHUFFDW = (wFlags >> 4) & 0x0003;
529   cSDHUFFBMSIZE = (wFlags >> 6) & 0x0001;
530   cSDHUFFAGGINST = (wFlags >> 7) & 0x0001;
531   if (pSymbolDictDecoder->SDHUFF == 0) {
532     if (pSymbolDictDecoder->SDTEMPLATE == 0) {
533       dwTemp = 8;
534     } else {
535       dwTemp = 2;
536     }
537     for (i = 0; i < (int32_t)dwTemp; i++) {
538       if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDAT[i]) != 0) {
539         nRet = JBIG2_ERROR_TOO_SHORT;
540         goto failed;
541       }
542     }
543   }
544   if ((pSymbolDictDecoder->SDREFAGG == 1) &&
545       (pSymbolDictDecoder->SDRTEMPLATE == 0)) {
546     for (i = 0; i < 4; i++) {
547       if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDRAT[i]) != 0) {
548         nRet = JBIG2_ERROR_TOO_SHORT;
549         goto failed;
550       }
551     }
552   }
553   if ((m_pStream->readInteger(&pSymbolDictDecoder->SDNUMEXSYMS) != 0) ||
554       (m_pStream->readInteger(&pSymbolDictDecoder->SDNUMNEWSYMS) != 0)) {
555     nRet = JBIG2_ERROR_TOO_SHORT;
556     goto failed;
557   }
558   if (pSymbolDictDecoder->SDNUMEXSYMS > JBIG2_MAX_EXPORT_SYSMBOLS ||
559       pSymbolDictDecoder->SDNUMNEWSYMS > JBIG2_MAX_NEW_SYSMBOLS) {
560     nRet = JBIG2_ERROR_LIMIT;
561     goto failed;
562   }
563   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
564     if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i])) {
565       nRet = JBIG2_ERROR_FATAL;
566       goto failed;
567     }
568   }
569   pSymbolDictDecoder->SDNUMINSYMS = 0;
570   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
571     pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
572     if (pSeg->m_cFlags.s.type == 0) {
573       pSymbolDictDecoder->SDNUMINSYMS += pSeg->m_Result.sd->SDNUMEXSYMS;
574       pLRSeg = pSeg;
575     }
576   }
577   if (pSymbolDictDecoder->SDNUMINSYMS == 0) {
578     SDINSYMS = NULL;
579   } else {
580     SDINSYMS = FX_Alloc(CJBig2_Image*, pSymbolDictDecoder->SDNUMINSYMS);
581     dwTemp = 0;
582     for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
583       pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
584       if (pSeg->m_cFlags.s.type == 0) {
585         JBIG2_memcpy(SDINSYMS + dwTemp, pSeg->m_Result.sd->SDEXSYMS,
586                      pSeg->m_Result.sd->SDNUMEXSYMS * sizeof(CJBig2_Image*));
587         dwTemp += pSeg->m_Result.sd->SDNUMEXSYMS;
588       }
589     }
590   }
591   pSymbolDictDecoder->SDINSYMS = SDINSYMS;
592   if (pSymbolDictDecoder->SDHUFF == 1) {
593     if ((cSDHUFFDH == 2) || (cSDHUFFDW == 2)) {
594       nRet = JBIG2_ERROR_FATAL;
595       goto failed;
596     }
597     nIndex = 0;
598     if (cSDHUFFDH == 0) {
599       Table_B4 = new CJBig2_HuffmanTable(HuffmanTable_B4,
600                                          FX_ArraySize(HuffmanTable_B4),
601                                          HuffmanTable_HTOOB_B4);
602       pSymbolDictDecoder->SDHUFFDH = Table_B4;
603     } else if (cSDHUFFDH == 1) {
604       Table_B5 = new CJBig2_HuffmanTable(HuffmanTable_B5,
605                                          FX_ArraySize(HuffmanTable_B5),
606                                          HuffmanTable_HTOOB_B5);
607       pSymbolDictDecoder->SDHUFFDH = Table_B5;
608     } else {
609       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
610       if (!pSeg) {
611         nRet = JBIG2_ERROR_FATAL;
612         goto failed;
613       }
614       pSymbolDictDecoder->SDHUFFDH = pSeg->m_Result.ht;
615     }
616     if (cSDHUFFDW == 0) {
617       Table_B2 = new CJBig2_HuffmanTable(HuffmanTable_B2,
618                                          FX_ArraySize(HuffmanTable_B2),
619                                          HuffmanTable_HTOOB_B2);
620       pSymbolDictDecoder->SDHUFFDW = Table_B2;
621     } else if (cSDHUFFDW == 1) {
622       Table_B3 = new CJBig2_HuffmanTable(HuffmanTable_B3,
623                                          FX_ArraySize(HuffmanTable_B3),
624                                          HuffmanTable_HTOOB_B3);
625       pSymbolDictDecoder->SDHUFFDW = Table_B3;
626     } else {
627       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
628       if (!pSeg) {
629         nRet = JBIG2_ERROR_FATAL;
630         goto failed;
631       }
632       pSymbolDictDecoder->SDHUFFDW = pSeg->m_Result.ht;
633     }
634     if (cSDHUFFBMSIZE == 0) {
635       Table_B1 = new CJBig2_HuffmanTable(HuffmanTable_B1,
636                                          FX_ArraySize(HuffmanTable_B1),
637                                          HuffmanTable_HTOOB_B1);
638       pSymbolDictDecoder->SDHUFFBMSIZE = Table_B1;
639     } else {
640       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
641       if (!pSeg) {
642         nRet = JBIG2_ERROR_FATAL;
643         goto failed;
644       }
645       pSymbolDictDecoder->SDHUFFBMSIZE = pSeg->m_Result.ht;
646     }
647     if (pSymbolDictDecoder->SDREFAGG == 1) {
648       if (cSDHUFFAGGINST == 0) {
649         if (!Table_B1) {
650           Table_B1 = new CJBig2_HuffmanTable(HuffmanTable_B1,
651                                              FX_ArraySize(HuffmanTable_B1),
652                                              HuffmanTable_HTOOB_B1);
653         }
654         pSymbolDictDecoder->SDHUFFAGGINST = Table_B1;
655       } else {
656         pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
657         if (!pSeg) {
658           nRet = JBIG2_ERROR_FATAL;
659           goto failed;
660         }
661         pSymbolDictDecoder->SDHUFFAGGINST = pSeg->m_Result.ht;
662       }
663     }
664   }
665   if ((wFlags & 0x0100) && pLRSeg && pLRSeg->m_Result.sd->m_bContextRetained) {
666     if (pSymbolDictDecoder->SDHUFF == 0) {
667       dwTemp = pSymbolDictDecoder->SDTEMPLATE == 0
668                    ? 65536
669                    : pSymbolDictDecoder->SDTEMPLATE == 1 ? 8192 : 1024;
670       gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
671       JBIG2_memcpy(gbContext, pLRSeg->m_Result.sd->m_gbContext,
672                    sizeof(JBig2ArithCtx) * dwTemp);
673     }
674     if (pSymbolDictDecoder->SDREFAGG == 1) {
675       dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13;
676       grContext = FX_Alloc(JBig2ArithCtx, dwTemp);
677       JBIG2_memcpy(grContext, pLRSeg->m_Result.sd->m_grContext,
678                    sizeof(JBig2ArithCtx) * dwTemp);
679     }
680   } else {
681     if (pSymbolDictDecoder->SDHUFF == 0) {
682       dwTemp = pSymbolDictDecoder->SDTEMPLATE == 0
683                    ? 65536
684                    : pSymbolDictDecoder->SDTEMPLATE == 1 ? 8192 : 1024;
685       gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
686       JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
687     }
688     if (pSymbolDictDecoder->SDREFAGG == 1) {
689       dwTemp = pSymbolDictDecoder->SDRTEMPLATE ? 1 << 10 : 1 << 13;
690       grContext = FX_Alloc(JBig2ArithCtx, dwTemp);
691       JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
692     }
693   }
694   pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER;
695   for (std::list<CJBig2_CachePair>::iterator it = m_pSymbolDictCache->begin();
696        it != m_pSymbolDictCache->end(); ++it) {
697     if (it->first == key) {
698       pSegment->m_Result.sd = it->second->DeepCopy();
699       m_pSymbolDictCache->push_front(*it);
700       m_pSymbolDictCache->erase(it);
701       cache_hit = true;
702       break;
703     }
704   }
705   if (!cache_hit) {
706     if (pSymbolDictDecoder->SDHUFF == 0) {
707       pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
708       pSegment->m_Result.sd =
709           pSymbolDictDecoder->decode_Arith(pArithDecoder, gbContext, grContext);
710       delete pArithDecoder;
711       if (pSegment->m_Result.sd == NULL) {
712         nRet = JBIG2_ERROR_FATAL;
713         goto failed;
714       }
715       m_pStream->alignByte();
716       m_pStream->offset(2);
717     } else {
718       pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(
719           m_pStream, gbContext, grContext, pPause);
720       if (pSegment->m_Result.sd == NULL) {
721         nRet = JBIG2_ERROR_FATAL;
722         goto failed;
723       }
724       m_pStream->alignByte();
725     }
726     CJBig2_SymbolDict* value = pSegment->m_Result.sd->DeepCopy();
727     if (value && kSymbolDictCacheMaxSize > 0) {
728       while (m_pSymbolDictCache->size() >= kSymbolDictCacheMaxSize) {
729         delete m_pSymbolDictCache->back().second;
730         m_pSymbolDictCache->pop_back();
731       }
732       m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value));
733     }
734   }
735   if (wFlags & 0x0200) {
736     pSegment->m_Result.sd->m_bContextRetained = TRUE;
737     if (pSymbolDictDecoder->SDHUFF == 0) {
738       pSegment->m_Result.sd->m_gbContext = gbContext;
739     }
740     if (pSymbolDictDecoder->SDREFAGG == 1) {
741       pSegment->m_Result.sd->m_grContext = grContext;
742     }
743     bUsed = TRUE;
744   } else {
745     bUsed = FALSE;
746   }
747   delete pSymbolDictDecoder;
748   FX_Free(SDINSYMS);
749   delete Table_B1;
750   delete Table_B2;
751   delete Table_B3;
752   delete Table_B4;
753   delete Table_B5;
754   if (bUsed == FALSE) {
755     FX_Free(gbContext);
756     FX_Free(grContext);
757   }
758   return JBIG2_SUCCESS;
759 failed:
760   delete pSymbolDictDecoder;
761   FX_Free(SDINSYMS);
762   delete Table_B1;
763   delete Table_B2;
764   delete Table_B3;
765   delete Table_B4;
766   delete Table_B5;
767   FX_Free(gbContext);
768   FX_Free(grContext);
769   return nRet;
770 }
771
772 int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) {
773   FX_DWORD dwTemp;
774   FX_WORD wFlags;
775   int32_t i, nIndex, nRet;
776   JBig2RegionInfo ri;
777   CJBig2_Segment* pSeg;
778   CJBig2_Image** SBSYMS = NULL;
779   JBig2HuffmanCode* SBSYMCODES = NULL;
780   uint8_t cSBHUFFFS, cSBHUFFDS, cSBHUFFDT, cSBHUFFRDW, cSBHUFFRDH, cSBHUFFRDX,
781       cSBHUFFRDY, cSBHUFFRSIZE;
782   CJBig2_HuffmanTable *Table_B1 = NULL, *Table_B6 = NULL, *Table_B7 = NULL,
783                       *Table_B8 = NULL, *Table_B9 = NULL, *Table_B10 = NULL,
784                       *Table_B11 = NULL, *Table_B12 = NULL, *Table_B13 = NULL,
785                       *Table_B14 = NULL, *Table_B15 = NULL;
786   JBig2ArithCtx* grContext = NULL;
787   CJBig2_ArithDecoder* pArithDecoder;
788   CJBig2_TRDProc* pTRD = new CJBig2_TRDProc();
789   if ((parseRegionInfo(&ri) != JBIG2_SUCCESS) ||
790       (m_pStream->readShortInteger(&wFlags) != 0)) {
791     nRet = JBIG2_ERROR_TOO_SHORT;
792     goto failed;
793   }
794   pTRD->SBW = ri.width;
795   pTRD->SBH = ri.height;
796   pTRD->SBHUFF = wFlags & 0x0001;
797   pTRD->SBREFINE = (wFlags >> 1) & 0x0001;
798   dwTemp = (wFlags >> 2) & 0x0003;
799   pTRD->SBSTRIPS = 1 << dwTemp;
800   pTRD->REFCORNER = (JBig2Corner)((wFlags >> 4) & 0x0003);
801   pTRD->TRANSPOSED = (wFlags >> 6) & 0x0001;
802   pTRD->SBCOMBOP = (JBig2ComposeOp)((wFlags >> 7) & 0x0003);
803   pTRD->SBDEFPIXEL = (wFlags >> 9) & 0x0001;
804   pTRD->SBDSOFFSET = (wFlags >> 10) & 0x001f;
805   if (pTRD->SBDSOFFSET >= 0x0010) {
806     pTRD->SBDSOFFSET = pTRD->SBDSOFFSET - 0x0020;
807   }
808   pTRD->SBRTEMPLATE = (wFlags >> 15) & 0x0001;
809   if (pTRD->SBHUFF == 1) {
810     if (m_pStream->readShortInteger(&wFlags) != 0) {
811       nRet = JBIG2_ERROR_TOO_SHORT;
812       goto failed;
813     }
814     cSBHUFFFS = wFlags & 0x0003;
815     cSBHUFFDS = (wFlags >> 2) & 0x0003;
816     cSBHUFFDT = (wFlags >> 4) & 0x0003;
817     cSBHUFFRDW = (wFlags >> 6) & 0x0003;
818     cSBHUFFRDH = (wFlags >> 8) & 0x0003;
819     cSBHUFFRDX = (wFlags >> 10) & 0x0003;
820     cSBHUFFRDY = (wFlags >> 12) & 0x0003;
821     cSBHUFFRSIZE = (wFlags >> 14) & 0x0001;
822   }
823   if ((pTRD->SBREFINE == 1) && (pTRD->SBRTEMPLATE == 0)) {
824     for (i = 0; i < 4; i++) {
825       if (m_pStream->read1Byte((uint8_t*)&pTRD->SBRAT[i]) != 0) {
826         nRet = JBIG2_ERROR_TOO_SHORT;
827         goto failed;
828       }
829     }
830   }
831   if (m_pStream->readInteger(&pTRD->SBNUMINSTANCES) != 0) {
832     nRet = JBIG2_ERROR_TOO_SHORT;
833     goto failed;
834   }
835   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
836     if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i])) {
837       nRet = JBIG2_ERROR_FATAL;
838       goto failed;
839     }
840   }
841   pTRD->SBNUMSYMS = 0;
842   for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
843     pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
844     if (pSeg->m_cFlags.s.type == 0) {
845       pTRD->SBNUMSYMS += pSeg->m_Result.sd->SDNUMEXSYMS;
846     }
847   }
848   if (pTRD->SBNUMSYMS > 0) {
849     SBSYMS = FX_Alloc(CJBig2_Image*, pTRD->SBNUMSYMS);
850     dwTemp = 0;
851     for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
852       pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
853       if (pSeg->m_cFlags.s.type == 0) {
854         JBIG2_memcpy(SBSYMS + dwTemp, pSeg->m_Result.sd->SDEXSYMS,
855                      pSeg->m_Result.sd->SDNUMEXSYMS * sizeof(CJBig2_Image*));
856         dwTemp += pSeg->m_Result.sd->SDNUMEXSYMS;
857       }
858     }
859     pTRD->SBSYMS = SBSYMS;
860   } else {
861     pTRD->SBSYMS = NULL;
862   }
863   if (pTRD->SBHUFF == 1) {
864     SBSYMCODES = decodeSymbolIDHuffmanTable(m_pStream, pTRD->SBNUMSYMS);
865     if (SBSYMCODES == NULL) {
866       nRet = JBIG2_ERROR_FATAL;
867       goto failed;
868     }
869     m_pStream->alignByte();
870     pTRD->SBSYMCODES = SBSYMCODES;
871   } else {
872     dwTemp = 0;
873     while ((FX_DWORD)(1 << dwTemp) < pTRD->SBNUMSYMS) {
874       dwTemp++;
875     }
876     pTRD->SBSYMCODELEN = (uint8_t)dwTemp;
877   }
878   if (pTRD->SBHUFF == 1) {
879     if ((cSBHUFFFS == 2) || (cSBHUFFRDW == 2) || (cSBHUFFRDH == 2) ||
880         (cSBHUFFRDX == 2) || (cSBHUFFRDY == 2)) {
881       nRet = JBIG2_ERROR_FATAL;
882       goto failed;
883     }
884     nIndex = 0;
885     if (cSBHUFFFS == 0) {
886       Table_B6 = new CJBig2_HuffmanTable(HuffmanTable_B6,
887                                          FX_ArraySize(HuffmanTable_B6),
888                                          HuffmanTable_HTOOB_B6);
889       pTRD->SBHUFFFS = Table_B6;
890     } else if (cSBHUFFFS == 1) {
891       Table_B7 = new CJBig2_HuffmanTable(HuffmanTable_B7,
892                                          FX_ArraySize(HuffmanTable_B7),
893                                          HuffmanTable_HTOOB_B7);
894       pTRD->SBHUFFFS = Table_B7;
895     } else {
896       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
897       if (!pSeg) {
898         nRet = JBIG2_ERROR_FATAL;
899         goto failed;
900       }
901       pTRD->SBHUFFFS = pSeg->m_Result.ht;
902     }
903     if (cSBHUFFDS == 0) {
904       Table_B8 = new CJBig2_HuffmanTable(HuffmanTable_B8,
905                                          FX_ArraySize(HuffmanTable_B8),
906                                          HuffmanTable_HTOOB_B8);
907       pTRD->SBHUFFDS = Table_B8;
908     } else if (cSBHUFFDS == 1) {
909       Table_B9 = new CJBig2_HuffmanTable(HuffmanTable_B9,
910                                          FX_ArraySize(HuffmanTable_B9),
911                                          HuffmanTable_HTOOB_B9);
912       pTRD->SBHUFFDS = Table_B9;
913     } else if (cSBHUFFDS == 2) {
914       Table_B10 = new CJBig2_HuffmanTable(HuffmanTable_B10,
915                                           FX_ArraySize(HuffmanTable_B10),
916                                           HuffmanTable_HTOOB_B10);
917       pTRD->SBHUFFDS = Table_B10;
918     } else {
919       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
920       if (!pSeg) {
921         nRet = JBIG2_ERROR_FATAL;
922         goto failed;
923       }
924       pTRD->SBHUFFDS = pSeg->m_Result.ht;
925     }
926     if (cSBHUFFDT == 0) {
927       Table_B11 = new CJBig2_HuffmanTable(HuffmanTable_B11,
928                                           FX_ArraySize(HuffmanTable_B11),
929                                           HuffmanTable_HTOOB_B11);
930       pTRD->SBHUFFDT = Table_B11;
931     } else if (cSBHUFFDT == 1) {
932       Table_B12 = new CJBig2_HuffmanTable(HuffmanTable_B12,
933                                           FX_ArraySize(HuffmanTable_B12),
934                                           HuffmanTable_HTOOB_B12);
935       pTRD->SBHUFFDT = Table_B12;
936     } else if (cSBHUFFDT == 2) {
937       Table_B13 = new CJBig2_HuffmanTable(HuffmanTable_B13,
938                                           FX_ArraySize(HuffmanTable_B13),
939                                           HuffmanTable_HTOOB_B13);
940       pTRD->SBHUFFDT = Table_B13;
941     } else {
942       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
943       if (!pSeg) {
944         nRet = JBIG2_ERROR_FATAL;
945         goto failed;
946       }
947       pTRD->SBHUFFDT = pSeg->m_Result.ht;
948     }
949     if (cSBHUFFRDW == 0) {
950       Table_B14 = new CJBig2_HuffmanTable(HuffmanTable_B14,
951                                           FX_ArraySize(HuffmanTable_B14),
952                                           HuffmanTable_HTOOB_B14);
953       pTRD->SBHUFFRDW = Table_B14;
954     } else if (cSBHUFFRDW == 1) {
955       Table_B15 = new CJBig2_HuffmanTable(HuffmanTable_B15,
956                                           FX_ArraySize(HuffmanTable_B15),
957                                           HuffmanTable_HTOOB_B15);
958       pTRD->SBHUFFRDW = Table_B15;
959     } else {
960       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
961       if (!pSeg) {
962         nRet = JBIG2_ERROR_FATAL;
963         goto failed;
964       }
965       pTRD->SBHUFFRDW = pSeg->m_Result.ht;
966     }
967     if (cSBHUFFRDH == 0) {
968       if (!Table_B14) {
969         Table_B14 = new CJBig2_HuffmanTable(HuffmanTable_B14,
970                                             FX_ArraySize(HuffmanTable_B14),
971                                             HuffmanTable_HTOOB_B14);
972       }
973       pTRD->SBHUFFRDH = Table_B14;
974     } else if (cSBHUFFRDH == 1) {
975       if (!Table_B15) {
976         Table_B15 = new CJBig2_HuffmanTable(HuffmanTable_B15,
977                                             FX_ArraySize(HuffmanTable_B15),
978                                             HuffmanTable_HTOOB_B15);
979       }
980       pTRD->SBHUFFRDH = Table_B15;
981     } else {
982       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
983       if (!pSeg) {
984         nRet = JBIG2_ERROR_FATAL;
985         goto failed;
986       }
987       pTRD->SBHUFFRDH = pSeg->m_Result.ht;
988     }
989     if (cSBHUFFRDX == 0) {
990       if (!Table_B14) {
991         Table_B14 = new CJBig2_HuffmanTable(HuffmanTable_B14,
992                                             FX_ArraySize(HuffmanTable_B14),
993                                             HuffmanTable_HTOOB_B14);
994       }
995       pTRD->SBHUFFRDX = Table_B14;
996     } else if (cSBHUFFRDX == 1) {
997       if (!Table_B15) {
998         Table_B15 = new CJBig2_HuffmanTable(HuffmanTable_B15,
999                                             FX_ArraySize(HuffmanTable_B15),
1000                                             HuffmanTable_HTOOB_B15);
1001       }
1002       pTRD->SBHUFFRDX = Table_B15;
1003     } else {
1004       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1005       if (!pSeg) {
1006         nRet = JBIG2_ERROR_FATAL;
1007         goto failed;
1008       }
1009       pTRD->SBHUFFRDX = pSeg->m_Result.ht;
1010     }
1011     if (cSBHUFFRDY == 0) {
1012       if (!Table_B14) {
1013         Table_B14 = new CJBig2_HuffmanTable(HuffmanTable_B14,
1014                                             FX_ArraySize(HuffmanTable_B14),
1015                                             HuffmanTable_HTOOB_B14);
1016       }
1017       pTRD->SBHUFFRDY = Table_B14;
1018     } else if (cSBHUFFRDY == 1) {
1019       if (!Table_B15) {
1020         Table_B15 = new CJBig2_HuffmanTable(HuffmanTable_B15,
1021                                             FX_ArraySize(HuffmanTable_B15),
1022                                             HuffmanTable_HTOOB_B15);
1023       }
1024       pTRD->SBHUFFRDY = Table_B15;
1025     } else {
1026       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1027       if (!pSeg) {
1028         nRet = JBIG2_ERROR_FATAL;
1029         goto failed;
1030       }
1031       pTRD->SBHUFFRDY = pSeg->m_Result.ht;
1032     }
1033     if (cSBHUFFRSIZE == 0) {
1034       Table_B1 = new CJBig2_HuffmanTable(HuffmanTable_B1,
1035                                          FX_ArraySize(HuffmanTable_B1),
1036                                          HuffmanTable_HTOOB_B1);
1037       pTRD->SBHUFFRSIZE = Table_B1;
1038     } else {
1039       pSeg = findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
1040       if (!pSeg) {
1041         nRet = JBIG2_ERROR_FATAL;
1042         goto failed;
1043       }
1044       pTRD->SBHUFFRSIZE = pSeg->m_Result.ht;
1045     }
1046   }
1047   if (pTRD->SBREFINE == 1) {
1048     dwTemp = pTRD->SBRTEMPLATE ? 1 << 10 : 1 << 13;
1049     grContext = FX_Alloc(JBig2ArithCtx, dwTemp);
1050     JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1051   }
1052   if (pTRD->SBHUFF == 0) {
1053     pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
1054     pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1055     pSegment->m_Result.im = pTRD->decode_Arith(pArithDecoder, grContext);
1056     delete pArithDecoder;
1057     if (pSegment->m_Result.im == NULL) {
1058       nRet = JBIG2_ERROR_FATAL;
1059       goto failed;
1060     }
1061     m_pStream->alignByte();
1062     m_pStream->offset(2);
1063   } else {
1064     pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1065     pSegment->m_Result.im = pTRD->decode_Huffman(m_pStream, grContext);
1066     if (pSegment->m_Result.im == NULL) {
1067       nRet = JBIG2_ERROR_FATAL;
1068       goto failed;
1069     }
1070     m_pStream->alignByte();
1071   }
1072   if (pSegment->m_cFlags.s.type != 4) {
1073     if (!m_bBufSpecified) {
1074       JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1075       if ((pPageInfo->m_bIsStriped == 1) &&
1076           (ri.y + ri.height > m_pPage->m_nHeight)) {
1077         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1078       }
1079     }
1080     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1081                          (JBig2ComposeOp)(ri.flags & 0x03));
1082     delete pSegment->m_Result.im;
1083     pSegment->m_Result.im = NULL;
1084   }
1085   delete pTRD;
1086   FX_Free(SBSYMS);
1087   FX_Free(SBSYMCODES);
1088   FX_Free(grContext);
1089   delete Table_B1;
1090   delete Table_B6;
1091   delete Table_B7;
1092   delete Table_B8;
1093   delete Table_B9;
1094   delete Table_B10;
1095   delete Table_B11;
1096   delete Table_B12;
1097   delete Table_B13;
1098   delete Table_B14;
1099   delete Table_B15;
1100   return JBIG2_SUCCESS;
1101 failed:
1102   delete pTRD;
1103   FX_Free(SBSYMS);
1104   FX_Free(SBSYMCODES);
1105   FX_Free(grContext);
1106   delete Table_B1;
1107   delete Table_B6;
1108   delete Table_B7;
1109   delete Table_B8;
1110   delete Table_B9;
1111   delete Table_B10;
1112   delete Table_B11;
1113   delete Table_B12;
1114   delete Table_B13;
1115   delete Table_B14;
1116   delete Table_B15;
1117   return nRet;
1118 }
1119
1120 int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment,
1121                                          IFX_Pause* pPause) {
1122   FX_DWORD dwTemp;
1123   uint8_t cFlags;
1124   JBig2ArithCtx* gbContext;
1125   CJBig2_ArithDecoder* pArithDecoder;
1126   int32_t nRet;
1127   CJBig2_PDDProc* pPDD = new CJBig2_PDDProc();
1128   if ((m_pStream->read1Byte(&cFlags) != 0) ||
1129       (m_pStream->read1Byte(&pPDD->HDPW) != 0) ||
1130       (m_pStream->read1Byte(&pPDD->HDPH) != 0) ||
1131       (m_pStream->readInteger(&pPDD->GRAYMAX) != 0)) {
1132     nRet = JBIG2_ERROR_TOO_SHORT;
1133     goto failed;
1134   }
1135   if (pPDD->GRAYMAX > JBIG2_MAX_PATTERN_INDEX) {
1136     nRet = JBIG2_ERROR_LIMIT;
1137     goto failed;
1138   }
1139   pPDD->HDMMR = cFlags & 0x01;
1140   pPDD->HDTEMPLATE = (cFlags >> 1) & 0x03;
1141   pSegment->m_nResultType = JBIG2_PATTERN_DICT_POINTER;
1142   if (pPDD->HDMMR == 0) {
1143     dwTemp =
1144         pPDD->HDTEMPLATE == 0 ? 65536 : pPDD->HDTEMPLATE == 1 ? 8192 : 1024;
1145     gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
1146     JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1147     pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
1148     pSegment->m_Result.pd =
1149         pPDD->decode_Arith(pArithDecoder, gbContext, pPause);
1150     delete pArithDecoder;
1151     if (pSegment->m_Result.pd == NULL) {
1152       FX_Free(gbContext);
1153       nRet = JBIG2_ERROR_FATAL;
1154       goto failed;
1155     }
1156     FX_Free(gbContext);
1157     m_pStream->alignByte();
1158     m_pStream->offset(2);
1159   } else {
1160     pSegment->m_Result.pd = pPDD->decode_MMR(m_pStream, pPause);
1161     if (pSegment->m_Result.pd == NULL) {
1162       nRet = JBIG2_ERROR_FATAL;
1163       goto failed;
1164     }
1165     m_pStream->alignByte();
1166   }
1167   delete pPDD;
1168   return JBIG2_SUCCESS;
1169 failed:
1170   delete pPDD;
1171   return nRet;
1172 }
1173 int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment,
1174                                             IFX_Pause* pPause) {
1175   FX_DWORD dwTemp;
1176   uint8_t cFlags;
1177   JBig2RegionInfo ri;
1178   CJBig2_Segment* pSeg;
1179   CJBig2_PatternDict* pPatternDict;
1180   JBig2ArithCtx* gbContext;
1181   CJBig2_ArithDecoder* pArithDecoder;
1182   int32_t nRet;
1183   CJBig2_HTRDProc* pHRD = new CJBig2_HTRDProc();
1184   if ((parseRegionInfo(&ri) != JBIG2_SUCCESS) ||
1185       (m_pStream->read1Byte(&cFlags) != 0) ||
1186       (m_pStream->readInteger(&pHRD->HGW) != 0) ||
1187       (m_pStream->readInteger(&pHRD->HGH) != 0) ||
1188       (m_pStream->readInteger((FX_DWORD*)&pHRD->HGX) != 0) ||
1189       (m_pStream->readInteger((FX_DWORD*)&pHRD->HGY) != 0) ||
1190       (m_pStream->readShortInteger(&pHRD->HRX) != 0) ||
1191       (m_pStream->readShortInteger(&pHRD->HRY) != 0)) {
1192     nRet = JBIG2_ERROR_TOO_SHORT;
1193     goto failed;
1194   }
1195   pHRD->HBW = ri.width;
1196   pHRD->HBH = ri.height;
1197   pHRD->HMMR = cFlags & 0x01;
1198   pHRD->HTEMPLATE = (cFlags >> 1) & 0x03;
1199   pHRD->HENABLESKIP = (cFlags >> 3) & 0x01;
1200   pHRD->HCOMBOP = (JBig2ComposeOp)((cFlags >> 4) & 0x07);
1201   pHRD->HDEFPIXEL = (cFlags >> 7) & 0x01;
1202   if (pSegment->m_nReferred_to_segment_count != 1) {
1203     nRet = JBIG2_ERROR_FATAL;
1204     goto failed;
1205   }
1206   pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
1207   if ((pSeg == NULL) || (pSeg->m_cFlags.s.type != 16)) {
1208     nRet = JBIG2_ERROR_FATAL;
1209     goto failed;
1210   }
1211   pPatternDict = pSeg->m_Result.pd;
1212   if ((pPatternDict == NULL) || (pPatternDict->NUMPATS == 0)) {
1213     nRet = JBIG2_ERROR_FATAL;
1214     goto failed;
1215   }
1216   pHRD->HNUMPATS = pPatternDict->NUMPATS;
1217   pHRD->HPATS = pPatternDict->HDPATS;
1218   pHRD->HPW = pPatternDict->HDPATS[0]->m_nWidth;
1219   pHRD->HPH = pPatternDict->HDPATS[0]->m_nHeight;
1220   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1221   if (pHRD->HMMR == 0) {
1222     dwTemp = pHRD->HTEMPLATE == 0 ? 65536 : pHRD->HTEMPLATE == 1 ? 8192 : 1024;
1223     gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
1224     JBIG2_memset(gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1225     pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
1226     pSegment->m_Result.im =
1227         pHRD->decode_Arith(pArithDecoder, gbContext, pPause);
1228     delete pArithDecoder;
1229     if (pSegment->m_Result.im == NULL) {
1230       FX_Free(gbContext);
1231       nRet = JBIG2_ERROR_FATAL;
1232       goto failed;
1233     }
1234     FX_Free(gbContext);
1235     m_pStream->alignByte();
1236     m_pStream->offset(2);
1237   } else {
1238     pSegment->m_Result.im = pHRD->decode_MMR(m_pStream, pPause);
1239     if (pSegment->m_Result.im == NULL) {
1240       nRet = JBIG2_ERROR_FATAL;
1241       goto failed;
1242     }
1243     m_pStream->alignByte();
1244   }
1245   if (pSegment->m_cFlags.s.type != 20) {
1246     if (!m_bBufSpecified) {
1247       JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1248       if ((pPageInfo->m_bIsStriped == 1) &&
1249           (ri.y + ri.height > m_pPage->m_nHeight)) {
1250         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1251       }
1252     }
1253     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1254                          (JBig2ComposeOp)(ri.flags & 0x03));
1255     delete pSegment->m_Result.im;
1256     pSegment->m_Result.im = NULL;
1257   }
1258   delete pHRD;
1259   return JBIG2_SUCCESS;
1260 failed:
1261   delete pHRD;
1262   return nRet;
1263 }
1264
1265 int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment,
1266                                            IFX_Pause* pPause) {
1267   FX_DWORD dwTemp;
1268   uint8_t cFlags;
1269   int32_t i, nRet;
1270   if (m_pGRD == NULL) {
1271     m_pGRD = new CJBig2_GRDProc();
1272     if ((parseRegionInfo(&m_ri) != JBIG2_SUCCESS) ||
1273         (m_pStream->read1Byte(&cFlags) != 0)) {
1274       nRet = JBIG2_ERROR_TOO_SHORT;
1275       goto failed;
1276     }
1277     if (m_ri.height < 0 || m_ri.width < 0) {
1278       nRet = JBIG2_FAILED;
1279       goto failed;
1280     }
1281     m_pGRD->GBW = m_ri.width;
1282     m_pGRD->GBH = m_ri.height;
1283     m_pGRD->MMR = cFlags & 0x01;
1284     m_pGRD->GBTEMPLATE = (cFlags >> 1) & 0x03;
1285     m_pGRD->TPGDON = (cFlags >> 3) & 0x01;
1286     if (m_pGRD->MMR == 0) {
1287       if (m_pGRD->GBTEMPLATE == 0) {
1288         for (i = 0; i < 8; i++) {
1289           if (m_pStream->read1Byte((uint8_t*)&m_pGRD->GBAT[i]) != 0) {
1290             nRet = JBIG2_ERROR_TOO_SHORT;
1291             goto failed;
1292           }
1293         }
1294       } else {
1295         for (i = 0; i < 2; 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       }
1302     }
1303     m_pGRD->USESKIP = 0;
1304   }
1305   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1306   if (m_pGRD->MMR == 0) {
1307     dwTemp =
1308         m_pGRD->GBTEMPLATE == 0 ? 65536 : m_pGRD->GBTEMPLATE == 1 ? 8192 : 1024;
1309     if (m_gbContext == NULL) {
1310       m_gbContext = FX_Alloc(JBig2ArithCtx, dwTemp);
1311       JBIG2_memset(m_gbContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1312     }
1313     if (m_pArithDecoder == NULL) {
1314       m_pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
1315       m_ProcessiveStatus = m_pGRD->Start_decode_Arith(
1316           &pSegment->m_Result.im, m_pArithDecoder, m_gbContext, pPause);
1317     } else {
1318       m_ProcessiveStatus = m_pGRD->Continue_decode(pPause);
1319     }
1320     if (m_ProcessiveStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
1321       if (pSegment->m_cFlags.s.type != 36) {
1322         if (!m_bBufSpecified) {
1323           JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1324           if ((pPageInfo->m_bIsStriped == 1) &&
1325               (m_ri.y + m_ri.height > m_pPage->m_nHeight)) {
1326             m_pPage->expand(m_ri.y + m_ri.height,
1327                             (pPageInfo->m_cFlags & 4) ? 1 : 0);
1328           }
1329         }
1330         FX_RECT Rect = m_pGRD->GetReplaceRect();
1331         m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
1332                              pSegment->m_Result.im,
1333                              (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
1334       }
1335       return JBIG2_SUCCESS;
1336     } else {
1337       delete m_pArithDecoder;
1338       m_pArithDecoder = NULL;
1339       if (pSegment->m_Result.im == NULL) {
1340         FX_Free(m_gbContext);
1341         nRet = JBIG2_ERROR_FATAL;
1342         m_gbContext = NULL;
1343         m_ProcessiveStatus = FXCODEC_STATUS_ERROR;
1344         goto failed;
1345       }
1346       FX_Free(m_gbContext);
1347       m_gbContext = NULL;
1348       m_pStream->alignByte();
1349       m_pStream->offset(2);
1350     }
1351   } else {
1352     FXCODEC_STATUS status =
1353         m_pGRD->Start_decode_MMR(&pSegment->m_Result.im, m_pStream, pPause);
1354     while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
1355       m_pGRD->Continue_decode(pPause);
1356     }
1357     if (pSegment->m_Result.im == NULL) {
1358       nRet = JBIG2_ERROR_FATAL;
1359       goto failed;
1360     }
1361     m_pStream->alignByte();
1362   }
1363   if (pSegment->m_cFlags.s.type != 36) {
1364     if (!m_bBufSpecified) {
1365       JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1366       if ((pPageInfo->m_bIsStriped == 1) &&
1367           (m_ri.y + m_ri.height > m_pPage->m_nHeight)) {
1368         m_pPage->expand(m_ri.y + m_ri.height,
1369                         (pPageInfo->m_cFlags & 4) ? 1 : 0);
1370       }
1371     }
1372     FX_RECT Rect = m_pGRD->GetReplaceRect();
1373     m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
1374                          pSegment->m_Result.im,
1375                          (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
1376     delete pSegment->m_Result.im;
1377     pSegment->m_Result.im = NULL;
1378   }
1379   delete m_pGRD;
1380   m_pGRD = NULL;
1381   return JBIG2_SUCCESS;
1382 failed:
1383   delete m_pGRD;
1384   m_pGRD = NULL;
1385   return nRet;
1386 }
1387
1388 int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) {
1389   FX_DWORD dwTemp;
1390   JBig2RegionInfo ri;
1391   CJBig2_Segment* pSeg;
1392   int32_t i, nRet;
1393   uint8_t cFlags;
1394   JBig2ArithCtx* grContext;
1395   CJBig2_ArithDecoder* pArithDecoder;
1396   CJBig2_GRRDProc* pGRRD = new CJBig2_GRRDProc();
1397   if ((parseRegionInfo(&ri) != JBIG2_SUCCESS) ||
1398       (m_pStream->read1Byte(&cFlags) != 0)) {
1399     nRet = JBIG2_ERROR_TOO_SHORT;
1400     goto failed;
1401   }
1402   pGRRD->GRW = ri.width;
1403   pGRRD->GRH = ri.height;
1404   pGRRD->GRTEMPLATE = cFlags & 0x01;
1405   pGRRD->TPGRON = (cFlags >> 1) & 0x01;
1406   if (pGRRD->GRTEMPLATE == 0) {
1407     for (i = 0; i < 4; i++) {
1408       if (m_pStream->read1Byte((uint8_t*)&pGRRD->GRAT[i]) != 0) {
1409         nRet = JBIG2_ERROR_TOO_SHORT;
1410         goto failed;
1411       }
1412     }
1413   }
1414   pSeg = NULL;
1415   if (pSegment->m_nReferred_to_segment_count > 0) {
1416     for (i = 0; i < pSegment->m_nReferred_to_segment_count; i++) {
1417       pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
1418       if (pSeg == NULL) {
1419         nRet = JBIG2_ERROR_FATAL;
1420         goto failed;
1421       }
1422       if ((pSeg->m_cFlags.s.type == 4) || (pSeg->m_cFlags.s.type == 20) ||
1423           (pSeg->m_cFlags.s.type == 36) || (pSeg->m_cFlags.s.type == 40)) {
1424         break;
1425       }
1426     }
1427     if (i >= pSegment->m_nReferred_to_segment_count) {
1428       nRet = JBIG2_ERROR_FATAL;
1429       goto failed;
1430     }
1431     pGRRD->GRREFERENCE = pSeg->m_Result.im;
1432   } else {
1433     pGRRD->GRREFERENCE = m_pPage;
1434   }
1435   pGRRD->GRREFERENCEDX = 0;
1436   pGRRD->GRREFERENCEDY = 0;
1437   dwTemp = pGRRD->GRTEMPLATE ? 1 << 10 : 1 << 13;
1438   grContext = FX_Alloc(JBig2ArithCtx, dwTemp);
1439   JBIG2_memset(grContext, 0, sizeof(JBig2ArithCtx) * dwTemp);
1440   pArithDecoder = new CJBig2_ArithDecoder(m_pStream);
1441   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1442   pSegment->m_Result.im = pGRRD->decode(pArithDecoder, grContext);
1443   delete pArithDecoder;
1444   if (pSegment->m_Result.im == NULL) {
1445     FX_Free(grContext);
1446     nRet = JBIG2_ERROR_FATAL;
1447     goto failed;
1448   }
1449   FX_Free(grContext);
1450   m_pStream->alignByte();
1451   m_pStream->offset(2);
1452   if (pSegment->m_cFlags.s.type != 40) {
1453     if (!m_bBufSpecified) {
1454       JBig2PageInfo* pPageInfo = m_PageInfoList.back();
1455       if ((pPageInfo->m_bIsStriped == 1) &&
1456           (ri.y + ri.height > m_pPage->m_nHeight)) {
1457         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1458       }
1459     }
1460     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1461                          (JBig2ComposeOp)(ri.flags & 0x03));
1462     delete pSegment->m_Result.im;
1463     pSegment->m_Result.im = NULL;
1464   }
1465   delete pGRRD;
1466   return JBIG2_SUCCESS;
1467 failed:
1468   delete pGRRD;
1469   return nRet;
1470 }
1471 int32_t CJBig2_Context::parseTable(CJBig2_Segment* pSegment) {
1472   pSegment->m_nResultType = JBIG2_HUFFMAN_TABLE_POINTER;
1473   pSegment->m_Result.ht = new CJBig2_HuffmanTable(m_pStream);
1474   if (!pSegment->m_Result.ht->isOK()) {
1475     delete pSegment->m_Result.ht;
1476     pSegment->m_Result.ht = NULL;
1477     return JBIG2_ERROR_FATAL;
1478   }
1479   m_pStream->alignByte();
1480   return JBIG2_SUCCESS;
1481 }
1482 int32_t CJBig2_Context::parseRegionInfo(JBig2RegionInfo* pRI) {
1483   if ((m_pStream->readInteger((FX_DWORD*)&pRI->width) != 0) ||
1484       (m_pStream->readInteger((FX_DWORD*)&pRI->height) != 0) ||
1485       (m_pStream->readInteger((FX_DWORD*)&pRI->x) != 0) ||
1486       (m_pStream->readInteger((FX_DWORD*)&pRI->y) != 0) ||
1487       (m_pStream->read1Byte(&pRI->flags) != 0)) {
1488     return JBIG2_ERROR_TOO_SHORT;
1489   }
1490   return JBIG2_SUCCESS;
1491 }
1492 JBig2HuffmanCode* CJBig2_Context::decodeSymbolIDHuffmanTable(
1493     CJBig2_BitStream* pStream,
1494     FX_DWORD SBNUMSYMS) {
1495   JBig2HuffmanCode* SBSYMCODES;
1496   int32_t runcodes[35];
1497   int32_t runcodes_len[35];
1498   int32_t runcode;
1499   int32_t i;
1500   int32_t j;
1501   int32_t nVal;
1502   int32_t nBits;
1503   int32_t run;
1504   FX_DWORD nTemp;
1505   SBSYMCODES = FX_Alloc(JBig2HuffmanCode, SBNUMSYMS);
1506   for (i = 0; i < 35; i++) {
1507     if (pStream->readNBits(4, &runcodes_len[i]) != 0) {
1508       goto failed;
1509     }
1510   }
1511   huffman_assign_code(runcodes, runcodes_len, 35);
1512   i = 0;
1513   while (i < (int)SBNUMSYMS) {
1514     nVal = 0;
1515     nBits = 0;
1516     for (;;) {
1517       if (pStream->read1Bit(&nTemp) != 0) {
1518         goto failed;
1519       }
1520       nVal = (nVal << 1) | nTemp;
1521       nBits++;
1522       for (j = 0; j < 35; j++) {
1523         if ((nBits == runcodes_len[j]) && (nVal == runcodes[j])) {
1524           break;
1525         }
1526       }
1527       if (j < 35) {
1528         break;
1529       }
1530     }
1531     runcode = j;
1532     if (runcode < 32) {
1533       SBSYMCODES[i].codelen = runcode;
1534       run = 0;
1535     } else if (runcode == 32) {
1536       if (pStream->readNBits(2, &nTemp) != 0) {
1537         goto failed;
1538       }
1539       run = nTemp + 3;
1540     } else if (runcode == 33) {
1541       if (pStream->readNBits(3, &nTemp) != 0) {
1542         goto failed;
1543       }
1544       run = nTemp + 3;
1545     } else if (runcode == 34) {
1546       if (pStream->readNBits(7, &nTemp) != 0) {
1547         goto failed;
1548       }
1549       run = nTemp + 11;
1550     }
1551     if (run > 0) {
1552       if (i + run > (int)SBNUMSYMS) {
1553         goto failed;
1554       }
1555       for (j = 0; j < run; j++) {
1556         if (runcode == 32 && i > 0) {
1557           SBSYMCODES[i + j].codelen = SBSYMCODES[i - 1].codelen;
1558         } else {
1559           SBSYMCODES[i + j].codelen = 0;
1560         }
1561       }
1562       i += run;
1563     } else {
1564       i++;
1565     }
1566   }
1567   huffman_assign_code(SBSYMCODES, SBNUMSYMS);
1568   return SBSYMCODES;
1569 failed:
1570   FX_Free(SBSYMCODES);
1571   return NULL;
1572 }
1573 void CJBig2_Context::huffman_assign_code(int* CODES, int* PREFLEN, int NTEMP) {
1574   int CURLEN, LENMAX, CURCODE, CURTEMP, i;
1575   int* LENCOUNT;
1576   int* FIRSTCODE;
1577   LENMAX = 0;
1578   for (i = 0; i < NTEMP; i++) {
1579     if (PREFLEN[i] > LENMAX) {
1580       LENMAX = PREFLEN[i];
1581     }
1582   }
1583   LENCOUNT = FX_Alloc(int, LENMAX + 1);
1584   JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
1585   FIRSTCODE = FX_Alloc(int, LENMAX + 1);
1586   for (i = 0; i < NTEMP; i++) {
1587     LENCOUNT[PREFLEN[i]]++;
1588   }
1589   CURLEN = 1;
1590   FIRSTCODE[0] = 0;
1591   LENCOUNT[0] = 0;
1592   while (CURLEN <= LENMAX) {
1593     FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
1594     CURCODE = FIRSTCODE[CURLEN];
1595     CURTEMP = 0;
1596     while (CURTEMP < NTEMP) {
1597       if (PREFLEN[CURTEMP] == CURLEN) {
1598         CODES[CURTEMP] = CURCODE;
1599         CURCODE = CURCODE + 1;
1600       }
1601       CURTEMP = CURTEMP + 1;
1602     }
1603     CURLEN = CURLEN + 1;
1604   }
1605   FX_Free(LENCOUNT);
1606   FX_Free(FIRSTCODE);
1607 }
1608 void CJBig2_Context::huffman_assign_code(JBig2HuffmanCode* SBSYMCODES,
1609                                          int NTEMP) {
1610   int CURLEN, LENMAX, CURCODE, CURTEMP, i;
1611   int* LENCOUNT;
1612   int* FIRSTCODE;
1613   LENMAX = 0;
1614   for (i = 0; i < NTEMP; i++) {
1615     if (SBSYMCODES[i].codelen > LENMAX) {
1616       LENMAX = SBSYMCODES[i].codelen;
1617     }
1618   }
1619   LENCOUNT = FX_Alloc(int, (LENMAX + 1));
1620   JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
1621   FIRSTCODE = FX_Alloc(int, (LENMAX + 1));
1622   for (i = 0; i < NTEMP; i++) {
1623     LENCOUNT[SBSYMCODES[i].codelen]++;
1624   }
1625   CURLEN = 1;
1626   FIRSTCODE[0] = 0;
1627   LENCOUNT[0] = 0;
1628   while (CURLEN <= LENMAX) {
1629     FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
1630     CURCODE = FIRSTCODE[CURLEN];
1631     CURTEMP = 0;
1632     while (CURTEMP < NTEMP) {
1633       if (SBSYMCODES[CURTEMP].codelen == CURLEN) {
1634         SBSYMCODES[CURTEMP].code = CURCODE;
1635         CURCODE = CURCODE + 1;
1636       }
1637       CURTEMP = CURTEMP + 1;
1638     }
1639     CURLEN = CURLEN + 1;
1640   }
1641   FX_Free(LENCOUNT);
1642   FX_Free(FIRSTCODE);
1643 }