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

Generated by: LCOV version 1.10