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