LCOV - code coverage report
Current view: top level - vcl/source/filter/igif - gifread.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 339 384 88.3 %
Date: 2014-11-03 Functions: 17 18 94.4 %
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         130 : 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         130 :     , 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         260 :     , cNonTransIndex1 ( 0 )
      61             : {
      62         130 :     maUpperName = "SVIGIF";
      63         130 :     pSrcBuf = new sal_uInt8[ 256 ];
      64         130 :     ClearImageExtensions();
      65         130 : }
      66             : 
      67         390 : GIFReader::~GIFReader()
      68             : {
      69         130 :     aImGraphic.SetContext( NULL );
      70             : 
      71         130 :     if( pAcc1 )
      72           2 :         aBmp1.ReleaseAccess( pAcc1 );
      73             : 
      74         130 :     if( pAcc8 )
      75           2 :         aBmp8.ReleaseAccess( pAcc8 );
      76             : 
      77         130 :     delete[] pSrcBuf;
      78         260 : }
      79             : 
      80         490 : void GIFReader::ClearImageExtensions()
      81             : {
      82         490 :     nGCDisposalMethod = 0;
      83         490 :     bGCTransparent = false;
      84         490 :     nTimer = 0;
      85         490 : }
      86             : 
      87         234 : bool GIFReader::CreateBitmaps( long nWidth, long nHeight, BitmapPalette* pPal,
      88             :                                bool bWatchForBackgroundColor )
      89             : {
      90         234 :     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         234 :     if (nWidth >= 64000 && nHeight >= 64000)
     100             :     {
     101           2 :         bStatus = false;
     102           2 :         return bStatus;
     103             :     }
     104             : #endif
     105             : 
     106         232 :     if( bGCTransparent )
     107             :     {
     108         218 :         const Color aWhite( COL_WHITE );
     109             : 
     110         218 :         aBmp1 = Bitmap( aSize, 1 );
     111             : 
     112         218 :         if( !aAnimation.Count() )
     113         110 :             aBmp1.Erase( aWhite );
     114             : 
     115         218 :         pAcc1 = aBmp1.AcquireWriteAccess();
     116             : 
     117         218 :         if( pAcc1 )
     118             :         {
     119         218 :             cTransIndex1 = (sal_uInt8) pAcc1->GetBestPaletteIndex( aWhite );
     120         218 :             cNonTransIndex1 = cTransIndex1 ? 0 : 1;
     121             :         }
     122             :         else
     123           0 :             bStatus = false;
     124             :     }
     125             : 
     126         232 :     if( bStatus )
     127             :     {
     128         232 :         aBmp8 = Bitmap( aSize, 8, pPal );
     129             : 
     130         232 :         if( !!aBmp8 && bWatchForBackgroundColor && aAnimation.Count() )
     131         108 :             aBmp8.Erase( (*pPal)[ nBackgroundColor ] );
     132             :         else
     133         124 :           aBmp8.Erase( Color( COL_WHITE ) );
     134             : 
     135         232 :         pAcc8 = aBmp8.AcquireWriteAccess();
     136         232 :         bStatus = ( pAcc8 != NULL );
     137             :     }
     138             : 
     139         232 :     return bStatus;
     140             : }
     141             : 
     142         130 : bool GIFReader::ReadGlobalHeader()
     143             : {
     144             :     char    pBuf[ 7 ];
     145             :     sal_uInt8   nRF;
     146             :     sal_uInt8   nAspect;
     147         130 :     bool    bRet = false;
     148             : 
     149         130 :     rIStm.Read( pBuf, 6 );
     150         130 :     if( NO_PENDING( rIStm ) )
     151             :     {
     152         130 :         pBuf[ 6 ] = 0;
     153         130 :         if( !strcmp( pBuf, "GIF87a" ) || !strcmp( pBuf, "GIF89a" ) )
     154             :         {
     155         130 :             rIStm.Read( pBuf, 7 );
     156         130 :             if( NO_PENDING( rIStm ) )
     157             :             {
     158         130 :                 SvMemoryStream aMemStm;
     159             : 
     160         130 :                 aMemStm.SetBuffer( pBuf, 7, false, 7 );
     161         130 :                 aMemStm.ReadUInt16( nGlobalWidth );
     162         130 :                 aMemStm.ReadUInt16( nGlobalHeight );
     163         130 :                 aMemStm.ReadUChar( nRF );
     164         130 :                 aMemStm.ReadUChar( nBackgroundColor );
     165         130 :                 aMemStm.ReadUChar( nAspect );
     166             : 
     167         130 :                 bGlobalPalette = ( nRF & 0x80 );
     168             : 
     169         130 :                 if( bGlobalPalette )
     170         114 :                     ReadPaletteEntries( &aGPalette, 1 << ( ( nRF & 7 ) + 1 ) );
     171             :                 else
     172          16 :                     nBackgroundColor = 0;
     173             : 
     174         130 :                 if( NO_PENDING( rIStm ) )
     175         130 :                     bRet = true;
     176         130 :             }
     177             :         }
     178             :         else
     179           0 :             bStatus = false;
     180             :     }
     181             : 
     182         130 :     return bRet;
     183             : }
     184             : 
     185         126 : void GIFReader::ReadPaletteEntries( BitmapPalette* pPal, sal_uLong nCount )
     186             : {
     187         126 :     const sal_uLong nLen = 3UL * nCount;
     188         126 :     boost::scoped_array<sal_uInt8> pBuf(new sal_uInt8[ nLen ]);
     189             : 
     190         126 :     rIStm.Read( pBuf.get(), nLen );
     191         126 :     if( NO_PENDING( rIStm ) )
     192             :     {
     193         126 :         sal_uInt8* pTmp = pBuf.get();
     194             : 
     195       13700 :         for( sal_uLong i = 0UL; i < nCount; )
     196             :         {
     197       13448 :             BitmapColor& rColor = (*pPal)[ (sal_uInt16) i++ ];
     198             : 
     199       13448 :             rColor.SetRed( *pTmp++ );
     200       13448 :             rColor.SetGreen( *pTmp++ );
     201       13448 :             rColor.SetBlue( *pTmp++ );
     202             :         }
     203             : 
     204             :         // if possible accommodate some standard colours
     205         126 :         if( nCount < 256UL )
     206             :         {
     207         100 :             (*pPal)[ 255UL ] = Color( COL_WHITE );
     208             : 
     209         100 :             if( nCount < 255UL )
     210         100 :                 (*pPal)[ 254UL ] = Color( COL_BLACK );
     211             :         }
     212         126 :     }
     213         126 : }
     214             : 
     215         288 : bool GIFReader::ReadExtension()
     216             : {
     217             :     sal_uInt8   cFunction;
     218             :     sal_uInt8   cSize;
     219             :     sal_uInt8   cByte;
     220         288 :     bool    bRet = false;
     221         288 :     bool    bOverreadDataBlocks = false;
     222             : 
     223             :     // Extension-Label
     224         288 :     rIStm.ReadUChar( cFunction );
     225         288 :     if( NO_PENDING( rIStm ) )
     226             :     {
     227             :         // Block length
     228         288 :         rIStm.ReadUChar( cSize );
     229             : 
     230         288 :         switch( cFunction )
     231             :         {
     232             :             // 'Graphic Control Extension'
     233             :             case( 0xf9 ) :
     234             :             {
     235             :                 sal_uInt8 cFlags;
     236             : 
     237         232 :                 rIStm.ReadUChar( cFlags );
     238         232 :                 rIStm.ReadUInt16( nTimer );
     239         232 :                 rIStm.ReadUChar( nGCTransparentIndex );
     240         232 :                 rIStm.ReadUChar( cByte );
     241             : 
     242         232 :                 if ( NO_PENDING( rIStm ) )
     243             :                 {
     244         232 :                     nGCDisposalMethod = ( cFlags >> 2) & 7;
     245         232 :                     bGCTransparent = ( cFlags & 1 );
     246         232 :                     bStatus = ( cSize == 4 ) && ( cByte == 0 );
     247         232 :                     bRet = true;
     248             :                 }
     249             :             }
     250         232 :             break;
     251             : 
     252             :             // Application extension
     253             :             case ( 0xff ) :
     254             :             {
     255          52 :                 if ( NO_PENDING( rIStm ) )
     256             :                 {
     257             :                     // by default overread this extension
     258          52 :                     bOverreadDataBlocks = true;
     259             : 
     260             :                     // Appl. extension has length 11
     261          52 :                     if ( cSize == 0x0b )
     262             :                     {
     263          52 :                         OString aAppId = read_uInt8s_ToOString(rIStm, 8);
     264         104 :                         OString aAppCode = read_uInt8s_ToOString(rIStm, 3);
     265          52 :                         rIStm.ReadUChar( cSize );
     266             : 
     267             :                         // NetScape-Extension
     268          52 :                         if( aAppId == "NETSCAPE" && aAppCode == "2.0" && cSize == 3 )
     269             :                         {
     270           8 :                             rIStm.ReadUChar( cByte );
     271             : 
     272             :                             // Loop-Extension
     273           8 :                             if ( cByte == 0x01 )
     274             :                             {
     275           8 :                                 rIStm.ReadUChar( cByte );
     276           8 :                                 nLoops = cByte;
     277           8 :                                 rIStm.ReadUChar( cByte );
     278           8 :                                 nLoops |= ( (sal_uInt16) cByte << 8 );
     279           8 :                                 rIStm.ReadUChar( cByte );
     280             : 
     281           8 :                                 bStatus = ( cByte == 0 );
     282           8 :                                 bRet = NO_PENDING( rIStm );
     283           8 :                                 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           8 :                                 if( nLoops )
     289           0 :                                     nLoops++;
     290             :                             }
     291             :                             else
     292           0 :                                 rIStm.SeekRel( -1 );
     293             :                         }
     294          44 :                         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          52 :                         }
     310             : 
     311             :                     }
     312             :                 }
     313             :             }
     314          52 :             break;
     315             : 
     316             :             // overread everything else
     317             :             default:
     318           4 :                 bOverreadDataBlocks = true;
     319           4 :             break;
     320             :         }
     321             : 
     322             :         // overread sub-blocks
     323         288 :         if ( bOverreadDataBlocks )
     324             :         {
     325          48 :             bRet = true;
     326         270 :             while( cSize && bStatus && !rIStm.IsEof() )
     327             :             {
     328         174 :                 sal_uInt16  nCount = (sal_uInt16) cSize + 1;
     329         174 :                 boost::scoped_array<char> pBuffer(new char[ nCount ]);
     330             : 
     331         174 :                 bRet = false;
     332         174 :                 rIStm.Read( pBuffer.get(), nCount );
     333         174 :                 if( NO_PENDING( rIStm ) )
     334             :                 {
     335         174 :                     cSize = (sal_uInt8) pBuffer[ cSize ];
     336         174 :                     bRet = true;
     337             :                 }
     338             :                 else
     339           0 :                     cSize = 0;
     340         174 :             }
     341             :         }
     342             :     }
     343             : 
     344         288 :     return bRet;
     345             : }
     346             : 
     347         234 : bool GIFReader::ReadLocalHeader()
     348             : {
     349             :     sal_uInt8   pBuf[ 9 ];
     350         234 :     bool    bRet = false;
     351             : 
     352         234 :     rIStm.Read( pBuf, 9 );
     353         234 :     if( NO_PENDING( rIStm ) )
     354             :     {
     355         234 :         SvMemoryStream  aMemStm;
     356             :         BitmapPalette*  pPal;
     357             :         sal_uInt8           nFlags;
     358             : 
     359         234 :         aMemStm.SetBuffer( (char*) pBuf, 9, false, 9 );
     360         234 :         aMemStm.ReadUInt16( nImagePosX );
     361         234 :         aMemStm.ReadUInt16( nImagePosY );
     362         234 :         aMemStm.ReadUInt16( nImageWidth );
     363         234 :         aMemStm.ReadUInt16( nImageHeight );
     364         234 :         aMemStm.ReadUChar( nFlags );
     365             : 
     366             :         // if interlaced, first define startvalue
     367         234 :         bInterlaced = ( ( nFlags & 0x40 ) == 0x40 );
     368         234 :         nLastInterCount = 7;
     369         234 :         nLastImageY = 0;
     370             : 
     371         234 :         if( nFlags & 0x80 )
     372             :         {
     373          12 :             pPal = &aLPalette;
     374          12 :             ReadPaletteEntries( pPal, 1 << ( (nFlags & 7 ) + 1 ) );
     375             :         }
     376             :         else
     377         222 :             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         234 :         if( NO_PENDING( rIStm ) )
     383             :         {
     384         234 :             CreateBitmaps( nImageWidth, nImageHeight, pPal, bGlobalPalette && ( pPal == &aGPalette ) );
     385         234 :             bRet = true;
     386         234 :         }
     387             :     }
     388             : 
     389         234 :     return bRet;
     390             : }
     391             : 
     392       14260 : sal_uLong GIFReader::ReadNextBlock()
     393             : {
     394       14260 :     sal_uLong   nRet = 0UL;
     395             :     sal_uLong   nRead;
     396             :     sal_uInt8   cBlockSize;
     397             : 
     398       14260 :     rIStm.ReadUChar( cBlockSize );
     399             : 
     400       14260 :     if ( rIStm.IsEof() )
     401           0 :         nRet = 4UL;
     402       14260 :     else if ( NO_PENDING( rIStm ) )
     403             :     {
     404       14260 :         if ( cBlockSize == 0 )
     405         230 :             nRet = 2UL;
     406             :         else
     407             :         {
     408       14030 :             rIStm.Read( pSrcBuf, cBlockSize );
     409             : 
     410       14030 :             if( NO_PENDING( rIStm ) )
     411             :             {
     412       14030 :                 if( bOverreadBlock )
     413           6 :                     nRet = 3UL;
     414             :                 else
     415             :                 {
     416             :                     bool    bEOI;
     417       14024 :                     HPBYTE  pTarget = pDecomp->DecompressBlock( pSrcBuf, cBlockSize, nRead, bEOI );
     418             : 
     419       14024 :                     nRet = ( bEOI ? 3 : 1 );
     420             : 
     421       14024 :                     if( nRead && !bOverreadBlock )
     422       14024 :                         FillImages( pTarget, nRead );
     423             : 
     424       14024 :                     rtl_freeMemory( pTarget );
     425             :                 }
     426             :             }
     427             :         }
     428             :     }
     429             : 
     430       14260 :     return nRet;
     431             : }
     432             : 
     433       14024 : void GIFReader::FillImages( HPBYTE pBytes, sal_uLong nCount )
     434             : {
     435    35450688 :     for( sal_uLong i = 0UL; i < nCount; i++ )
     436             :     {
     437    35436666 :         if( nImageX >= nImageWidth )
     438             :         {
     439       27824 :             if( bInterlaced )
     440             :             {
     441             :                 long nT1;
     442             : 
     443             :                 // lines will be copied if interlaced
     444         988 :                 if( nLastInterCount )
     445             :                 {
     446         496 :                     long nMinY = std::min( (long) nLastImageY + 1, (long) nImageHeight - 1 );
     447         496 :                     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         496 :                     if( ( nMinY > nLastImageY ) && ( nLastImageY < ( nImageHeight - 1 ) ) )
     452             :                     {
     453         496 :                         HPBYTE  pScanline8 = pAcc8->GetScanline( nYAcc );
     454         496 :                         sal_uLong   nSize8 = pAcc8->GetScanlineSize();
     455         496 :                         HPBYTE  pScanline1 = 0;
     456         496 :                         sal_uLong   nSize1 = 0;
     457             : 
     458         496 :                         if( bGCTransparent )
     459             :                         {
     460         496 :                             pScanline1 = pAcc1->GetScanline( nYAcc );
     461         496 :                             nSize1 = pAcc1->GetScanlineSize();
     462             :                         }
     463             : 
     464        1984 :                         for( long j = nMinY; j <= nMaxY; j++ )
     465             :                         {
     466        1488 :                             memcpy( pAcc8->GetScanline( j ), pScanline8, nSize8 );
     467             : 
     468        1488 :                             if( bGCTransparent )
     469        1488 :                                 memcpy( pAcc1->GetScanline( j ), pScanline1, nSize1 );
     470             :                         }
     471             :                     }
     472             :                 }
     473             : 
     474         988 :                 nT1 = ( ++nImageY ) << 3;
     475         988 :                 nLastInterCount = 7;
     476             : 
     477         988 :                 if( nT1 >= nImageHeight )
     478             :                 {
     479         868 :                     long nT2 = nImageY - ( ( nImageHeight + 7 ) >> 3 );
     480         868 :                     nT1 = ( nT2 << 3 ) + 4;
     481         868 :                     nLastInterCount = 3;
     482             : 
     483         868 :                     if( nT1 >= nImageHeight )
     484             :                     {
     485         744 :                         nT2 -= ( nImageHeight + 3 ) >> 3;
     486         744 :                         nT1 = ( nT2 << 2 ) + 2;
     487         744 :                         nLastInterCount = 1;
     488             : 
     489         744 :                         if( nT1 >= nImageHeight )
     490             :                         {
     491         496 :                             nT2 -= ( nImageHeight + 1 ) >> 2;
     492         496 :                             nT1 = ( nT2 << 1 ) + 1;
     493         496 :                             nLastInterCount = 0;
     494             :                         }
     495             :                     }
     496             :                 }
     497             : 
     498         988 :                 nLastImageY = (sal_uInt16) nT1;
     499         988 :                 nYAcc = nT1;
     500             :             }
     501             :             else
     502             :             {
     503       26836 :                 nLastImageY = ++nImageY;
     504       26836 :                 nYAcc = nImageY;
     505             :             }
     506             : 
     507             :             // line starts from the beginning
     508       27824 :             nImageX = 0;
     509             :         }
     510             : 
     511    35436666 :         if( nImageY < nImageHeight )
     512             :         {
     513    35436664 :             const sal_uInt8 cTmp = pBytes[ i ];
     514             : 
     515    35436664 :             if( bGCTransparent )
     516             :             {
     517     5307598 :                 if( cTmp == nGCTransparentIndex )
     518      660348 :                     pAcc1->SetPixelIndex( nYAcc, nImageX++, cTransIndex1 );
     519             :                 else
     520             :                 {
     521     4647250 :                     pAcc8->SetPixelIndex( nYAcc, nImageX, cTmp );
     522     4647250 :                     pAcc1->SetPixelIndex( nYAcc, nImageX++, cNonTransIndex1 );
     523             :                 }
     524             :             }
     525             :             else
     526    30129066 :                 pAcc8->SetPixelIndex( nYAcc, nImageX++, cTmp );
     527             :         }
     528             :         else
     529             :         {
     530           2 :             bOverreadBlock = true;
     531           2 :             break;
     532             :         }
     533             :     }
     534       14024 : }
     535             : 
     536         230 : void GIFReader::CreateNewBitmaps()
     537             : {
     538         230 :     AnimationBitmap aAnimBmp;
     539             : 
     540         230 :     aBmp8.ReleaseAccess( pAcc8 );
     541         230 :     pAcc8 = NULL;
     542             : 
     543         230 :     if( bGCTransparent )
     544             :     {
     545         216 :         aBmp1.ReleaseAccess( pAcc1 );
     546         216 :         pAcc1 = NULL;
     547         216 :         aAnimBmp.aBmpEx = BitmapEx( aBmp8, aBmp1 );
     548             :     }
     549             :     else
     550          14 :         aAnimBmp.aBmpEx = BitmapEx( aBmp8 );
     551             : 
     552         230 :     aAnimBmp.aPosPix = Point( nImagePosX, nImagePosY );
     553         230 :     aAnimBmp.aSizePix = Size( nImageWidth, nImageHeight );
     554         230 :     aAnimBmp.nWait = ( nTimer != 65535 ) ? nTimer : ANIMATION_TIMEOUT_ON_CLICK;
     555         230 :     aAnimBmp.bUserInput = false;
     556             : 
     557         230 :     if( nGCDisposalMethod == 2 )
     558          96 :         aAnimBmp.eDisposal = DISPOSE_BACK;
     559         134 :     else if( nGCDisposalMethod == 3 )
     560           0 :         aAnimBmp.eDisposal = DISPOSE_PREVIOUS;
     561             :     else
     562         134 :         aAnimBmp.eDisposal = DISPOSE_NOT;
     563             : 
     564         230 :     aAnimation.Insert( aAnimBmp );
     565             : 
     566         230 :     if( aAnimation.Count() == 1 )
     567             :     {
     568         122 :         aAnimation.SetDisplaySizePixel( Size( nGlobalWidth, nGlobalHeight ) );
     569         122 :         aAnimation.SetLoopCount( nLoops );
     570         230 :     }
     571         230 : }
     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       15800 : bool GIFReader::ProcessGIF()
     602             : {
     603       15800 :     bool bRead = false;
     604       15800 :     bool bEnd = false;
     605             : 
     606       15800 :     if ( !bStatus )
     607           2 :         eActAction = ABORT_READING;
     608             : 
     609             :     // set stream to right position
     610       15800 :     rIStm.Seek( nLastPos );
     611             : 
     612       15800 :     switch( eActAction )
     613             :     {
     614             :         // read next marker
     615             :         case( MARKER_READING ):
     616             :         {
     617             :             sal_uInt8 cByte;
     618             : 
     619         648 :             rIStm.ReadUChar( cByte );
     620             : 
     621         648 :             if( rIStm.IsEof() )
     622           0 :                 eActAction = END_READING;
     623         648 :             else if( NO_PENDING( rIStm ) )
     624             :             {
     625         648 :                 bRead = true;
     626             : 
     627         648 :                 if( cByte == '!' )
     628         288 :                     eActAction = EXTENSION_READING;
     629         360 :                 else if( cByte == ',' )
     630         234 :                     eActAction = LOCAL_HEADER_READING;
     631         126 :                 else if( cByte == ';' )
     632         120 :                     eActAction = END_READING;
     633             :                 else
     634           6 :                     eActAction = ABORT_READING;
     635             :             }
     636             :         }
     637         648 :         break;
     638             : 
     639             :         // read ScreenDescriptor
     640             :         case( GLOBAL_HEADER_READING ):
     641             :         {
     642         130 :             if( ( bRead = ReadGlobalHeader() ) )
     643             :             {
     644         130 :                 ClearImageExtensions();
     645         130 :                 eActAction = MARKER_READING;
     646             :             }
     647             :         }
     648         130 :         break;
     649             : 
     650             :         // read extension
     651             :         case( EXTENSION_READING ):
     652             :         {
     653         288 :             if( ( bRead = ReadExtension() ) )
     654         288 :                 eActAction = MARKER_READING;
     655             :         }
     656         288 :         break;
     657             : 
     658             :         // read Image-Descriptor
     659             :         case( LOCAL_HEADER_READING ):
     660             :         {
     661         234 :             if( ( bRead = ReadLocalHeader() ) )
     662             :             {
     663         234 :                 nYAcc = nImageX = nImageY = 0;
     664         234 :                 eActAction = FIRST_BLOCK_READING;
     665             :             }
     666             :         }
     667         234 :         break;
     668             : 
     669             :         // read first data block
     670             :         case( FIRST_BLOCK_READING ):
     671             :         {
     672             :             sal_uInt8 cDataSize;
     673             : 
     674         232 :             rIStm.ReadUChar( cDataSize );
     675             : 
     676         232 :             if( rIStm.IsEof() )
     677           0 :                 eActAction = ABORT_READING;
     678         232 :             else if( cDataSize > 12 )
     679           2 :                 bStatus = false;
     680         230 :             else if( NO_PENDING( rIStm ) )
     681             :             {
     682         230 :                 bRead = true;
     683         230 :                 pDecomp = new GIFLZWDecompressor( cDataSize );
     684         230 :                 eActAction = NEXT_BLOCK_READING;
     685         230 :                 bOverreadBlock = false;
     686             :             }
     687             :             else
     688           0 :                 eActAction = FIRST_BLOCK_READING;
     689             :         }
     690         232 :         break;
     691             : 
     692             :         // read next data block
     693             :         case( NEXT_BLOCK_READING ):
     694             :         {
     695       14260 :             sal_uInt16  nLastX = nImageX;
     696       14260 :             sal_uInt16  nLastY = nImageY;
     697       14260 :             sal_uLong   nRet = ReadNextBlock();
     698             : 
     699             :             // Return: 0:Pending / 1:OK; / 2:OK and last block: / 3:EOI / 4:HardAbort
     700       14260 :             if( nRet )
     701             :             {
     702       14260 :                 bRead = true;
     703             : 
     704       14260 :                 if ( nRet == 1UL )
     705             :                 {
     706       13794 :                     bImGraphicReady = true;
     707       13794 :                     eActAction = NEXT_BLOCK_READING;
     708       13794 :                     bOverreadBlock = false;
     709             :                 }
     710             :                 else
     711             :                 {
     712         466 :                     if( nRet == 2UL )
     713             :                     {
     714         230 :                         delete pDecomp;
     715         230 :                         CreateNewBitmaps();
     716         230 :                         eActAction = MARKER_READING;
     717         230 :                         ClearImageExtensions();
     718             :                     }
     719         236 :                     else if( nRet == 3UL )
     720             :                     {
     721         236 :                         eActAction = NEXT_BLOCK_READING;
     722         236 :                         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       14260 :         break;
     740             : 
     741             :         // an error occurred
     742             :         case( ABORT_READING ):
     743             :         {
     744           8 :             bEnd = true;
     745           8 :             eActAction = END_READING;
     746             :         }
     747           8 :         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       15800 :     if( bRead || bEnd )
     757       15798 :         nLastPos = rIStm.Tell();
     758             : 
     759       15800 :     return bRead;
     760             : }
     761             : 
     762         130 : ReadState GIFReader::ReadGIF( Graphic& rGraphic )
     763             : {
     764             :     ReadState eReadState;
     765             : 
     766         130 :     bStatus = true;
     767             : 
     768         130 :     while( ProcessGIF() && ( eActAction != END_READING ) ) {}
     769             : 
     770         130 :     if( !bStatus )
     771           4 :         eReadState = GIFREAD_ERROR;
     772         126 :     else if( eActAction == END_READING )
     773         126 :         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         130 :     if( aAnimation.Count() == 1 )
     783             :     {
     784         114 :         rGraphic = aAnimation.Get( 0 ).aBmpEx;
     785             : 
     786         114 :         if( nLogWidth100 && nLogHeight100 )
     787             :         {
     788           0 :             rGraphic.SetPrefSize( Size( nLogWidth100, nLogHeight100 ) );
     789           0 :             rGraphic.SetPrefMapMode( MAP_100TH_MM );
     790             :         }
     791             :     }
     792             :     else
     793          16 :         rGraphic = aAnimation;
     794             : 
     795         130 :     return eReadState;
     796             : }
     797             : 
     798         130 : bool ImportGIF( SvStream & rStm, Graphic& rGraphic )
     799             : {
     800         130 :     GIFReader*  pGIFReader = static_cast<GIFReader*>(rGraphic.GetContext());
     801         130 :     sal_uInt16  nOldFormat = rStm.GetNumberFormatInt();
     802             :     ReadState   eReadState;
     803         130 :     bool        bRet = true;
     804             : 
     805         130 :     rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
     806             : 
     807         130 :     if( !pGIFReader )
     808         130 :         pGIFReader = new GIFReader( rStm );
     809             : 
     810         130 :     rGraphic.SetContext( NULL );
     811         130 :     eReadState = pGIFReader->ReadGIF( rGraphic );
     812             : 
     813         130 :     if( eReadState == GIFREAD_ERROR )
     814             :     {
     815           4 :         bRet = false;
     816           4 :         delete pGIFReader;
     817             :     }
     818         126 :     else if( eReadState == GIFREAD_OK )
     819         126 :         delete pGIFReader;
     820             :     else
     821             :     {
     822           0 :         rGraphic = pGIFReader->GetIntermediateGraphic();
     823           0 :         rGraphic.SetContext( pGIFReader );
     824             :     }
     825             : 
     826         130 :     rStm.SetNumberFormatInt( nOldFormat );
     827             : 
     828         130 :     return bRet;
     829        1233 : }
     830             : 
     831             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10