LCOV - code coverage report
Current view: top level - libreoffice/svtools/source/filter/igif - gifread.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 298 380 78.4 %
Date: 2012-12-17 Functions: 15 16 93.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10