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

Generated by: LCOV version 1.10