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