/************************************************************** * * 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; }