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-27 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           9 : GIFReader::GIFReader( SvStream& rStm ) :
      37             :             aGPalette       ( 256 ),
      38             :             aLPalette       ( 256 ),
      39             :             rIStm           ( rStm ),
      40             :             pAcc8           ( NULL ),
      41             :             pAcc1           ( NULL ),
      42           9 :             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          18 :             bImGraphicReady ( sal_False )
      53             : {
      54           9 :     maUpperName = rtl::OUString("SVIGIF");
      55           9 :     pSrcBuf = new sal_uInt8[ 256 ];
      56           9 :     ClearImageExtensions();
      57           9 : }
      58             : 
      59             : // ------------------------------------------------------------------------
      60             : 
      61          27 : GIFReader::~GIFReader()
      62             : {
      63           9 :     aImGraphic.SetContext( NULL );
      64             : 
      65           9 :     if( pAcc1 )
      66           1 :         aBmp1.ReleaseAccess( pAcc1 );
      67             : 
      68           9 :     if( pAcc8 )
      69           1 :         aBmp8.ReleaseAccess( pAcc8 );
      70             : 
      71           9 :     delete[] pSrcBuf;
      72          18 : }
      73             : 
      74             : // ------------------------------------------------------------------------
      75             : 
      76          74 : void GIFReader::ClearImageExtensions()
      77             : {
      78          74 :     nGCDisposalMethod = 0;
      79          74 :     bGCTransparent = sal_False;
      80          74 :     nTimer = 0;
      81          74 : }
      82             : 
      83             : // ------------------------------------------------------------------------
      84             : 
      85          58 : sal_Bool GIFReader::CreateBitmaps( long nWidth, long nHeight, BitmapPalette* pPal,
      86             :                                sal_Bool bWatchForBackgroundColor )
      87             : {
      88          58 :     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          58 :     if( bGCTransparent )
     105             :     {
     106          57 :         const Color aWhite( COL_WHITE );
     107             : 
     108          57 :         aBmp1 = Bitmap( aSize, 1 );
     109             : 
     110          57 :         if( !aAnimation.Count() )
     111           6 :             aBmp1.Erase( aWhite );
     112             : 
     113          57 :         pAcc1 = aBmp1.AcquireWriteAccess();
     114             : 
     115          57 :         if( pAcc1 )
     116             :         {
     117          57 :             cTransIndex1 = (sal_uInt8) pAcc1->GetBestPaletteIndex( aWhite );
     118          57 :             cNonTransIndex1 = cTransIndex1 ? 0 : 1;
     119             :         }
     120             :         else
     121           0 :             bStatus = sal_False;
     122             :     }
     123             : 
     124          58 :     if( bStatus )
     125             :     {
     126          58 :         aBmp8 = Bitmap( aSize, 8, pPal );
     127             : 
     128          58 :         if( !!aBmp8 && bWatchForBackgroundColor && aAnimation.Count() )
     129          51 :             aBmp8.Erase( (*pPal)[ nBackgroundColor ] );
     130             :         else
     131           7 :           aBmp8.Erase( Color( COL_WHITE ) );
     132             : 
     133          58 :         pAcc8 = aBmp8.AcquireWriteAccess();
     134          58 :         bStatus = ( pAcc8 != NULL );
     135             :     }
     136             : 
     137          58 :     return bStatus;
     138             : }
     139             : 
     140             : // ------------------------------------------------------------------------
     141             : 
     142           9 : sal_Bool GIFReader::ReadGlobalHeader()
     143             : {
     144             :     char    pBuf[ 7 ];
     145             :     sal_uInt8   nRF;
     146             :     sal_uInt8   nAspect;
     147           9 :     sal_Bool    bRet = sal_False;
     148             : 
     149           9 :     rIStm.Read( pBuf, 6 );
     150           9 :     if( NO_PENDING( rIStm ) )
     151             :     {
     152           9 :         pBuf[ 6 ] = 0;
     153           9 :         if( !strcmp( pBuf, "GIF87a" ) || !strcmp( pBuf, "GIF89a" ) )
     154             :         {
     155           9 :             rIStm.Read( pBuf, 7 );
     156           9 :             if( NO_PENDING( rIStm ) )
     157             :             {
     158           9 :                 SvMemoryStream aMemStm;
     159             : 
     160           9 :                 aMemStm.SetBuffer( pBuf, 7, sal_False, 7 );
     161           9 :                 aMemStm >> nGlobalWidth;
     162           9 :                 aMemStm >> nGlobalHeight;
     163           9 :                 aMemStm >> nRF;
     164           9 :                 aMemStm >> nBackgroundColor;
     165           9 :                 aMemStm >> nAspect;
     166             : 
     167           9 :                 bGlobalPalette = (sal_Bool) ( nRF & 0x80 );
     168             : 
     169           9 :                 if( bGlobalPalette )
     170           7 :                     ReadPaletteEntries( &aGPalette, 1 << ( ( nRF & 7 ) + 1 ) );
     171             :                 else
     172           2 :                     nBackgroundColor = 0;
     173             : 
     174           9 :                 if( NO_PENDING( rIStm ) )
     175           9 :                     bRet = sal_True;
     176           9 :             }
     177             :         }
     178             :         else
     179           0 :             bStatus = sal_False;
     180             :     }
     181             : 
     182           9 :     return bRet;
     183             : }
     184             : 
     185             : // ------------------------------------------------------------------------
     186             : 
     187           7 : void GIFReader::ReadPaletteEntries( BitmapPalette* pPal, sal_uLong nCount )
     188             : {
     189           7 :     const sal_uLong nLen = 3UL * nCount;
     190           7 :     sal_uInt8*      pBuf = new sal_uInt8[ nLen ];
     191             : 
     192           7 :     rIStm.Read( pBuf, nLen );
     193           7 :     if( NO_PENDING( rIStm ) )
     194             :     {
     195           7 :         sal_uInt8* pTmp = pBuf;
     196             : 
     197         702 :         for( sal_uLong i = 0UL; i < nCount; )
     198             :         {
     199         688 :             BitmapColor& rColor = (*pPal)[ (sal_uInt16) i++ ];
     200             : 
     201         688 :             rColor.SetRed( *pTmp++ );
     202         688 :             rColor.SetGreen( *pTmp++ );
     203         688 :             rColor.SetBlue( *pTmp++ );
     204             :         }
     205             : 
     206             :         // nach Moeglichkeit noch einige Standardfarben unterbringen
     207           7 :         if( nCount < 256UL )
     208             :         {
     209           5 :             (*pPal)[ 255UL ] = Color( COL_WHITE );
     210             : 
     211           5 :             if( nCount < 255UL )
     212           5 :                 (*pPal)[ 254UL ] = Color( COL_BLACK );
     213             :         }
     214             :     }
     215             : 
     216           7 :     delete[] pBuf;
     217           7 : }
     218             : 
     219             : // ------------------------------------------------------------------------
     220             : 
     221          62 : sal_Bool GIFReader::ReadExtension()
     222             : {
     223             :     sal_uInt8   cFunction;
     224             :     sal_uInt8   cSize;
     225             :     sal_uInt8   cByte;
     226          62 :     sal_Bool    bRet = sal_False;
     227          62 :     sal_Bool    bOverreadDataBlocks = sal_False;
     228             : 
     229             :     // Extension-Label
     230          62 :     rIStm >> cFunction;
     231          62 :     if( NO_PENDING( rIStm ) )
     232             :     {
     233             :         // Block-Laenge
     234          62 :         rIStm >> cSize;
     235             : 
     236          62 :         switch( cFunction )
     237             :         {
     238             :             // 'Graphic Control Extension'
     239             :             case( 0xf9 ) :
     240             :             {
     241             :                 sal_uInt8 cFlags;
     242             : 
     243          57 :                 rIStm >> cFlags;
     244          57 :                 rIStm >> nTimer;
     245          57 :                 rIStm >> nGCTransparentIndex;
     246          57 :                 rIStm >> cByte;
     247             : 
     248          57 :                 if ( NO_PENDING( rIStm ) )
     249             :                 {
     250          57 :                     nGCDisposalMethod = ( cFlags >> 2) & 7;
     251          57 :                     bGCTransparent = ( cFlags & 1 ) ? sal_True : sal_False;
     252          57 :                     bStatus = ( cSize == 4 ) && ( cByte == 0 );
     253          57 :                     bRet = sal_True;
     254             :                 }
     255             :             }
     256          57 :             break;
     257             : 
     258             :             // Application-Extension
     259             :             case ( 0xff ) :
     260             :             {
     261           3 :                 if ( NO_PENDING( rIStm ) )
     262             :                 {
     263             :                     // default diese Extension ueberlesen
     264           3 :                     bOverreadDataBlocks = sal_True;
     265             : 
     266             :                     // Appl.-Extension hat Laenge 11
     267           3 :                     if ( cSize == 0x0b )
     268             :                     {
     269           3 :                         rtl::OString aAppId = read_uInt8s_ToOString(rIStm, 8);
     270           3 :                         rtl::OString aAppCode = read_uInt8s_ToOString(rIStm, 3);
     271           3 :                         rIStm >> cSize;
     272             : 
     273             :                         // NetScape-Extension
     274           3 :                         if( aAppId.equalsL(RTL_CONSTASCII_STRINGPARAM("NETSCAPE")) && aAppCode.equalsL(RTL_CONSTASCII_STRINGPARAM("2.0")) && cSize == 3 )
     275             :                         {
     276           3 :                             rIStm >> cByte;
     277             : 
     278             :                             // Loop-Extension
     279           3 :                             if ( cByte == 0x01 )
     280             :                             {
     281           3 :                                 rIStm >> cByte;
     282           3 :                                 nLoops = cByte;
     283           3 :                                 rIStm >> cByte;
     284           3 :                                 nLoops |= ( (sal_uInt16) cByte << 8 );
     285           3 :                                 rIStm >> cByte;
     286             : 
     287           3 :                                 bStatus = ( cByte == 0 );
     288           3 :                                 bRet = NO_PENDING( rIStm );
     289           3 :                                 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           3 :                                 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           3 :                         }
     317             : 
     318             :                     }
     319             :                 }
     320             :             }
     321           3 :             break;
     322             : 
     323             :             // alles andere ueberlesen
     324             :             default:
     325           2 :                 bOverreadDataBlocks = sal_True;
     326           2 :             break;
     327             :         }
     328             : 
     329             :         // Sub-Blocks ueberlesen
     330          62 :         if ( bOverreadDataBlocks )
     331             :         {
     332           2 :             bRet = sal_True;
     333          21 :             while( cSize && bStatus && !rIStm.IsEof() )
     334             :             {
     335          17 :                 sal_uInt16  nCount = (sal_uInt16) cSize + 1;
     336          17 :                 char*   pBuffer = new char[ nCount ];
     337             : 
     338          17 :                 bRet = sal_False;
     339          17 :                 rIStm.Read( pBuffer, nCount );
     340          17 :                 if( NO_PENDING( rIStm ) )
     341             :                 {
     342          17 :                     cSize = (sal_uInt8) pBuffer[ cSize ];
     343          17 :                     bRet = sal_True;
     344             :                 }
     345             :                 else
     346           0 :                     cSize = 0;
     347             : 
     348          17 :                 delete[] pBuffer;
     349             :             }
     350             :         }
     351             :     }
     352             : 
     353          62 :     return bRet;
     354             : }
     355             : 
     356             : // ------------------------------------------------------------------------
     357             : 
     358          58 : sal_Bool GIFReader::ReadLocalHeader()
     359             : {
     360             :     sal_uInt8   pBuf[ 9 ];
     361          58 :     sal_Bool    bRet = sal_False;
     362             : 
     363          58 :     rIStm.Read( pBuf, 9 );
     364          58 :     if( NO_PENDING( rIStm ) )
     365             :     {
     366          58 :         SvMemoryStream  aMemStm;
     367             :         BitmapPalette*  pPal;
     368             :         sal_uInt8           nFlags;
     369             : 
     370          58 :         aMemStm.SetBuffer( (char*) pBuf, 9, sal_False, 9 );
     371          58 :         aMemStm >> nImagePosX;
     372          58 :         aMemStm >> nImagePosY;
     373          58 :         aMemStm >> nImageWidth;
     374          58 :         aMemStm >> nImageHeight;
     375          58 :         aMemStm >> nFlags;
     376             : 
     377             :         // Falls Interlaced, ersten Startwert vorgeben
     378          58 :         bInterlaced = ( ( nFlags & 0x40 ) == 0x40 );
     379          58 :         nLastInterCount = 7;
     380          58 :         nLastImageY = 0;
     381             : 
     382          58 :         if( nFlags & 0x80 )
     383             :         {
     384           0 :             pPal = &aLPalette;
     385           0 :             ReadPaletteEntries( pPal, 1 << ( (nFlags & 7 ) + 1 ) );
     386             :         }
     387             :         else
     388          58 :             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          58 :         if( NO_PENDING( rIStm ) )
     396             :         {
     397          58 :             CreateBitmaps( nImageWidth, nImageHeight, pPal, bGlobalPalette && ( pPal == &aGPalette ) );
     398          58 :             bRet = sal_True;
     399          58 :         }
     400             :     }
     401             : 
     402          58 :     return bRet;
     403             : }
     404             : 
     405             : // ------------------------------------------------------------------------
     406             : 
     407         145 : sal_uLong GIFReader::ReadNextBlock()
     408             : {
     409         145 :     sal_uLong   nRet = 0UL;
     410             :     sal_uLong   nRead;
     411             :     sal_uInt8   cBlockSize;
     412             : 
     413         145 :     rIStm >> cBlockSize;
     414             : 
     415         145 :     if ( rIStm.IsEof() )
     416           0 :         nRet = 4UL;
     417         145 :     else if ( NO_PENDING( rIStm ) )
     418             :     {
     419         145 :         if ( cBlockSize == 0 )
     420          56 :             nRet = 2UL;
     421             :         else
     422             :         {
     423          89 :             rIStm.Read( pSrcBuf, cBlockSize );
     424             : 
     425          89 :             if( NO_PENDING( rIStm ) )
     426             :             {
     427          89 :                 if( bOverreadBlock )
     428           0 :                     nRet = 3UL;
     429             :                 else
     430             :                 {
     431             :                     sal_Bool    bEOI;
     432          89 :                     HPBYTE  pTarget = pDecomp->DecompressBlock( pSrcBuf, cBlockSize, nRead, bEOI );
     433             : 
     434          89 :                     nRet = ( bEOI ? 3 : 1 );
     435             : 
     436          89 :                     if( nRead && !bOverreadBlock )
     437          89 :                         FillImages( pTarget, nRead );
     438             : 
     439          89 :                     rtl_freeMemory( pTarget );
     440             :                 }
     441             :             }
     442             :         }
     443             :     }
     444             : 
     445         145 :     return nRet;
     446             : }
     447             : 
     448             : // ------------------------------------------------------------------------
     449             : 
     450          89 : void GIFReader::FillImages( HPBYTE pBytes, sal_uLong nCount )
     451             : {
     452       25487 :     for( sal_uLong i = 0UL; i < nCount; i++ )
     453             :     {
     454       25399 :         if( nImageX >= nImageWidth )
     455             :         {
     456        1089 :             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        1089 :                 nLastImageY = ++nImageY;
     521        1089 :                 nYAcc = nImageY;
     522             :             }
     523             : 
     524             :             // Zeile faengt von vorne an
     525        1089 :             nImageX = 0;
     526             :         }
     527             : 
     528       25399 :         if( nImageY < nImageHeight )
     529             :         {
     530       25398 :             const sal_uInt8 cTmp = pBytes[ i ];
     531             : 
     532       25398 :             if( bGCTransparent )
     533             :             {
     534       25398 :                 if( cTmp == nGCTransparentIndex )
     535        7971 :                     pAcc1->SetPixel( nYAcc, nImageX++, cTransIndex1 );
     536             :                 else
     537             :                 {
     538       17427 :                     pAcc8->SetPixel( nYAcc, nImageX, cTmp );
     539       17427 :                     pAcc1->SetPixel( nYAcc, nImageX++, cNonTransIndex1 );
     540             :                 }
     541             :             }
     542             :             else
     543           0 :                 pAcc8->SetPixel( nYAcc, nImageX++, cTmp );
     544             :         }
     545             :         else
     546             :         {
     547           1 :             bOverreadBlock = sal_True;
     548           1 :             break;
     549             :         }
     550             :     }
     551          89 : }
     552             : 
     553             : // ------------------------------------------------------------------------
     554             : 
     555          56 : void GIFReader::CreateNewBitmaps()
     556             : {
     557          56 :     AnimationBitmap aAnimBmp;
     558             : 
     559          56 :     aBmp8.ReleaseAccess( pAcc8 );
     560          56 :     pAcc8 = NULL;
     561             : 
     562          56 :     if( bGCTransparent )
     563             :     {
     564          56 :         aBmp1.ReleaseAccess( pAcc1 );
     565          56 :         pAcc1 = NULL;
     566          56 :         aAnimBmp.aBmpEx = BitmapEx( aBmp8, aBmp1 );
     567             :     }
     568             :     else
     569           0 :         aAnimBmp.aBmpEx = BitmapEx( aBmp8 );
     570             : 
     571          56 :     aAnimBmp.aPosPix = Point( nImagePosX, nImagePosY );
     572          56 :     aAnimBmp.aSizePix = Size( nImageWidth, nImageHeight );
     573          56 :     aAnimBmp.nWait = ( nTimer != 65535 ) ? nTimer : ANIMATION_TIMEOUT_ON_CLICK;
     574          56 :     aAnimBmp.bUserInput = sal_False;
     575             : 
     576          56 :     if( nGCDisposalMethod == 2 )
     577          48 :         aAnimBmp.eDisposal = DISPOSE_BACK;
     578           8 :     else if( nGCDisposalMethod == 3 )
     579           0 :         aAnimBmp.eDisposal = DISPOSE_PREVIOUS;
     580             :     else
     581           8 :         aAnimBmp.eDisposal = DISPOSE_NOT;
     582             : 
     583          56 :     aAnimation.Insert( aAnimBmp );
     584             : 
     585          56 :     if( aAnimation.Count() == 1 )
     586             :     {
     587           5 :         aAnimation.SetDisplaySizePixel( Size( nGlobalWidth, nGlobalHeight ) );
     588           5 :         aAnimation.SetLoopCount( nLoops );
     589          56 :     }
     590          56 : }
     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         461 : sal_Bool GIFReader::ProcessGIF()
     626             : {
     627         461 :     sal_Bool bRead = sal_False;
     628         461 :     sal_Bool bEnd = sal_False;
     629             : 
     630         461 :     if ( !bStatus )
     631           1 :         eActAction = ABORT_READING;
     632             : 
     633             :     // Stream an die richtige Stelle bringen
     634         461 :     rIStm.Seek( nLastPos );
     635             : 
     636         461 :     switch( eActAction )
     637             :     {
     638             :         // naechsten Marker lesen
     639             :         case( MARKER_READING ):
     640             :         {
     641             :             sal_uInt8 cByte;
     642             : 
     643         127 :             rIStm >> cByte;
     644             : 
     645         127 :             if( rIStm.IsEof() )
     646           0 :                 eActAction = END_READING;
     647         127 :             else if( NO_PENDING( rIStm ) )
     648             :             {
     649         127 :                 bRead = sal_True;
     650             : 
     651         127 :                 if( cByte == '!' )
     652          62 :                     eActAction = EXTENSION_READING;
     653          65 :                 else if( cByte == ',' )
     654          58 :                     eActAction = LOCAL_HEADER_READING;
     655           7 :                 else if( cByte == ';' )
     656           5 :                     eActAction = END_READING;
     657             :                 else
     658           2 :                     eActAction = ABORT_READING;
     659             :             }
     660             :         }
     661         127 :         break;
     662             : 
     663             :         // ScreenDescriptor lesen
     664             :         case( GLOBAL_HEADER_READING ):
     665             :         {
     666           9 :             if( ( bRead = ReadGlobalHeader() ) == sal_True )
     667             :             {
     668           9 :                 ClearImageExtensions();
     669           9 :                 eActAction = MARKER_READING;
     670             :             }
     671             :         }
     672           9 :         break;
     673             : 
     674             : 
     675             :         // Extension lesen
     676             :         case( EXTENSION_READING ):
     677             :         {
     678          62 :             if( ( bRead = ReadExtension() ) == sal_True )
     679          62 :                 eActAction = MARKER_READING;
     680             :         }
     681          62 :         break;
     682             : 
     683             : 
     684             :         // Image-Descriptor lesen
     685             :         case( LOCAL_HEADER_READING ):
     686             :         {
     687          58 :             if( ( bRead = ReadLocalHeader() ) == sal_True )
     688             :             {
     689          58 :                 nYAcc = nImageX = nImageY = 0;
     690          58 :                 eActAction = FIRST_BLOCK_READING;
     691             :             }
     692             :         }
     693          58 :         break;
     694             : 
     695             : 
     696             :         // ersten Datenblock lesen
     697             :         case( FIRST_BLOCK_READING ):
     698             :         {
     699             :             sal_uInt8 cDataSize;
     700             : 
     701          57 :             rIStm >> cDataSize;
     702             : 
     703          57 :             if( rIStm.IsEof() )
     704           0 :                 eActAction = ABORT_READING;
     705          57 :             else if( cDataSize > 12 )
     706           1 :                 bStatus = sal_False;
     707          56 :             else if( NO_PENDING( rIStm ) )
     708             :             {
     709          56 :                 bRead = sal_True;
     710          56 :                 pDecomp = new GIFLZWDecompressor( cDataSize );
     711          56 :                 eActAction = NEXT_BLOCK_READING;
     712          56 :                 bOverreadBlock = sal_False;
     713             :             }
     714             :             else
     715           0 :                 eActAction = FIRST_BLOCK_READING;
     716             :         }
     717          57 :         break;
     718             : 
     719             :         // naechsten Datenblock lesen
     720             :         case( NEXT_BLOCK_READING ):
     721             :         {
     722         145 :             sal_uInt16  nLastX = nImageX;
     723         145 :             sal_uInt16  nLastY = nImageY;
     724         145 :             sal_uLong   nRet = ReadNextBlock();
     725             : 
     726             :             // Return: 0:Pending / 1:OK; / 2:OK und letzter Block: / 3:EOI / 4:HardAbort
     727         145 :             if( nRet )
     728             :             {
     729         145 :                 bRead = sal_True;
     730             : 
     731         145 :                 if ( nRet == 1UL )
     732             :                 {
     733          33 :                     bImGraphicReady = sal_True;
     734          33 :                     eActAction = NEXT_BLOCK_READING;
     735          33 :                     bOverreadBlock = sal_False;
     736             :                 }
     737             :                 else
     738             :                 {
     739         112 :                     if( nRet == 2UL )
     740             :                     {
     741          56 :                         delete pDecomp;
     742          56 :                         CreateNewBitmaps();
     743          56 :                         eActAction = MARKER_READING;
     744          56 :                         ClearImageExtensions();
     745             :                     }
     746          56 :                     else if( nRet == 3UL )
     747             :                     {
     748          56 :                         eActAction = NEXT_BLOCK_READING;
     749          56 :                         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         145 :         break;
     767             : 
     768             :         // ein Fehler trat auf
     769             :         case( ABORT_READING ):
     770             :         {
     771           3 :             bEnd = sal_True;
     772           3 :             eActAction = END_READING;
     773             :         }
     774           3 :         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         461 :     if( bRead || bEnd )
     784         460 :         nLastPos = rIStm.Tell();
     785             : 
     786         461 :     return bRead;
     787             : }
     788             : 
     789             : // ------------------------------------------------------------------------
     790             : 
     791           9 : ReadState GIFReader::ReadGIF( Graphic& rGraphic )
     792             : {
     793             :     ReadState eReadState;
     794             : 
     795           9 :     bStatus = sal_True;
     796             : 
     797           9 :     while( ProcessGIF() && ( eActAction != END_READING ) ) {}
     798             : 
     799           9 :     if( !bStatus )
     800           2 :         eReadState = GIFREAD_ERROR;
     801           7 :     else if( eActAction == END_READING )
     802           7 :         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           9 :     if( aAnimation.Count() == 1 )
     812             :     {
     813           2 :         rGraphic = aAnimation.Get( 0 ).aBmpEx;
     814             : 
     815           2 :         if( nLogWidth100 && nLogHeight100 )
     816             :         {
     817           0 :             rGraphic.SetPrefSize( Size( nLogWidth100, nLogHeight100 ) );
     818           0 :             rGraphic.SetPrefMapMode( MAP_100TH_MM );
     819             :         }
     820             :     }
     821             :     else
     822           7 :         rGraphic = aAnimation;
     823             : 
     824           9 :     return eReadState;
     825             : }
     826             : 
     827             : 
     828             : // -------------
     829             : // - ImportGIF -
     830             : // -------------
     831             : 
     832           9 : sal_Bool ImportGIF( SvStream & rStm, Graphic& rGraphic )
     833             : {
     834           9 :     GIFReader*  pGIFReader = (GIFReader*) rGraphic.GetContext();
     835           9 :     sal_uInt16      nOldFormat = rStm.GetNumberFormatInt();
     836             :     ReadState   eReadState;
     837           9 :     sal_Bool        bRet = sal_True;
     838             : 
     839           9 :     rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
     840             : 
     841           9 :     if( !pGIFReader )
     842           9 :         pGIFReader = new GIFReader( rStm );
     843             : 
     844           9 :     rGraphic.SetContext( NULL );
     845           9 :     eReadState = pGIFReader->ReadGIF( rGraphic );
     846             : 
     847           9 :     if( eReadState == GIFREAD_ERROR )
     848             :     {
     849           2 :         bRet = sal_False;
     850           2 :         delete pGIFReader;
     851             :     }
     852           7 :     else if( eReadState == GIFREAD_OK )
     853           7 :         delete pGIFReader;
     854             :     else
     855             :     {
     856           0 :         rGraphic = pGIFReader->GetIntermediateGraphic();
     857           0 :         rGraphic.SetContext( pGIFReader );
     858             :     }
     859             : 
     860           9 :     rStm.SetNumberFormatInt( nOldFormat );
     861             : 
     862           9 :     return bRet;
     863             : }
     864             : 
     865             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10