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