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