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