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