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