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