15900e8ecSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
35900e8ecSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
45900e8ecSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
55900e8ecSAndrew Rist  * distributed with this work for additional information
65900e8ecSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
75900e8ecSAndrew Rist  * to you under the Apache License, Version 2.0 (the
85900e8ecSAndrew Rist  * "License"); you may not use this file except in compliance
95900e8ecSAndrew Rist  * with the License.  You may obtain a copy of the License at
105900e8ecSAndrew Rist  *
115900e8ecSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
125900e8ecSAndrew Rist  *
135900e8ecSAndrew Rist  * Unless required by applicable law or agreed to in writing,
145900e8ecSAndrew Rist  * software distributed under the License is distributed on an
155900e8ecSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
165900e8ecSAndrew Rist  * KIND, either express or implied.  See the License for the
175900e8ecSAndrew Rist  * specific language governing permissions and limitations
185900e8ecSAndrew Rist  * under the License.
195900e8ecSAndrew Rist  *
205900e8ecSAndrew Rist  *************************************************************/
215900e8ecSAndrew Rist 
225900e8ecSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_svtools.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #define _GIFPRIVATE
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "decode.hxx"
30cdf0e10cSrcweir #include "gifread.hxx"
31cdf0e10cSrcweir 
32cdf0e10cSrcweir // -----------
33cdf0e10cSrcweir // - Defines -
34cdf0e10cSrcweir // -----------
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #define NO_PENDING( rStm ) ( ( rStm ).GetError() != ERRCODE_IO_PENDING )
37cdf0e10cSrcweir 
38cdf0e10cSrcweir // -------------
39cdf0e10cSrcweir // - GIFReader -
40cdf0e10cSrcweir // -------------
41cdf0e10cSrcweir 
GIFReader(SvStream & rStm)42cdf0e10cSrcweir GIFReader::GIFReader( SvStream& rStm ) :
43cdf0e10cSrcweir 			aGPalette		( 256 ),
44cdf0e10cSrcweir 			aLPalette		( 256 ),
45cdf0e10cSrcweir 			rIStm			( rStm ),
46cdf0e10cSrcweir 			pAcc8			( NULL ),
47cdf0e10cSrcweir 			pAcc1			( NULL ),
48cdf0e10cSrcweir 			nLastPos		( rStm.Tell() ),
49cdf0e10cSrcweir 			nLogWidth100	( 0UL ),
50cdf0e10cSrcweir 			nLogHeight100	( 0UL ),
51cdf0e10cSrcweir 			nLoops			( 1 ),
52cdf0e10cSrcweir 			eActAction		( GLOBAL_HEADER_READING ),
53cdf0e10cSrcweir 			bGCTransparent	( sal_False ),
54cdf0e10cSrcweir 			bImGraphicReady	( sal_False )
55cdf0e10cSrcweir {
56cdf0e10cSrcweir 	maUpperName = UniString::CreateFromAscii( "SVIGIF", 6 );
57cdf0e10cSrcweir 	pSrcBuf = new sal_uInt8[ 256 ];
58cdf0e10cSrcweir 	ClearImageExtensions();
59cdf0e10cSrcweir }
60cdf0e10cSrcweir 
61cdf0e10cSrcweir // ------------------------------------------------------------------------
62cdf0e10cSrcweir 
~GIFReader()63cdf0e10cSrcweir GIFReader::~GIFReader()
64cdf0e10cSrcweir {
65cdf0e10cSrcweir 	aImGraphic.SetContext( NULL );
66cdf0e10cSrcweir 
67cdf0e10cSrcweir 	if( pAcc1 )
68cdf0e10cSrcweir 		aBmp1.ReleaseAccess( pAcc1 );
69cdf0e10cSrcweir 
70cdf0e10cSrcweir 	if( pAcc8 )
71cdf0e10cSrcweir 		aBmp8.ReleaseAccess( pAcc8 );
72cdf0e10cSrcweir 
73cdf0e10cSrcweir 	delete[] pSrcBuf;
74cdf0e10cSrcweir }
75cdf0e10cSrcweir 
76cdf0e10cSrcweir // ------------------------------------------------------------------------
77cdf0e10cSrcweir 
ClearImageExtensions()78cdf0e10cSrcweir void GIFReader::ClearImageExtensions()
79cdf0e10cSrcweir {
80cdf0e10cSrcweir 	nGCDisposalMethod = 0;
81cdf0e10cSrcweir 	bGCTransparent = sal_False;
82cdf0e10cSrcweir 	nTimer = 0;
83cdf0e10cSrcweir }
84cdf0e10cSrcweir 
85cdf0e10cSrcweir // ------------------------------------------------------------------------
86cdf0e10cSrcweir 
CreateBitmaps(long nWidth,long nHeight,BitmapPalette * pPal,sal_Bool bWatchForBackgroundColor)87cdf0e10cSrcweir sal_Bool GIFReader::CreateBitmaps( long nWidth, long nHeight, BitmapPalette* pPal,
88cdf0e10cSrcweir 							   sal_Bool bWatchForBackgroundColor )
89cdf0e10cSrcweir {
90cdf0e10cSrcweir 	const Size aSize( nWidth, nHeight );
91cdf0e10cSrcweir 
92cdf0e10cSrcweir 	if( bGCTransparent )
93cdf0e10cSrcweir 	{
94cdf0e10cSrcweir 		const Color aWhite( COL_WHITE );
95cdf0e10cSrcweir 
96cdf0e10cSrcweir 		aBmp1 = Bitmap( aSize, 1 );
97cdf0e10cSrcweir 
98cdf0e10cSrcweir 		if( !aAnimation.Count() )
99cdf0e10cSrcweir 			aBmp1.Erase( aWhite );
100cdf0e10cSrcweir 
101cdf0e10cSrcweir 		pAcc1 = aBmp1.AcquireWriteAccess();
102cdf0e10cSrcweir 
103cdf0e10cSrcweir 		if( pAcc1 )
104cdf0e10cSrcweir 		{
105cdf0e10cSrcweir 			cTransIndex1 = (sal_uInt8) pAcc1->GetBestPaletteIndex( aWhite );
106cdf0e10cSrcweir 			cNonTransIndex1 = cTransIndex1 ? 0 : 1;
107cdf0e10cSrcweir 		}
108cdf0e10cSrcweir 		else
109cdf0e10cSrcweir 			bStatus = sal_False;
110cdf0e10cSrcweir 	}
111cdf0e10cSrcweir 
112cdf0e10cSrcweir 	if( bStatus )
113cdf0e10cSrcweir 	{
114cdf0e10cSrcweir 		aBmp8 = Bitmap( aSize, 8, pPal );
115cdf0e10cSrcweir 
116cdf0e10cSrcweir 		if( !!aBmp8 && bWatchForBackgroundColor && aAnimation.Count() )
117cdf0e10cSrcweir 			aBmp8.Erase( (*pPal)[ nBackgroundColor ] );
118cdf0e10cSrcweir 		else
119cdf0e10cSrcweir 		  aBmp8.Erase( Color( COL_WHITE ) );
120cdf0e10cSrcweir 
121cdf0e10cSrcweir 		pAcc8 = aBmp8.AcquireWriteAccess();
122cdf0e10cSrcweir 		bStatus = ( pAcc8 != NULL );
123cdf0e10cSrcweir 	}
124cdf0e10cSrcweir 
125cdf0e10cSrcweir 	return bStatus;
126cdf0e10cSrcweir }
127cdf0e10cSrcweir 
128cdf0e10cSrcweir // ------------------------------------------------------------------------
129cdf0e10cSrcweir 
ReadGlobalHeader()130cdf0e10cSrcweir sal_Bool GIFReader::ReadGlobalHeader()
131cdf0e10cSrcweir {
132cdf0e10cSrcweir 	char	pBuf[ 7 ];
133cdf0e10cSrcweir 	sal_uInt8	nRF;
134cdf0e10cSrcweir 	sal_uInt8	nAspect;
135cdf0e10cSrcweir 	sal_Bool	bRet = sal_False;
136cdf0e10cSrcweir 
137cdf0e10cSrcweir 	rIStm.Read( pBuf, 6 );
138cdf0e10cSrcweir 	if( NO_PENDING( rIStm ) )
139cdf0e10cSrcweir 	{
140cdf0e10cSrcweir 		pBuf[ 6 ] = 0;
141cdf0e10cSrcweir 		if( !strcmp( pBuf, "GIF87a" ) || !strcmp( pBuf, "GIF89a" ) )
142cdf0e10cSrcweir 		{
143cdf0e10cSrcweir 			rIStm.Read( pBuf, 7 );
144cdf0e10cSrcweir 			if( NO_PENDING( rIStm ) )
145cdf0e10cSrcweir 			{
146cdf0e10cSrcweir 				SvMemoryStream aMemStm;
147cdf0e10cSrcweir 
148cdf0e10cSrcweir 				aMemStm.SetBuffer( pBuf, 7, sal_False, 7 );
149cdf0e10cSrcweir 				aMemStm >> nGlobalWidth;
150cdf0e10cSrcweir 				aMemStm >> nGlobalHeight;
151cdf0e10cSrcweir 				aMemStm >> nRF;
152cdf0e10cSrcweir 				aMemStm >> nBackgroundColor;
153cdf0e10cSrcweir 				aMemStm >> nAspect;
154cdf0e10cSrcweir 
155cdf0e10cSrcweir 				bGlobalPalette = (sal_Bool) ( nRF & 0x80 );
156cdf0e10cSrcweir 
157cdf0e10cSrcweir 				if( bGlobalPalette )
158cdf0e10cSrcweir 					ReadPaletteEntries( &aGPalette, 1 << ( ( nRF & 7 ) + 1 ) );
159cdf0e10cSrcweir 				else
160cdf0e10cSrcweir 					nBackgroundColor = 0;
161cdf0e10cSrcweir 
162cdf0e10cSrcweir 				if( NO_PENDING( rIStm ) )
163cdf0e10cSrcweir 					bRet = sal_True;
164cdf0e10cSrcweir 			}
165cdf0e10cSrcweir 		}
166cdf0e10cSrcweir 		else
167cdf0e10cSrcweir 			bStatus = sal_False;
168cdf0e10cSrcweir 	}
169cdf0e10cSrcweir 
170cdf0e10cSrcweir 	return bRet;
171cdf0e10cSrcweir }
172cdf0e10cSrcweir 
173cdf0e10cSrcweir // ------------------------------------------------------------------------
174cdf0e10cSrcweir 
ReadPaletteEntries(BitmapPalette * pPal,sal_uLong nCount)175cdf0e10cSrcweir void GIFReader::ReadPaletteEntries( BitmapPalette* pPal, sal_uLong nCount )
176cdf0e10cSrcweir {
177cdf0e10cSrcweir 	const sal_uLong	nLen = 3UL * nCount;
178cdf0e10cSrcweir 	sal_uInt8*		pBuf = new sal_uInt8[ nLen ];
179cdf0e10cSrcweir 
180cdf0e10cSrcweir 	rIStm.Read( pBuf, nLen );
181cdf0e10cSrcweir 	if( NO_PENDING( rIStm ) )
182cdf0e10cSrcweir 	{
183cdf0e10cSrcweir 		sal_uInt8* pTmp = pBuf;
184cdf0e10cSrcweir 
185cdf0e10cSrcweir 		for( sal_uLong i = 0UL; i < nCount; )
186cdf0e10cSrcweir 		{
187cdf0e10cSrcweir 			BitmapColor& rColor = (*pPal)[ (sal_uInt16) i++ ];
188cdf0e10cSrcweir 
189cdf0e10cSrcweir 			rColor.SetRed( *pTmp++ );
190cdf0e10cSrcweir 			rColor.SetGreen( *pTmp++ );
191cdf0e10cSrcweir 			rColor.SetBlue( *pTmp++ );
192cdf0e10cSrcweir 		}
193cdf0e10cSrcweir 
194cdf0e10cSrcweir 		// nach Moeglichkeit noch einige Standardfarben unterbringen
195cdf0e10cSrcweir 		if( nCount < 256UL )
196cdf0e10cSrcweir 		{
197cdf0e10cSrcweir 			(*pPal)[ 255UL ] = Color( COL_WHITE );
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 			if( nCount < 255UL )
200cdf0e10cSrcweir 				(*pPal)[ 254UL ] = Color( COL_BLACK );
201cdf0e10cSrcweir 		}
202cdf0e10cSrcweir 	}
203cdf0e10cSrcweir 
204cdf0e10cSrcweir 	delete[] pBuf;
205cdf0e10cSrcweir }
206cdf0e10cSrcweir 
207cdf0e10cSrcweir // ------------------------------------------------------------------------
208cdf0e10cSrcweir 
ReadExtension()209cdf0e10cSrcweir sal_Bool GIFReader::ReadExtension()
210cdf0e10cSrcweir {
211cdf0e10cSrcweir 	sal_uInt8	cFunction;
212cdf0e10cSrcweir 	sal_uInt8	cSize;
213cdf0e10cSrcweir 	sal_uInt8	cByte;
214cdf0e10cSrcweir 	sal_Bool	bRet = sal_False;
215cdf0e10cSrcweir 	sal_Bool	bOverreadDataBlocks = sal_False;
216cdf0e10cSrcweir 
217cdf0e10cSrcweir 	// Extension-Label
218cdf0e10cSrcweir 	rIStm >> cFunction;
219cdf0e10cSrcweir 	if( NO_PENDING( rIStm ) )
220cdf0e10cSrcweir 	{
221cdf0e10cSrcweir 		// Block-Laenge
222cdf0e10cSrcweir 		rIStm >> cSize;
223cdf0e10cSrcweir 
224cdf0e10cSrcweir 		switch( cFunction )
225cdf0e10cSrcweir 		{
226cdf0e10cSrcweir 			// 'Graphic Control Extension'
227cdf0e10cSrcweir 			case( 0xf9 ) :
228cdf0e10cSrcweir 			{
229cdf0e10cSrcweir 				sal_uInt8 cFlags;
230cdf0e10cSrcweir 
231cdf0e10cSrcweir 				rIStm >> cFlags;
232cdf0e10cSrcweir 				rIStm >> nTimer;
233cdf0e10cSrcweir 				rIStm >> nGCTransparentIndex;
234cdf0e10cSrcweir 				rIStm >> cByte;
235cdf0e10cSrcweir 
236cdf0e10cSrcweir 				if ( NO_PENDING( rIStm ) )
237cdf0e10cSrcweir 				{
238cdf0e10cSrcweir 					nGCDisposalMethod = ( cFlags >> 2) & 7;
239cdf0e10cSrcweir 					bGCTransparent = ( cFlags & 1 ) ? sal_True : sal_False;
240cdf0e10cSrcweir 					bStatus = ( cSize == 4 ) && ( cByte == 0 );
241cdf0e10cSrcweir 					bRet = sal_True;
242cdf0e10cSrcweir 				}
243cdf0e10cSrcweir 			}
244cdf0e10cSrcweir 			break;
245cdf0e10cSrcweir 
246cdf0e10cSrcweir 			// Application-Extension
247cdf0e10cSrcweir 			case ( 0xff ) :
248cdf0e10cSrcweir 			{
249cdf0e10cSrcweir 				if ( NO_PENDING( rIStm ) )
250cdf0e10cSrcweir 				{
251cdf0e10cSrcweir 					// default diese Extension ueberlesen
252cdf0e10cSrcweir 					bOverreadDataBlocks = sal_True;
253cdf0e10cSrcweir 
254cdf0e10cSrcweir 					// Appl.-Extension hat Laenge 11
255cdf0e10cSrcweir 					if ( cSize == 0x0b )
256cdf0e10cSrcweir 					{
257cdf0e10cSrcweir 						ByteString	aAppId;
258cdf0e10cSrcweir 						ByteString	aAppCode;
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 						rIStm.Read( aAppId.AllocBuffer( 8 ), 8 );
261cdf0e10cSrcweir 						rIStm.Read( aAppCode.AllocBuffer( 3 ), 3 );
262cdf0e10cSrcweir 						rIStm >> cSize;
263cdf0e10cSrcweir 
264cdf0e10cSrcweir 						// NetScape-Extension
265cdf0e10cSrcweir 						if( aAppId == "NETSCAPE" && aAppCode == "2.0" && cSize == 3 )
266cdf0e10cSrcweir 						{
267cdf0e10cSrcweir 							rIStm >> cByte;
268cdf0e10cSrcweir 
269cdf0e10cSrcweir 							// Loop-Extension
270cdf0e10cSrcweir 							if ( cByte == 0x01 )
271cdf0e10cSrcweir 							{
272cdf0e10cSrcweir 								rIStm >> cByte;
273cdf0e10cSrcweir 								nLoops = cByte;
274cdf0e10cSrcweir 								rIStm >> cByte;
275cdf0e10cSrcweir 								nLoops |= ( (sal_uInt16) cByte << 8 );
276cdf0e10cSrcweir 								rIStm >> cByte;
277cdf0e10cSrcweir 
278cdf0e10cSrcweir 								bStatus = ( cByte == 0 );
279cdf0e10cSrcweir 								bRet = NO_PENDING( rIStm );
280cdf0e10cSrcweir 								bOverreadDataBlocks = sal_False;
281cdf0e10cSrcweir 
282cdf0e10cSrcweir 								// Netscape interpretiert den LoopCount
283cdf0e10cSrcweir 								// als reine Anzahl der _Wiederholungen_;
284cdf0e10cSrcweir 								// bei uns ist es die Gesamtanzahl der
285cdf0e10cSrcweir 								// Durchlaeufe
286cdf0e10cSrcweir 								if( nLoops )
287cdf0e10cSrcweir 									nLoops++;
288cdf0e10cSrcweir 							}
289cdf0e10cSrcweir 							else
290cdf0e10cSrcweir 								rIStm.SeekRel( -1 );
291cdf0e10cSrcweir 						}
292cdf0e10cSrcweir 						else if ( aAppId == "STARDIV " && aAppCode == "5.0" && cSize == 9 )
293cdf0e10cSrcweir 						{
294cdf0e10cSrcweir 							rIStm >> cByte;
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 							// Loop-Extension
297cdf0e10cSrcweir 							if ( cByte == 0x01 )
298cdf0e10cSrcweir 							{
299cdf0e10cSrcweir 								rIStm >> nLogWidth100 >> nLogHeight100;
300cdf0e10cSrcweir 								rIStm >> cByte;
301cdf0e10cSrcweir 								bStatus = ( cByte == 0 );
302cdf0e10cSrcweir 								bRet = NO_PENDING( rIStm );
303cdf0e10cSrcweir 								bOverreadDataBlocks = sal_False;
304cdf0e10cSrcweir 							}
305cdf0e10cSrcweir 							else
306cdf0e10cSrcweir 								rIStm.SeekRel( -1 );
307cdf0e10cSrcweir 						}
308cdf0e10cSrcweir 
309cdf0e10cSrcweir 					}
310cdf0e10cSrcweir 				}
311cdf0e10cSrcweir 			}
312cdf0e10cSrcweir 			break;
313cdf0e10cSrcweir 
314cdf0e10cSrcweir 			// alles andere ueberlesen
315cdf0e10cSrcweir 			default:
316cdf0e10cSrcweir 				bOverreadDataBlocks = sal_True;
317cdf0e10cSrcweir 			break;
318cdf0e10cSrcweir 		}
319cdf0e10cSrcweir 
320cdf0e10cSrcweir 		// Sub-Blocks ueberlesen
321cdf0e10cSrcweir 		if ( bOverreadDataBlocks )
322cdf0e10cSrcweir 		{
323cdf0e10cSrcweir 			bRet = sal_True;
324cdf0e10cSrcweir 			while( cSize && bStatus && !rIStm.IsEof() )
325cdf0e10cSrcweir 			{
326cdf0e10cSrcweir 				sal_uInt16	nCount = (sal_uInt16) cSize + 1;
327cdf0e10cSrcweir 				char*	pBuffer = new char[ nCount ];
328cdf0e10cSrcweir 
329cdf0e10cSrcweir 				bRet = sal_False;
330cdf0e10cSrcweir 				rIStm.Read( pBuffer, nCount );
331cdf0e10cSrcweir 				if( NO_PENDING( rIStm ) )
332cdf0e10cSrcweir 				{
333cdf0e10cSrcweir 					cSize = (sal_uInt8) pBuffer[ cSize ];
334cdf0e10cSrcweir 					bRet = sal_True;
335cdf0e10cSrcweir 				}
336cdf0e10cSrcweir 				else
337cdf0e10cSrcweir 					cSize = 0;
338cdf0e10cSrcweir 
339cdf0e10cSrcweir 				delete[] pBuffer;
340cdf0e10cSrcweir 			}
341cdf0e10cSrcweir 		}
342cdf0e10cSrcweir 	}
343cdf0e10cSrcweir 
344cdf0e10cSrcweir 	return bRet;
345cdf0e10cSrcweir }
346cdf0e10cSrcweir 
347cdf0e10cSrcweir // ------------------------------------------------------------------------
348cdf0e10cSrcweir 
ReadLocalHeader()349cdf0e10cSrcweir sal_Bool GIFReader::ReadLocalHeader()
350cdf0e10cSrcweir {
351cdf0e10cSrcweir 	sal_uInt8	pBuf[ 9 ];
352cdf0e10cSrcweir 	sal_Bool	bRet = sal_False;
353cdf0e10cSrcweir 
354cdf0e10cSrcweir 	rIStm.Read( pBuf, 9 );
355cdf0e10cSrcweir 	if( NO_PENDING( rIStm ) )
356cdf0e10cSrcweir 	{
357cdf0e10cSrcweir 		SvMemoryStream	aMemStm;
358cdf0e10cSrcweir 		BitmapPalette*	pPal;
359cdf0e10cSrcweir 		sal_uInt8			nFlags;
360cdf0e10cSrcweir 
361cdf0e10cSrcweir 		aMemStm.SetBuffer( (char*) pBuf, 9, sal_False, 9 );
362cdf0e10cSrcweir 		aMemStm >> nImagePosX;
363cdf0e10cSrcweir 		aMemStm >> nImagePosY;
364cdf0e10cSrcweir 		aMemStm >> nImageWidth;
365cdf0e10cSrcweir 		aMemStm >> nImageHeight;
366cdf0e10cSrcweir 		aMemStm >> nFlags;
367cdf0e10cSrcweir 
368cdf0e10cSrcweir 		// Falls Interlaced, ersten Startwert vorgeben
369cdf0e10cSrcweir 		bInterlaced = ( ( nFlags & 0x40 ) == 0x40 );
370cdf0e10cSrcweir 		nLastInterCount = 7;
371cdf0e10cSrcweir 		nLastImageY = 0;
372cdf0e10cSrcweir 
373cdf0e10cSrcweir 		if( nFlags & 0x80 )
374cdf0e10cSrcweir 		{
375cdf0e10cSrcweir 			pPal = &aLPalette;
376cdf0e10cSrcweir 			ReadPaletteEntries( pPal, 1 << ( (nFlags & 7 ) + 1 ) );
377cdf0e10cSrcweir 		}
378cdf0e10cSrcweir 		else
379cdf0e10cSrcweir 			pPal = &aGPalette;
380cdf0e10cSrcweir 
381cdf0e10cSrcweir 		// Falls alles soweit eingelesen werden konnte, kann
382cdf0e10cSrcweir 		// nun das lokale Bild angelegt werden;
383cdf0e10cSrcweir 		// es wird uebergeben, ob der BackgroundColorIndex evtl.
384cdf0e10cSrcweir 		// beruecksichtigt werden soll ( wenn Globale Farbtab. und
385cdf0e10cSrcweir 		// diese auch fuer dieses Bild gilt )
386cdf0e10cSrcweir 		if( NO_PENDING( rIStm ) )
387cdf0e10cSrcweir 		{
388cdf0e10cSrcweir 			CreateBitmaps( nImageWidth, nImageHeight, pPal, bGlobalPalette && ( pPal == &aGPalette ) );
389cdf0e10cSrcweir 			bRet = sal_True;
390cdf0e10cSrcweir 		}
391cdf0e10cSrcweir 	}
392cdf0e10cSrcweir 
393cdf0e10cSrcweir 	return bRet;
394cdf0e10cSrcweir }
395cdf0e10cSrcweir 
396cdf0e10cSrcweir // ------------------------------------------------------------------------
397cdf0e10cSrcweir 
ReadNextBlock()398cdf0e10cSrcweir sal_uLong GIFReader::ReadNextBlock()
399cdf0e10cSrcweir {
400cdf0e10cSrcweir 	sal_uLong	nRet = 0UL;
401cdf0e10cSrcweir 	sal_uLong	nRead;
402cdf0e10cSrcweir 	sal_uInt8	cBlockSize;
403cdf0e10cSrcweir 
404cdf0e10cSrcweir 	rIStm >> cBlockSize;
405cdf0e10cSrcweir 
406cdf0e10cSrcweir 	if ( rIStm.IsEof() )
407cdf0e10cSrcweir 		nRet = 4UL;
408cdf0e10cSrcweir 	else if ( NO_PENDING( rIStm ) )
409cdf0e10cSrcweir 	{
410cdf0e10cSrcweir 		if ( cBlockSize == 0 )
411cdf0e10cSrcweir 			nRet = 2UL;
412cdf0e10cSrcweir 		else
413cdf0e10cSrcweir 		{
414cdf0e10cSrcweir 			rIStm.Read( pSrcBuf, cBlockSize );
415cdf0e10cSrcweir 
416cdf0e10cSrcweir 			if( NO_PENDING( rIStm ) )
417cdf0e10cSrcweir 			{
418cdf0e10cSrcweir 				if( bOverreadBlock )
419cdf0e10cSrcweir 					nRet = 3UL;
420cdf0e10cSrcweir 				else
421cdf0e10cSrcweir 				{
422cdf0e10cSrcweir 					sal_Bool	bEOI;
423cdf0e10cSrcweir 					HPBYTE	pTarget = pDecomp->DecompressBlock( pSrcBuf, cBlockSize, nRead, bEOI );
424cdf0e10cSrcweir 
425cdf0e10cSrcweir 					nRet = ( bEOI ? 3 : 1 );
426cdf0e10cSrcweir 
427cdf0e10cSrcweir 					if( nRead && !bOverreadBlock )
428cdf0e10cSrcweir 						FillImages( pTarget, nRead );
429cdf0e10cSrcweir 
430cdf0e10cSrcweir 					rtl_freeMemory( pTarget );
431cdf0e10cSrcweir 				}
432cdf0e10cSrcweir 			}
433cdf0e10cSrcweir 		}
434cdf0e10cSrcweir 	}
435cdf0e10cSrcweir 
436cdf0e10cSrcweir 	return nRet;
437cdf0e10cSrcweir }
438cdf0e10cSrcweir 
439cdf0e10cSrcweir // ------------------------------------------------------------------------
440cdf0e10cSrcweir 
FillImages(HPBYTE pBytes,sal_uLong nCount)441cdf0e10cSrcweir void GIFReader::FillImages( HPBYTE pBytes, sal_uLong nCount )
442cdf0e10cSrcweir {
443cdf0e10cSrcweir 	for( sal_uLong i = 0UL; i < nCount; i++ )
444cdf0e10cSrcweir 	{
445cdf0e10cSrcweir 		if( nImageX >= nImageWidth )
446cdf0e10cSrcweir 		{
447cdf0e10cSrcweir 			if( bInterlaced )
448cdf0e10cSrcweir 			{
449cdf0e10cSrcweir 				long nT1, nT2;
450cdf0e10cSrcweir 
451cdf0e10cSrcweir 				// falls Interlaced, werden die Zeilen kopiert
452cdf0e10cSrcweir 				if( nLastInterCount )
453cdf0e10cSrcweir 				{
454cdf0e10cSrcweir 					long nMinY = Min( (long) nLastImageY + 1, (long) nImageHeight - 1 );
455cdf0e10cSrcweir 					long nMaxY = Min( (long) nLastImageY + nLastInterCount, (long) nImageHeight - 1 );
456cdf0e10cSrcweir 
457cdf0e10cSrcweir 					// letzte gelesene Zeile kopieren, wenn Zeilen
458cdf0e10cSrcweir 					// nicht zusanmmenfallen ( kommt vorm wenn wir am Ende des Bildes sind )
459cdf0e10cSrcweir 					if( ( nMinY > nLastImageY ) && ( nLastImageY < ( nImageHeight - 1 ) ) )
460cdf0e10cSrcweir 					{
461cdf0e10cSrcweir 						HPBYTE	pScanline8 = pAcc8->GetScanline( nYAcc );
462cdf0e10cSrcweir 						sal_uLong	nSize8 = pAcc8->GetScanlineSize();
463cdf0e10cSrcweir 						HPBYTE	pScanline1 = 0;
464cdf0e10cSrcweir 						sal_uLong	nSize1 = 0;
465cdf0e10cSrcweir 
466cdf0e10cSrcweir 						if( bGCTransparent )
467cdf0e10cSrcweir 						{
468cdf0e10cSrcweir 							pScanline1 = pAcc1->GetScanline( nYAcc );
469cdf0e10cSrcweir 							nSize1 = pAcc1->GetScanlineSize();
470cdf0e10cSrcweir 						}
471cdf0e10cSrcweir 
472cdf0e10cSrcweir 						for( long j = nMinY; j <= nMaxY; j++ )
473cdf0e10cSrcweir 						{
474cdf0e10cSrcweir 							memcpy( pAcc8->GetScanline( j ), pScanline8, nSize8 );
475cdf0e10cSrcweir 
476cdf0e10cSrcweir 							if( bGCTransparent )
477cdf0e10cSrcweir 								memcpy( pAcc1->GetScanline( j ), pScanline1, nSize1 );
478cdf0e10cSrcweir 						}
479cdf0e10cSrcweir 					}
480cdf0e10cSrcweir 				}
481cdf0e10cSrcweir 
482cdf0e10cSrcweir 				nT1 = ( ++nImageY ) << 3;
483cdf0e10cSrcweir 				nLastInterCount = 7;
484cdf0e10cSrcweir 
485cdf0e10cSrcweir 				if( nT1 >= nImageHeight )
486cdf0e10cSrcweir 				{
487cdf0e10cSrcweir 					nT2 = nImageY - ( ( nImageHeight + 7 ) >> 3 );
488cdf0e10cSrcweir 					nT1 = ( nT2 << 3 ) + 4;
489cdf0e10cSrcweir 					nLastInterCount = 3;
490cdf0e10cSrcweir 
491cdf0e10cSrcweir 					if( nT1 >= nImageHeight )
492cdf0e10cSrcweir 					{
493cdf0e10cSrcweir 						nT2 -= ( nImageHeight + 3 ) >> 3;
494cdf0e10cSrcweir 						nT1 = ( nT2 << 2 ) + 2;
495cdf0e10cSrcweir 						nLastInterCount = 1;
496cdf0e10cSrcweir 
497cdf0e10cSrcweir 						if( nT1 >= nImageHeight )
498cdf0e10cSrcweir 						{
499cdf0e10cSrcweir 							nT2 -= ( nImageHeight + 1 ) >> 2;
500cdf0e10cSrcweir 							nT1 = ( nT2 << 1 ) + 1;
501cdf0e10cSrcweir 							nLastInterCount = 0;
502cdf0e10cSrcweir 						}
503cdf0e10cSrcweir 					}
504cdf0e10cSrcweir 				}
505cdf0e10cSrcweir 
506cdf0e10cSrcweir 				nLastImageY = (sal_uInt16) nT1;
507cdf0e10cSrcweir 				nYAcc = nT1;
508cdf0e10cSrcweir 			}
509cdf0e10cSrcweir 			else
510cdf0e10cSrcweir 			{
511cdf0e10cSrcweir 				nLastImageY = ++nImageY;
512cdf0e10cSrcweir 				nYAcc = nImageY;
513cdf0e10cSrcweir 			}
514cdf0e10cSrcweir 
515cdf0e10cSrcweir 			// Zeile faengt von vorne an
516cdf0e10cSrcweir 			nImageX = 0;
517cdf0e10cSrcweir 		}
518cdf0e10cSrcweir 
519cdf0e10cSrcweir 		if( nImageY < nImageHeight )
520cdf0e10cSrcweir 		{
521cdf0e10cSrcweir 			const sal_uInt8 cTmp = pBytes[ i ];
522cdf0e10cSrcweir 
523cdf0e10cSrcweir 			if( bGCTransparent )
524cdf0e10cSrcweir 			{
525cdf0e10cSrcweir 				if( cTmp == nGCTransparentIndex )
526*87bc88d3SHerbert Dürr 					pAcc1->SetPixelIndex( nYAcc, nImageX++, cTransIndex1 );
527cdf0e10cSrcweir 				else
528cdf0e10cSrcweir 				{
529*87bc88d3SHerbert Dürr 					pAcc8->SetPixelIndex( nYAcc, nImageX, cTmp );
530*87bc88d3SHerbert Dürr 					pAcc1->SetPixelIndex( nYAcc, nImageX++, cNonTransIndex1 );
531cdf0e10cSrcweir 				}
532cdf0e10cSrcweir 			}
533cdf0e10cSrcweir 			else
534*87bc88d3SHerbert Dürr 				pAcc8->SetPixelIndex( nYAcc, nImageX++, cTmp );
535cdf0e10cSrcweir 		}
536cdf0e10cSrcweir 		else
537cdf0e10cSrcweir 		{
538cdf0e10cSrcweir 			bOverreadBlock = sal_True;
539cdf0e10cSrcweir 			break;
540cdf0e10cSrcweir 		}
541cdf0e10cSrcweir 	}
542cdf0e10cSrcweir }
543cdf0e10cSrcweir 
544cdf0e10cSrcweir // ------------------------------------------------------------------------
545cdf0e10cSrcweir 
CreateNewBitmaps()546cdf0e10cSrcweir void GIFReader::CreateNewBitmaps()
547cdf0e10cSrcweir {
548cdf0e10cSrcweir 	AnimationBitmap	aAnimBmp;
549cdf0e10cSrcweir 
550cdf0e10cSrcweir 	aBmp8.ReleaseAccess( pAcc8 );
551cdf0e10cSrcweir 	pAcc8 = NULL;
552cdf0e10cSrcweir 
553cdf0e10cSrcweir 	if( bGCTransparent )
554cdf0e10cSrcweir 	{
555cdf0e10cSrcweir 		aBmp1.ReleaseAccess( pAcc1 );
556cdf0e10cSrcweir 		pAcc1 = NULL;
557cdf0e10cSrcweir 		aAnimBmp.aBmpEx = BitmapEx( aBmp8, aBmp1 );
558cdf0e10cSrcweir 	}
559cdf0e10cSrcweir 	else
560cdf0e10cSrcweir 		aAnimBmp.aBmpEx = BitmapEx( aBmp8 );
561cdf0e10cSrcweir 
562cdf0e10cSrcweir 	aAnimBmp.aPosPix = Point( nImagePosX, nImagePosY );
563cdf0e10cSrcweir 	aAnimBmp.aSizePix = Size( nImageWidth, nImageHeight );
564cdf0e10cSrcweir 	aAnimBmp.nWait = ( nTimer != 65535 ) ? nTimer : ANIMATION_TIMEOUT_ON_CLICK;
565cdf0e10cSrcweir 	aAnimBmp.bUserInput = sal_False;
566cdf0e10cSrcweir 
567cdf0e10cSrcweir 	if( nGCDisposalMethod == 2 )
568cdf0e10cSrcweir 		aAnimBmp.eDisposal = DISPOSE_BACK;
569cdf0e10cSrcweir 	else if( nGCDisposalMethod == 3 )
570cdf0e10cSrcweir 		aAnimBmp.eDisposal = DISPOSE_PREVIOUS;
571cdf0e10cSrcweir 	else
572cdf0e10cSrcweir 		aAnimBmp.eDisposal = DISPOSE_NOT;
573cdf0e10cSrcweir 
574cdf0e10cSrcweir 	aAnimation.Insert( aAnimBmp );
575cdf0e10cSrcweir 
576cdf0e10cSrcweir 	if( aAnimation.Count() == 1 )
577cdf0e10cSrcweir 	{
578cdf0e10cSrcweir 		aAnimation.SetDisplaySizePixel( Size( nGlobalWidth, nGlobalHeight ) );
579cdf0e10cSrcweir 		aAnimation.SetLoopCount( nLoops );
580cdf0e10cSrcweir 	}
581cdf0e10cSrcweir }
582cdf0e10cSrcweir 
583cdf0e10cSrcweir // ------------------------------------------------------------------------
584cdf0e10cSrcweir 
GetIntermediateGraphic()585cdf0e10cSrcweir const Graphic& GIFReader::GetIntermediateGraphic()
586cdf0e10cSrcweir {
587cdf0e10cSrcweir 	// Intermediate-Graphic nur erzeugen, wenn schon
588cdf0e10cSrcweir 	// Daten vorliegen, aber die Graphic noch nicht
589cdf0e10cSrcweir 	// vollstaendig eingelesen wurde
590cdf0e10cSrcweir 	if ( bImGraphicReady && !aAnimation.Count() )
591cdf0e10cSrcweir 	{
592cdf0e10cSrcweir 		Bitmap	aBmp;
593cdf0e10cSrcweir 
594cdf0e10cSrcweir 		aBmp8.ReleaseAccess( pAcc8 );
595cdf0e10cSrcweir 
596cdf0e10cSrcweir 		if ( bGCTransparent )
597cdf0e10cSrcweir 		{
598cdf0e10cSrcweir 			aBmp1.ReleaseAccess( pAcc1 );
599cdf0e10cSrcweir 			aImGraphic = BitmapEx( aBmp8, aBmp1 );
600cdf0e10cSrcweir 
601cdf0e10cSrcweir 			pAcc1 = aBmp1.AcquireWriteAccess();
602cdf0e10cSrcweir 			bStatus = bStatus && ( pAcc1 != NULL );
603cdf0e10cSrcweir 		}
604cdf0e10cSrcweir 		else
605cdf0e10cSrcweir 			aImGraphic = aBmp8;
606cdf0e10cSrcweir 
607cdf0e10cSrcweir 		pAcc8 = aBmp8.AcquireWriteAccess();
608cdf0e10cSrcweir 		bStatus = bStatus && ( pAcc8 != NULL );
609cdf0e10cSrcweir 	}
610cdf0e10cSrcweir 
611cdf0e10cSrcweir 	return aImGraphic;
612cdf0e10cSrcweir }
613cdf0e10cSrcweir 
614cdf0e10cSrcweir // ------------------------------------------------------------------------
615cdf0e10cSrcweir 
ProcessGIF()616cdf0e10cSrcweir sal_Bool GIFReader::ProcessGIF()
617cdf0e10cSrcweir {
618cdf0e10cSrcweir 	sal_Bool bRead = sal_False;
619cdf0e10cSrcweir 	sal_Bool bEnd = sal_False;
620cdf0e10cSrcweir 
621cdf0e10cSrcweir 	if ( !bStatus )
622cdf0e10cSrcweir 		eActAction = ABORT_READING;
623cdf0e10cSrcweir 
624cdf0e10cSrcweir 	// Stream an die richtige Stelle bringen
625cdf0e10cSrcweir 	rIStm.Seek( nLastPos );
626cdf0e10cSrcweir 
627cdf0e10cSrcweir 	switch( eActAction )
628cdf0e10cSrcweir 	{
629cdf0e10cSrcweir 		// naechsten Marker lesen
630cdf0e10cSrcweir 		case( MARKER_READING ):
631cdf0e10cSrcweir 		{
632cdf0e10cSrcweir 			sal_uInt8 cByte;
633cdf0e10cSrcweir 
634cdf0e10cSrcweir 			rIStm >> cByte;
635cdf0e10cSrcweir 
636cdf0e10cSrcweir 			if( rIStm.IsEof() )
637cdf0e10cSrcweir 				eActAction = END_READING;
638cdf0e10cSrcweir 			else if( NO_PENDING( rIStm ) )
639cdf0e10cSrcweir 			{
640cdf0e10cSrcweir 				bRead = sal_True;
641cdf0e10cSrcweir 
642cdf0e10cSrcweir 				if( cByte == '!' )
643cdf0e10cSrcweir 					eActAction = EXTENSION_READING;
644cdf0e10cSrcweir 				else if( cByte == ',' )
645cdf0e10cSrcweir 					eActAction = LOCAL_HEADER_READING;
646cdf0e10cSrcweir 				else if( cByte == ';' )
647cdf0e10cSrcweir 					eActAction = END_READING;
648cdf0e10cSrcweir 				else
649cdf0e10cSrcweir 					eActAction = ABORT_READING;
650cdf0e10cSrcweir 			}
651cdf0e10cSrcweir 		}
652cdf0e10cSrcweir 		break;
653cdf0e10cSrcweir 
654cdf0e10cSrcweir 		// ScreenDescriptor lesen
655cdf0e10cSrcweir 		case( GLOBAL_HEADER_READING ):
656cdf0e10cSrcweir 		{
657cdf0e10cSrcweir 			if( ( bRead = ReadGlobalHeader() ) == sal_True )
658cdf0e10cSrcweir 			{
659cdf0e10cSrcweir 				ClearImageExtensions();
660cdf0e10cSrcweir 				eActAction = MARKER_READING;
661cdf0e10cSrcweir 			}
662cdf0e10cSrcweir 		}
663cdf0e10cSrcweir 		break;
664cdf0e10cSrcweir 
665cdf0e10cSrcweir 
666cdf0e10cSrcweir 		// Extension lesen
667cdf0e10cSrcweir 		case( EXTENSION_READING ):
668cdf0e10cSrcweir 		{
669cdf0e10cSrcweir 			if( ( bRead = ReadExtension() ) == sal_True )
670cdf0e10cSrcweir 				eActAction = MARKER_READING;
671cdf0e10cSrcweir 		}
672cdf0e10cSrcweir 		break;
673cdf0e10cSrcweir 
674cdf0e10cSrcweir 
675cdf0e10cSrcweir 		// Image-Descriptor lesen
676cdf0e10cSrcweir 		case( LOCAL_HEADER_READING ):
677cdf0e10cSrcweir 		{
678cdf0e10cSrcweir 			if( ( bRead = ReadLocalHeader() ) == sal_True )
679cdf0e10cSrcweir 			{
680cdf0e10cSrcweir 				nYAcc = nImageX = nImageY = 0;
681cdf0e10cSrcweir 				eActAction = FIRST_BLOCK_READING;
682cdf0e10cSrcweir 			}
683cdf0e10cSrcweir 		}
684cdf0e10cSrcweir 		break;
685cdf0e10cSrcweir 
686cdf0e10cSrcweir 
687cdf0e10cSrcweir 		// ersten Datenblock lesen
688cdf0e10cSrcweir 		case( FIRST_BLOCK_READING ):
689cdf0e10cSrcweir 		{
690cdf0e10cSrcweir 			sal_uInt8 cDataSize;
691cdf0e10cSrcweir 
692cdf0e10cSrcweir 			rIStm >> cDataSize;
693cdf0e10cSrcweir 
694cdf0e10cSrcweir 			if( rIStm.IsEof() )
695cdf0e10cSrcweir 				eActAction = ABORT_READING;
696cdf0e10cSrcweir 			else if( cDataSize > 12 )
697cdf0e10cSrcweir 				bStatus = sal_False;
698cdf0e10cSrcweir 			else if( NO_PENDING( rIStm ) )
699cdf0e10cSrcweir 			{
700cdf0e10cSrcweir 				bRead = sal_True;
701cdf0e10cSrcweir 				pDecomp = new GIFLZWDecompressor( cDataSize );
702cdf0e10cSrcweir 				eActAction = NEXT_BLOCK_READING;
703cdf0e10cSrcweir 				bOverreadBlock = sal_False;
704cdf0e10cSrcweir 			}
705cdf0e10cSrcweir 			else
706cdf0e10cSrcweir 				eActAction = FIRST_BLOCK_READING;
707cdf0e10cSrcweir 		}
708cdf0e10cSrcweir 		break;
709cdf0e10cSrcweir 
710cdf0e10cSrcweir 		// naechsten Datenblock lesen
711cdf0e10cSrcweir 		case( NEXT_BLOCK_READING ):
712cdf0e10cSrcweir 		{
713cdf0e10cSrcweir 			sal_uInt16	nLastX = nImageX;
714cdf0e10cSrcweir 			sal_uInt16	nLastY = nImageY;
715cdf0e10cSrcweir 			sal_uLong	nRet = ReadNextBlock();
716cdf0e10cSrcweir 
717cdf0e10cSrcweir 			// Return: 0:Pending / 1:OK; / 2:OK und letzter Block: / 3:EOI / 4:HardAbort
718cdf0e10cSrcweir 			if( nRet )
719cdf0e10cSrcweir 			{
720cdf0e10cSrcweir 				bRead = sal_True;
721cdf0e10cSrcweir 
722cdf0e10cSrcweir 				if ( nRet == 1UL )
723cdf0e10cSrcweir 				{
724cdf0e10cSrcweir 					bImGraphicReady = sal_True;
725cdf0e10cSrcweir 					eActAction = NEXT_BLOCK_READING;
726cdf0e10cSrcweir 					bOverreadBlock = sal_False;
727cdf0e10cSrcweir 				}
728cdf0e10cSrcweir 				else
729cdf0e10cSrcweir 				{
730cdf0e10cSrcweir 					if( nRet == 2UL )
731cdf0e10cSrcweir 					{
732cdf0e10cSrcweir 						delete pDecomp;
733cdf0e10cSrcweir 						CreateNewBitmaps();
734cdf0e10cSrcweir 						eActAction = MARKER_READING;
735cdf0e10cSrcweir 						ClearImageExtensions();
736cdf0e10cSrcweir 					}
737cdf0e10cSrcweir 					else if( nRet == 3UL )
738cdf0e10cSrcweir 					{
739cdf0e10cSrcweir 						eActAction = NEXT_BLOCK_READING;
740cdf0e10cSrcweir 						bOverreadBlock = sal_True;
741cdf0e10cSrcweir 					}
742cdf0e10cSrcweir 					else
743cdf0e10cSrcweir 					{
744cdf0e10cSrcweir 						delete pDecomp;
745cdf0e10cSrcweir 						CreateNewBitmaps();
746cdf0e10cSrcweir 						eActAction = ABORT_READING;
747cdf0e10cSrcweir 						ClearImageExtensions();
748cdf0e10cSrcweir 					}
749cdf0e10cSrcweir 				}
750cdf0e10cSrcweir 			}
751cdf0e10cSrcweir 			else
752cdf0e10cSrcweir 			{
753cdf0e10cSrcweir 				nImageX = nLastX;
754cdf0e10cSrcweir 				nImageY = nLastY;
755cdf0e10cSrcweir 			}
756cdf0e10cSrcweir 		}
757cdf0e10cSrcweir 		break;
758cdf0e10cSrcweir 
759cdf0e10cSrcweir 		// ein Fehler trat auf
760cdf0e10cSrcweir 		case( ABORT_READING ):
761cdf0e10cSrcweir 		{
762cdf0e10cSrcweir 			bEnd = sal_True;
763cdf0e10cSrcweir 			eActAction = END_READING;
764cdf0e10cSrcweir 		}
765cdf0e10cSrcweir 		break;
766cdf0e10cSrcweir 
767cdf0e10cSrcweir 		default:
768cdf0e10cSrcweir 		break;
769cdf0e10cSrcweir 	}
770cdf0e10cSrcweir 
771cdf0e10cSrcweir 	// Stream an die richtige Stelle bringen,
772cdf0e10cSrcweir 	// falls Daten gelesen werden konnten
773cdf0e10cSrcweir 	// entweder alte Position oder aktuelle Position
774cdf0e10cSrcweir 	if( bRead || bEnd )
775cdf0e10cSrcweir 		nLastPos = rIStm.Tell();
776cdf0e10cSrcweir 
777cdf0e10cSrcweir 	return bRead;
778cdf0e10cSrcweir }
779cdf0e10cSrcweir 
780cdf0e10cSrcweir // ------------------------------------------------------------------------
781cdf0e10cSrcweir 
ReadGIF(Graphic & rGraphic)782cdf0e10cSrcweir ReadState GIFReader::ReadGIF( Graphic& rGraphic )
783cdf0e10cSrcweir {
784cdf0e10cSrcweir 	ReadState eReadState;
785cdf0e10cSrcweir 
786cdf0e10cSrcweir 	bStatus = sal_True;
787cdf0e10cSrcweir 
788cdf0e10cSrcweir 	while( ProcessGIF() && ( eActAction != END_READING ) ) {}
789cdf0e10cSrcweir 
790cdf0e10cSrcweir 	if( !bStatus )
791cdf0e10cSrcweir 		eReadState = GIFREAD_ERROR;
792cdf0e10cSrcweir 	else if( eActAction == END_READING )
793cdf0e10cSrcweir 		eReadState = GIFREAD_OK;
794cdf0e10cSrcweir 	else
795cdf0e10cSrcweir 	{
796cdf0e10cSrcweir 		if ( rIStm.GetError() == ERRCODE_IO_PENDING )
797cdf0e10cSrcweir 			rIStm.ResetError();
798cdf0e10cSrcweir 
799cdf0e10cSrcweir 		eReadState = GIFREAD_NEED_MORE;
800cdf0e10cSrcweir 	}
801cdf0e10cSrcweir 
802cdf0e10cSrcweir 	if( aAnimation.Count() == 1 )
803cdf0e10cSrcweir 	{
804cdf0e10cSrcweir 		rGraphic = aAnimation.Get( 0 ).aBmpEx;
805cdf0e10cSrcweir 
806cdf0e10cSrcweir 		if( nLogWidth100 && nLogHeight100 )
807cdf0e10cSrcweir 		{
808cdf0e10cSrcweir 			rGraphic.SetPrefSize( Size( nLogWidth100, nLogHeight100 ) );
809cdf0e10cSrcweir 			rGraphic.SetPrefMapMode( MAP_100TH_MM );
810cdf0e10cSrcweir 		}
811cdf0e10cSrcweir 	}
812cdf0e10cSrcweir 	else
813cdf0e10cSrcweir 		rGraphic = aAnimation;
814cdf0e10cSrcweir 
815cdf0e10cSrcweir 	return eReadState;
816cdf0e10cSrcweir }
817cdf0e10cSrcweir 
818cdf0e10cSrcweir 
819cdf0e10cSrcweir // -------------
820cdf0e10cSrcweir // - ImportGIF -
821cdf0e10cSrcweir // -------------
822cdf0e10cSrcweir 
ImportGIF(SvStream & rStm,Graphic & rGraphic)823cdf0e10cSrcweir sal_Bool ImportGIF( SvStream & rStm, Graphic& rGraphic )
824cdf0e10cSrcweir {
825cdf0e10cSrcweir 	GIFReader*	pGIFReader = (GIFReader*) rGraphic.GetContext();
826cdf0e10cSrcweir 	sal_uInt16		nOldFormat = rStm.GetNumberFormatInt();
827cdf0e10cSrcweir 	ReadState	eReadState;
828cdf0e10cSrcweir 	sal_Bool		bRet = sal_True;
829cdf0e10cSrcweir 
830cdf0e10cSrcweir 	rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
831cdf0e10cSrcweir 
832cdf0e10cSrcweir 	if( !pGIFReader )
833cdf0e10cSrcweir 		pGIFReader = new GIFReader( rStm );
834cdf0e10cSrcweir 
835cdf0e10cSrcweir 	rGraphic.SetContext( NULL );
836cdf0e10cSrcweir 	eReadState = pGIFReader->ReadGIF( rGraphic );
837cdf0e10cSrcweir 
838cdf0e10cSrcweir 	if( eReadState == GIFREAD_ERROR )
839cdf0e10cSrcweir 	{
840cdf0e10cSrcweir 		bRet = sal_False;
841cdf0e10cSrcweir 		delete pGIFReader;
842cdf0e10cSrcweir 	}
843cdf0e10cSrcweir 	else if( eReadState == GIFREAD_OK )
844cdf0e10cSrcweir 		delete pGIFReader;
845cdf0e10cSrcweir 	else
846cdf0e10cSrcweir 	{
847cdf0e10cSrcweir 		rGraphic = pGIFReader->GetIntermediateGraphic();
848cdf0e10cSrcweir 		rGraphic.SetContext( pGIFReader );
849cdf0e10cSrcweir 	}
850cdf0e10cSrcweir 
851cdf0e10cSrcweir 	rStm.SetNumberFormatInt( nOldFormat );
852cdf0e10cSrcweir 
853cdf0e10cSrcweir 	return bRet;
854cdf0e10cSrcweir }
855