LCOV - code coverage report
Current view: top level - svtools/source/filter/igif - gifread.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 297 380 78.2 %
Date: 2012-08-25 Functions: 15 16 93.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 225 483 46.6 %

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

Generated by: LCOV version 1.10