| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svtools.hxx" |
| |
| #include "decode.hxx" |
| |
| // ------------------------------------------------------------------------ |
| |
| struct GIFLZWTableEntry |
| { |
| GIFLZWTableEntry* pPrev; |
| GIFLZWTableEntry* pFirst; |
| sal_uInt8 nData; |
| }; |
| |
| // ------------------------------------------------------------------------ |
| |
| GIFLZWDecompressor::GIFLZWDecompressor( sal_uInt8 cDataSize ) : |
| nInputBitsBuf ( 0 ), |
| nOutBufDataLen ( 0 ), |
| nInputBitsBufSize ( 0 ), |
| bEOIFound ( sal_False ), |
| nDataSize ( cDataSize ) |
| { |
| pOutBuf = new sal_uInt8[ 4096 ]; |
| |
| nClearCode = 1 << nDataSize; |
| nEOICode = nClearCode + 1; |
| nTableSize = nEOICode + 1; |
| nCodeSize = nDataSize + 1; |
| nOldCode = 0xffff; |
| pOutBufData = pOutBuf + 4096; |
| |
| pTable = new GIFLZWTableEntry[ 4098 ]; |
| |
| for( sal_uInt16 i = 0; i < nTableSize; i++ ) |
| { |
| pTable[i].pPrev = NULL; |
| pTable[i].pFirst = pTable + i; |
| pTable[i].nData = (sal_uInt8) i; |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| GIFLZWDecompressor::~GIFLZWDecompressor() |
| { |
| delete[] pOutBuf; |
| delete[] pTable; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| HPBYTE GIFLZWDecompressor::DecompressBlock( HPBYTE pSrc, sal_uInt8 cBufSize, |
| sal_uLong& rCount, sal_Bool& rEOI ) |
| { |
| sal_uLong nTargetSize = 4096; |
| sal_uLong nCount = 0; |
| HPBYTE pTarget = (HPBYTE) rtl_allocateMemory( nTargetSize ); |
| HPBYTE pTmpTarget = pTarget; |
| |
| nBlockBufSize = cBufSize; |
| nBlockBufPos = 0; |
| pBlockBuf = pSrc; |
| |
| while( ProcessOneCode() ) |
| { |
| nCount += nOutBufDataLen; |
| |
| if( nCount > nTargetSize ) |
| { |
| sal_uLong nNewSize = nTargetSize << 1; |
| sal_uLong nOffset = pTmpTarget - pTarget; |
| HPBYTE pTmp = (HPBYTE) rtl_allocateMemory( nNewSize ); |
| |
| memcpy( pTmp, pTarget, nTargetSize ); |
| rtl_freeMemory( pTarget ); |
| |
| nTargetSize = nNewSize; |
| pTmpTarget = ( pTarget = pTmp ) + nOffset; |
| } |
| |
| memcpy( pTmpTarget, pOutBufData, nOutBufDataLen ); |
| pTmpTarget += nOutBufDataLen; |
| pOutBufData += nOutBufDataLen; |
| nOutBufDataLen = 0; |
| |
| if ( bEOIFound ) |
| break; |
| } |
| |
| rCount = nCount; |
| rEOI = bEOIFound; |
| |
| return pTarget; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| void GIFLZWDecompressor::AddToTable( sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData ) |
| { |
| GIFLZWTableEntry* pE; |
| |
| if( nTableSize < 4096 ) |
| { |
| pE = pTable + nTableSize; |
| pE->pPrev = pTable + nPrevCode; |
| pE->pFirst = pE->pPrev->pFirst; |
| pE->nData = pTable[ nCodeFirstData ].pFirst->nData; |
| nTableSize++; |
| |
| if ( ( nTableSize == (sal_uInt16) (1 << nCodeSize) ) && ( nTableSize < 4096 ) ) |
| nCodeSize++; |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| sal_Bool GIFLZWDecompressor::ProcessOneCode() |
| { |
| GIFLZWTableEntry* pE; |
| sal_uInt16 nCode; |
| sal_Bool bRet = sal_False; |
| sal_Bool bEndOfBlock = sal_False; |
| |
| while( nInputBitsBufSize < nCodeSize ) |
| { |
| if( nBlockBufPos >= nBlockBufSize ) |
| { |
| bEndOfBlock = sal_True; |
| break; |
| } |
| |
| nInputBitsBuf |= ( (sal_uLong) pBlockBuf[ nBlockBufPos++ ] ) << nInputBitsBufSize; |
| nInputBitsBufSize += 8; |
| } |
| |
| if ( !bEndOfBlock ) |
| { |
| // Einen Code aus dem Eingabe-Buffer holen: |
| nCode = sal::static_int_cast< sal_uInt16 >( |
| ( (sal_uInt16) nInputBitsBuf ) & ( ~( 0xffff << nCodeSize ) )); |
| nInputBitsBuf >>= nCodeSize; |
| nInputBitsBufSize = nInputBitsBufSize - nCodeSize; |
| |
| if ( nCode < nClearCode ) |
| { |
| if ( nOldCode != 0xffff ) |
| AddToTable( nOldCode, nCode ); |
| } |
| else if ( ( nCode > nEOICode ) && ( nCode <= nTableSize ) ) |
| { |
| if ( nCode == nTableSize ) |
| AddToTable( nOldCode, nOldCode ); |
| else |
| AddToTable( nOldCode, nCode ); |
| } |
| else |
| { |
| if ( nCode == nClearCode ) |
| { |
| nTableSize = nEOICode + 1; |
| nCodeSize = nDataSize + 1; |
| nOldCode = 0xffff; |
| nOutBufDataLen = 0; |
| } |
| else |
| bEOIFound = sal_True; |
| |
| return sal_True; |
| } |
| |
| nOldCode = nCode; |
| |
| // Zeichen(/-folge) des Codes nCode in den Ausgabe-Buffer schreiben: |
| pE = pTable + nCode; |
| do |
| { |
| nOutBufDataLen++; |
| *(--pOutBufData) = pE->nData; |
| pE = pE->pPrev; |
| } |
| while( pE ); |
| |
| bRet = sal_True; |
| } |
| |
| return bRet; |
| } |