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.
18const int kSymbolDictCacheMaxSize = 2;
19
20void OutputBitmap(CJBig2_Image* pImage)
21{
22    if(!pImage) {
23        return;
24    }
25}
26CJBig2_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}
31void CJBig2_Context::DestroyContext(CJBig2_Context *pContext)
32{
33    if(pContext) {
34        delete pContext;
35    }
36}
37CJBig2_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}
64CJBig2_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}
99FX_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    }
139failed:
140    return nRet;
141}
142FX_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}
192FX_INT32 CJBig2_Context::decode_EmbedOrgnazation(IFX_Pause* pPause)
193{
194    return decode_SquentialOrgnazation(pPause);
195}
196FX_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}
220FX_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}
238FX_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}
263FX_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}
314FX_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}
348FX_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}
362FX_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}
391CJBig2_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}
409CJBig2_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}
427FX_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;
503failed:
504    m_pModule->JBig2_Error("header too short.");
505    return JBIG2_ERROR_TOO_SHORT;
506}
507FX_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}
515FX_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;
609failed1:
610    m_pModule->JBig2_Error("segment data too short.");
611    return JBIG2_ERROR_TOO_SHORT;
612failed2:
613    m_pModule->JBig2_Error("segment syntax error.");
614    return JBIG2_ERROR_FETAL;
615}
616FX_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;
887failed:
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
916FX_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;
1279failed:
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
1326FX_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;
1376failed:
1377    delete pPDD;
1378    return nRet;
1379}
1380FX_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;
1469failed:
1470    delete pHRD;
1471    return nRet;
1472}
1473
1474FX_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;
1585failed:
1586    delete m_pGRD;
1587    m_pGRD = NULL;
1588    return nRet;
1589}
1590
1591FX_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;
1674failed:
1675    delete pGRRD;
1676    return nRet;
1677}
1678FX_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}
1690FX_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}
1701JBig2HuffmanCode *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;
1772failed:
1773    m_pModule->JBig2_Free(SBSYMCODES);
1774    return NULL;
1775}
1776void 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}
1812void 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}
1848