cid#1606940 Check of thread-shared field evades lock acquisition
[LibreOffice.git] / vcl / source / filter / egif / giflzwc.cxx
blob95137f75fa0d931c9b88553923666c3c653d3907
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <tools/stream.hxx>
22 #include "giflzwc.hxx"
23 #include <array>
26 class GIFImageDataOutputStream
28 private:
30 void FlushBlockBuf();
31 inline void FlushBitsBufsFullBytes();
33 SvStream& rStream;
34 std::array<sal_uInt8, 255>
35 pBlockBuf;
36 sal_uInt8 nBlockBufSize;
37 sal_uInt32 nBitsBuf;
38 sal_uInt16 nBitsBufSize;
40 public:
42 GIFImageDataOutputStream( SvStream & rGIF, sal_uInt8 nLZWDataSize );
43 ~GIFImageDataOutputStream();
45 inline void WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen );
49 inline void GIFImageDataOutputStream::FlushBitsBufsFullBytes()
51 while (nBitsBufSize>=8)
53 if( nBlockBufSize==255 )
54 FlushBlockBuf();
56 assert(nBlockBufSize != 255 && "FlushBlockBuf ensures this is incrementable without overflow");
57 pBlockBuf[nBlockBufSize++] = static_cast<sal_uInt8>(nBitsBuf);
58 nBitsBuf >>= 8;
59 nBitsBufSize -= 8;
64 inline void GIFImageDataOutputStream::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen )
66 if( nBitsBufSize+nCodeLen>32 )
67 FlushBitsBufsFullBytes();
69 nBitsBuf |= static_cast<sal_uInt32>(nCode) << nBitsBufSize;
70 nBitsBufSize = nBitsBufSize + nCodeLen;
74 GIFImageDataOutputStream::GIFImageDataOutputStream( SvStream & rGIF, sal_uInt8 nLZWDataSize ) :
75 rStream(rGIF), nBlockBufSize(0), nBitsBuf(0), nBitsBufSize(0)
77 rStream.WriteUChar( nLZWDataSize );
81 GIFImageDataOutputStream::~GIFImageDataOutputStream()
83 WriteBits(0,7);
84 FlushBitsBufsFullBytes();
85 FlushBlockBuf();
86 rStream.WriteUChar( 0 );
90 void GIFImageDataOutputStream::FlushBlockBuf()
92 if( nBlockBufSize )
94 rStream.WriteUChar( nBlockBufSize );
95 rStream.WriteBytes(pBlockBuf.data(), nBlockBufSize);
96 nBlockBufSize = 0;
101 struct GIFLZWCTreeNode
104 GIFLZWCTreeNode* pBrother; // next node which has the same father
105 GIFLZWCTreeNode* pFirstChild; // first
106 sal_uInt16 nCode; // the code for the string of pixel values which comes about
107 sal_uInt16 nValue; // the pixel value
111 GIFLZWCompressor::GIFLZWCompressor()
112 : pPrefix(nullptr), nDataSize(0), nClearCode(0),
113 nEOICode(0), nTableSize(0), nCodeSize(0)
118 GIFLZWCompressor::~GIFLZWCompressor()
120 if (pIDOS!=nullptr) EndCompression();
124 void GIFLZWCompressor::StartCompression( SvStream& rGIF, sal_uInt16 nPixelSize )
126 if( pIDOS )
127 return;
129 sal_uInt16 i;
131 nDataSize = nPixelSize;
133 if( nDataSize < 2 )
134 nDataSize=2;
136 nClearCode=1<<nDataSize;
137 nEOICode=nClearCode+1;
138 nTableSize=nEOICode+1;
139 nCodeSize=nDataSize+1;
141 pIDOS.reset(new GIFImageDataOutputStream(rGIF,static_cast<sal_uInt8>(nDataSize)));
142 pTable.reset(new GIFLZWCTreeNode[4096]);
144 for (i=0; i<4096; i++)
146 pTable[i].pBrother = pTable[i].pFirstChild = nullptr;
147 pTable[i].nCode = i;
148 pTable[i].nValue = static_cast<sal_uInt8>( i );
151 pPrefix = nullptr;
152 pIDOS->WriteBits( nClearCode,nCodeSize );
155 void GIFLZWCompressor::Compress(sal_uInt8* pSrc, sal_uInt32 nSize)
157 if( !pIDOS )
158 return;
160 GIFLZWCTreeNode* p;
161 sal_uInt16 i;
162 sal_uInt8 nV;
164 if( !pPrefix && nSize )
166 pPrefix=&pTable[*pSrc++];
167 nSize--;
170 while( nSize )
172 nSize--;
173 nV=*pSrc++;
174 for( p=pPrefix->pFirstChild; p!=nullptr; p=p->pBrother )
176 if (p->nValue==nV)
177 break;
180 if( p)
181 pPrefix=p;
182 else
184 pIDOS->WriteBits(pPrefix->nCode,nCodeSize);
186 if (nTableSize==4096)
188 pIDOS->WriteBits(nClearCode,nCodeSize);
190 for (i=0; i<nClearCode; i++)
191 pTable[i].pFirstChild=nullptr;
193 nCodeSize=nDataSize+1;
194 nTableSize=nEOICode+1;
196 else
198 if(nTableSize==static_cast<sal_uInt16>(1<<nCodeSize))
199 nCodeSize++;
201 p=&pTable[nTableSize++];
202 p->pBrother=pPrefix->pFirstChild;
203 pPrefix->pFirstChild=p;
204 p->nValue=nV;
205 p->pFirstChild=nullptr;
208 pPrefix=&pTable[nV];
213 void GIFLZWCompressor::EndCompression()
215 if( pIDOS )
217 if( pPrefix )
218 pIDOS->WriteBits(pPrefix->nCode,nCodeSize);
220 pIDOS->WriteBits( nEOICode,nCodeSize );
221 pTable.reset();
222 pIDOS.reset();
226 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */