Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : :
21 : : #include "decode.hxx"
22 : :
23 : : // ------------------------------------------------------------------------
24 : :
25 : : struct GIFLZWTableEntry
26 : : {
27 : : GIFLZWTableEntry* pPrev;
28 : : GIFLZWTableEntry* pFirst;
29 : : sal_uInt8 nData;
30 : : };
31 : :
32 : : // ------------------------------------------------------------------------
33 : :
34 : 282 : GIFLZWDecompressor::GIFLZWDecompressor( sal_uInt8 cDataSize ) :
35 : : nInputBitsBuf ( 0 ),
36 : : nOutBufDataLen ( 0 ),
37 : : nInputBitsBufSize ( 0 ),
38 : : bEOIFound ( sal_False ),
39 : 282 : nDataSize ( cDataSize )
40 : : {
41 : 282 : pOutBuf = new sal_uInt8[ 4096 ];
42 : :
43 : 282 : nClearCode = 1 << nDataSize;
44 : 282 : nEOICode = nClearCode + 1;
45 : 282 : nTableSize = nEOICode + 1;
46 : 282 : nCodeSize = nDataSize + 1;
47 : 282 : nOldCode = 0xffff;
48 : 282 : pOutBufData = pOutBuf + 4096;
49 : :
50 : 282 : pTable = new GIFLZWTableEntry[ 4098 ];
51 : :
52 [ + + ]: 42318 : for( sal_uInt16 i = 0; i < nTableSize; i++ )
53 : : {
54 : 42036 : pTable[i].pPrev = NULL;
55 : 42036 : pTable[i].pFirst = pTable + i;
56 : 42036 : pTable[i].nData = (sal_uInt8) i;
57 : : }
58 : 282 : }
59 : :
60 : : // ------------------------------------------------------------------------
61 : :
62 : 282 : GIFLZWDecompressor::~GIFLZWDecompressor()
63 : : {
64 [ + - ]: 282 : delete[] pOutBuf;
65 [ + - ]: 282 : delete[] pTable;
66 : 282 : }
67 : :
68 : : // ------------------------------------------------------------------------
69 : :
70 : 447 : HPBYTE GIFLZWDecompressor::DecompressBlock( HPBYTE pSrc, sal_uInt8 cBufSize,
71 : : sal_uLong& rCount, sal_Bool& rEOI )
72 : : {
73 : 447 : sal_uLong nTargetSize = 4096;
74 : 447 : sal_uLong nCount = 0;
75 : 447 : HPBYTE pTarget = (HPBYTE) rtl_allocateMemory( nTargetSize );
76 : 447 : HPBYTE pTmpTarget = pTarget;
77 : :
78 : 447 : nBlockBufSize = cBufSize;
79 : 447 : nBlockBufPos = 0;
80 : 447 : pBlockBuf = pSrc;
81 : :
82 [ + + ]: 62927 : while( ProcessOneCode() )
83 : : {
84 : 62762 : nCount += nOutBufDataLen;
85 : :
86 [ - + ]: 62762 : if( nCount > nTargetSize )
87 : : {
88 : 0 : sal_uLong nNewSize = nTargetSize << 1;
89 : 0 : sal_uLong nOffset = pTmpTarget - pTarget;
90 : 0 : HPBYTE pTmp = (HPBYTE) rtl_allocateMemory( nNewSize );
91 : :
92 : 0 : memcpy( pTmp, pTarget, nTargetSize );
93 : 0 : rtl_freeMemory( pTarget );
94 : :
95 : 0 : nTargetSize = nNewSize;
96 : 0 : pTmpTarget = ( pTarget = pTmp ) + nOffset;
97 : : }
98 : :
99 : 62762 : memcpy( pTmpTarget, pOutBufData, nOutBufDataLen );
100 : 62762 : pTmpTarget += nOutBufDataLen;
101 : 62762 : pOutBufData += nOutBufDataLen;
102 : 62762 : nOutBufDataLen = 0;
103 : :
104 [ + + ]: 62762 : if ( bEOIFound )
105 : 282 : break;
106 : : }
107 : :
108 : 447 : rCount = nCount;
109 : 447 : rEOI = bEOIFound;
110 : :
111 : 447 : return pTarget;
112 : : }
113 : :
114 : : // ------------------------------------------------------------------------
115 : :
116 : 61916 : void GIFLZWDecompressor::AddToTable( sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData )
117 : : {
118 : : GIFLZWTableEntry* pE;
119 : :
120 [ + - ]: 61916 : if( nTableSize < 4096 )
121 : : {
122 : 61916 : pE = pTable + nTableSize;
123 : 61916 : pE->pPrev = pTable + nPrevCode;
124 : 61916 : pE->pFirst = pE->pPrev->pFirst;
125 : 61916 : pE->nData = pTable[ nCodeFirstData ].pFirst->nData;
126 : 61916 : nTableSize++;
127 : :
128 [ + + ][ + - ]: 61916 : if ( ( nTableSize == (sal_uInt16) (1 << nCodeSize) ) && ( nTableSize < 4096 ) )
129 : 515 : nCodeSize++;
130 : : }
131 : 61916 : }
132 : :
133 : : // ------------------------------------------------------------------------
134 : :
135 : 62927 : sal_Bool GIFLZWDecompressor::ProcessOneCode()
136 : : {
137 : : GIFLZWTableEntry* pE;
138 : : sal_uInt16 nCode;
139 : 62927 : sal_Bool bRet = sal_False;
140 : 62927 : sal_Bool bEndOfBlock = sal_False;
141 : :
142 [ + + ]: 129426 : while( nInputBitsBufSize < nCodeSize )
143 : : {
144 [ + + ]: 66664 : if( nBlockBufPos >= nBlockBufSize )
145 : : {
146 : 165 : bEndOfBlock = sal_True;
147 : 165 : break;
148 : : }
149 : :
150 : 66499 : nInputBitsBuf |= ( (sal_uLong) pBlockBuf[ nBlockBufPos++ ] ) << nInputBitsBufSize;
151 : 66499 : nInputBitsBufSize += 8;
152 : : }
153 : :
154 [ + + ]: 62927 : if ( !bEndOfBlock )
155 : : {
156 : : // Einen Code aus dem Eingabe-Buffer holen:
157 : : nCode = sal::static_int_cast< sal_uInt16 >(
158 : 62762 : ( (sal_uInt16) nInputBitsBuf ) & ( ~( 0xffff << nCodeSize ) ));
159 : 62762 : nInputBitsBuf >>= nCodeSize;
160 : 62762 : nInputBitsBufSize = nInputBitsBufSize - nCodeSize;
161 : :
162 [ + + ]: 62762 : if ( nCode < nClearCode )
163 : : {
164 [ + + ]: 38781 : if ( nOldCode != 0xffff )
165 : 38499 : AddToTable( nOldCode, nCode );
166 : : }
167 [ + + ][ + + ]: 23981 : else if ( ( nCode > nEOICode ) && ( nCode <= nTableSize ) )
168 : : {
169 [ + + ]: 46834 : if ( nCode == nTableSize )
170 : 3081 : AddToTable( nOldCode, nOldCode );
171 : : else
172 : 20336 : AddToTable( nOldCode, nCode );
173 : : }
174 : : else
175 : : {
176 [ + + ]: 564 : if ( nCode == nClearCode )
177 : : {
178 : 282 : nTableSize = nEOICode + 1;
179 : 282 : nCodeSize = nDataSize + 1;
180 : 282 : nOldCode = 0xffff;
181 : 282 : nOutBufDataLen = 0;
182 : : }
183 : : else
184 : 282 : bEOIFound = sal_True;
185 : :
186 : 564 : return sal_True;
187 : : }
188 : :
189 : 62198 : nOldCode = nCode;
190 : :
191 : : // Zeichen(/-folge) des Codes nCode in den Ausgabe-Buffer schreiben:
192 : 62198 : pE = pTable + nCode;
193 [ + + ]: 127557 : do
194 : : {
195 : 127557 : nOutBufDataLen++;
196 : 127557 : *(--pOutBufData) = pE->nData;
197 : 127557 : pE = pE->pPrev;
198 : : }
199 : : while( pE );
200 : :
201 : 62198 : bRet = sal_True;
202 : : }
203 : :
204 : 62927 : return bRet;
205 : : }
206 : :
207 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|