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