mmplugins/imagingplugins/codecs/GifCodec/GIFcodec.cpp
branchRCL_3
changeset 50 948c7f65f6d4
equal deleted inserted replaced
49:735348f59235 50:948c7f65f6d4
       
     1 // Copyright (c) 1997-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Licensed under US Patent No 4,558,302 and foreign counterparts
       
    15 // 
       
    16 //
       
    17 
       
    18 // CGifWriteCodec::TableEntry() is based on compress_byte() from wrgif.c
       
    19 // in the IJG V6 code, Copyright (C) 1991-1997, Thomas G. Lane.
       
    20 
       
    21 #include <fbs.h>
       
    22 #include "GIFcodec.h"
       
    23 #include "rawimageprocessor.h"
       
    24 
       
    25 const TInt KPass2StartLine = 4;
       
    26 const TInt KPass3StartLine = 2;
       
    27 const TInt KPass4StartLine = 1;
       
    28 const TInt KPass1YPosIncrement = 8;
       
    29 const TInt KPass2YPosIncrement = 8;
       
    30 const TInt KPass3YPosIncrement = 4;
       
    31 const TInt KPass4YPosIncrement = 2;
       
    32 const TInt KPass1LineRepeat = 7;
       
    33 const TInt KPass2LineRepeat = 3;
       
    34 const TInt KPass3LineRepeat = 1;
       
    35 const TInt KPass4LineRepeat = 0;
       
    36 const TUint KLZWLimit = 20000;
       
    37 const TInt KSetCommentsLimit = 64;
       
    38 const TUint16 KTranspColIdxNotPresent = 0xFFFF;
       
    39 
       
    40 
       
    41 // CGifReadCodec
       
    42 CGifReadCodec::CGifReadCodec(TRgb* aGlobalPalette,TInt aBackgroundColorIndex, TSize aScreenSize,TBool aFastDecode):
       
    43 	iBackgroundColorIndex(aBackgroundColorIndex),
       
    44 	iScreenSize(aScreenSize),
       
    45 	iGlobalPalette(aGlobalPalette),
       
    46 	iFastDecode(aFastDecode)
       
    47 	{
       
    48 	}
       
    49 
       
    50 CGifReadCodec::~CGifReadCodec()
       
    51 	{
       
    52 	iComment.ResetAndDestroy();
       
    53     delete [] iPrefixIndex;
       
    54 	delete [] iSuffixCode;
       
    55 	delete [] iOutputString;
       
    56 	delete [] i64KPalette;
       
    57 	delete [] iPixelBuffer;
       
    58 	delete [] iMaskBuffer;
       
    59 	}
       
    60 
       
    61 CGifReadCodec* CGifReadCodec::NewL(TRgb* aGlobalPalette,TInt aBackgroundColorIndex, TSize aScreenSize,TBool aFastDecode)
       
    62 	{
       
    63 	CGifReadCodec* self = new(ELeave) CGifReadCodec(aGlobalPalette, aBackgroundColorIndex, aScreenSize, aFastDecode);
       
    64 	CleanupStack::PushL(self);
       
    65 
       
    66     self->ConstructL();
       
    67 
       
    68 	CleanupStack::Pop(self); 
       
    69 	return self;
       
    70 	}
       
    71 
       
    72 void CGifReadCodec::ConstructL()
       
    73     {
       
    74     CImageMaskProcessorReadCodec::ConstructL();
       
    75     
       
    76 	iPrefixIndex    = new (ELeave) TInt16[KGifConversionTableSize +1];
       
    77 	iSuffixCode     = new (ELeave) TUint8 [KGifConversionTableSize+1];
       
    78 	iOutputString   = new (ELeave) TUint8 [KGifConversionTableSize];
       
    79 	iPPos = &Pos();
       
    80 	iPixelBuffer = NULL;
       
    81 	iMaskBuffer = NULL;
       
    82     }
       
    83 
       
    84 void CGifReadCodec::InitFrameHeader(TFrameInfo& aFrameSettings, CFrameImageData& aFrameImageData)
       
    85 	{
       
    86 	ASSERT(aFrameSettings.CurrentFrameState() == TFrameInfo::EFrameInfoUninitialised);
       
    87 	iFrameInfo = &aFrameSettings;
       
    88 	iFrameData = &aFrameImageData;
       
    89 	iFrameImageDesc = NULL;
       
    90 	iFrameImageControl = NULL;
       
    91 	iReadingOtherExtensionBlock=EFalse;
       
    92 	iReadingCommentExtensionBlock = EFalse;
       
    93 	iComment.ResetAndDestroy();
       
    94 	iCommentIndex = 0;
       
    95 	iFrameInfo->SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingFrameHeader);
       
    96 	}
       
    97 
       
    98 TFrameState CGifReadCodec::ProcessFrameHeaderL(TBufPtr8& aData)
       
    99 	{	
       
   100 	iStartDataPtr = CONST_CAST(TUint8*,aData.Ptr());
       
   101 	iDataPtr = iStartDataPtr;
       
   102 	iDataPtrLimit = iStartDataPtr + aData.Length();
       
   103 
       
   104 	if (iFrameInfo->CurrentFrameState() == TFrameInfo::EFrameInfoProcessingFrame)
       
   105 		{
       
   106 		do	{
       
   107 			//we need the block length (iDataPtr[0]+1) + the first byte of the next block
       
   108 			//(used in the KGifTerminatorId evaluation below)
       
   109 			if((iDataPtr + iDataPtr[0] + 2)<iDataPtrLimit)
       
   110 				{// If there is enough data in the buffer to continue processing header info
       
   111 				iFrameLZWInfo->iCompressedBytes += iDataPtr[0] + 1;
       
   112 
       
   113 				// Shift the local buffer data pointer to point to the beginning of the next block
       
   114 				iDataPtr += iDataPtr[0] + 1;
       
   115 			}
       
   116 			else
       
   117 				{ // Else if there is not enough data in the buffer shift the 'aData' pointer
       
   118 				// to point to the degining of the unused data and return to the calling method
       
   119 				// so that the buffer can be refilled.
       
   120 				aData.Shift((iDataPtr - iStartDataPtr));
       
   121 				return EFrameIncomplete;
       
   122 				}
       
   123 			} while(iDataPtr[0]!=KGifFrameTerminatorId); //Continue until end of frame is reached
       
   124 
       
   125 		if(iDataPtr[1] == KGifTerminatorId)
       
   126 			{ // End of Image File
       
   127 			DoSaveCommentsL();
       
   128 			iFrameInfo->SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingComplete);
       
   129 			return EFrameComplete;
       
   130 			}
       
   131 		else if ((iDataPtr[1] == KGifImageDescriptorId) || (iDataPtr[1] == KGifExtensionId))
       
   132 			{ // End of Frame
       
   133 			DoSaveCommentsL();
       
   134 			aData.Shift((iDataPtr - iStartDataPtr)+1); 
       
   135 			iFrameInfo->SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingComplete);
       
   136 			return EFrameIncomplete;
       
   137 			}
       
   138 		else
       
   139 			{ // Unexpected end of data
       
   140 			return EUnexpectedEndOfData;
       
   141 			}
       
   142 		}
       
   143 
       
   144 	if (iFrameInfo->CurrentFrameState() == TFrameInfo::EFrameInfoProcessingFrameHeader)
       
   145 		{
       
   146 		TRAPD(err,DoProcessInfoL(iDataPtr,iDataPtrLimit));
       
   147 		if (err == KErrCompletion)
       
   148 			{
       
   149 			DoSaveCommentsL();
       
   150 			return EFrameComplete; // KGifTerminatorId found - no more images
       
   151 			}
       
   152 
       
   153 		if (err == KErrUnderflow)
       
   154 			{
       
   155 			TInt dataUsed = iDataPtr - iStartDataPtr;
       
   156 			aData.Shift(dataUsed);
       
   157 			TInt frameDataOffset = iFrameInfo->FrameDataOffset();
       
   158 			iFrameInfo->SetFrameDataOffset(frameDataOffset + dataUsed);
       
   159 			return EFrameIncomplete;
       
   160 			}
       
   161 
       
   162 		if (err!=KErrNone)
       
   163 			{
       
   164 			User::LeaveIfError(err); // A real error occured
       
   165 			}
       
   166 
       
   167 		if (iFrameImageDesc == NULL)
       
   168 			{
       
   169 			User::Leave(KErrCorrupt);
       
   170 			}
       
   171 
       
   172 		TInt frameDataOffset = iFrameInfo->FrameDataOffset();
       
   173 		iFrameInfo->SetFrameDataOffset(frameDataOffset + (iDataPtr - iStartDataPtr));
       
   174 		aData.Shift(iDataPtr - iStartDataPtr);
       
   175 
       
   176 		iFrameInfo->iFrameSizeInTwips.SetSize(0,0);
       
   177 		iFrameInfo->iDelay = (iFrameImageControl) ? iFrameImageControl->iDelayTimeInCentiseconds * KGifCentiSecondsToMicroSeconds : 0;
       
   178 		iFrameInfo->iFlags = TFrameInfo::EColor | TFrameInfo::ECanDither | TFrameInfo::EUsesFrameSizeInPixels;
       
   179 		if (iFrameImageControl)
       
   180 			{
       
   181 			if (iFrameImageControl->iTransparentColorIndex != KErrNotFound)
       
   182 				{
       
   183 				iFrameInfo->iFlags |= TFrameInfo::ETransparencyPossible;
       
   184 				if(iFrameImageDesc->iInterlaced)
       
   185 					iFrameInfo->iFlags |= TFrameInfo::EPartialDecodeInvalid;
       
   186 				}
       
   187 			switch (iFrameImageControl->iDisposalMethod)
       
   188 				{
       
   189 			case TGifImageControl::ELeaveInPlace:
       
   190 				iFrameInfo->iFlags |= TFrameInfo::ELeaveInPlace;
       
   191 				break;
       
   192 			case TGifImageControl::ERestoreToBackground:
       
   193 				iFrameInfo->iFlags |= TFrameInfo::ERestoreToBackground;
       
   194 				break;
       
   195 			case TGifImageControl::ERestoreToPrevious:
       
   196 				iFrameInfo->iFlags |= TFrameInfo::ERestoreToPrevious;
       
   197 				break;
       
   198 			case ENone:
       
   199 			default:
       
   200 				break;
       
   201 				};
       
   202 			}
       
   203 
       
   204 		iFrameInfo->SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingFrame);
       
   205 		}
       
   206 
       
   207 	return EFrameIncomplete;
       
   208 	}
       
   209 
       
   210 TFrameState CGifReadCodec::ProcessFrameL(TBufPtr8& aSrc)
       
   211 	{
       
   212 	if ((iFrameSize.iWidth == 0) || (iFrameSize.iHeight == 0))
       
   213 		return EFrameComplete;
       
   214 
       
   215 	iPixRead = 0;
       
   216 
       
   217 	while (aSrc.Length() > 2 && !iComplete)
       
   218 		{
       
   219 		iDataPtr = aSrc.Ptr();
       
   220 		const TInt dataSize = iDataPtr[0];
       
   221 		iDataPtr++;
       
   222 		if (dataSize == 0 || dataSize >= aSrc.Length())
       
   223 		    {
       
   224 		    break;
       
   225 		    }
       
   226 		iDataPtrLimit = iDataPtr + dataSize;
       
   227 		DoProcessDataL();
       
   228 
       
   229 		aSrc.Shift(dataSize + 1);
       
   230 		}
       
   231 
       
   232 	TPoint& pos = Pos();
       
   233 	pos = *iPPos;
       
   234 	FlushPixBuffer(iLatestPixSize);
       
   235 	
       
   236 	if (iFastAccessMode) 
       
   237 		{
       
   238 		const TInt frameWidth = iFrameSize.iWidth;
       
   239 		TInt rowPixels = Min(frameWidth - pos.iX, iPixRead);
       
   240 		pos.iX += rowPixels;
       
   241 		iPixRead -= rowPixels;
       
   242 		if (pos.iX == frameWidth)
       
   243 			{
       
   244 			TInt rowCount = iPixRead/frameWidth+1;
       
   245 			pos.iY += rowCount;
       
   246 			iPixRead -= (rowCount-1) * frameWidth;
       
   247 			pos.iX = iPixRead;
       
   248 			}
       
   249 		iPixRead = 0;
       
   250 		}
       
   251 	
       
   252 	if (pos.iY >= (iFrameSize.iHeight + iFrameOffset.iY) || iComplete)
       
   253 		{
       
   254 		ImageProcessor()->FlushPixels();
       
   255 		CImageProcessor*const maskProc = MaskProcessor();
       
   256 		if (maskProc)
       
   257 			maskProc->FlushPixels();
       
   258 		pos = iFrameOffset;
       
   259 		//in case of iFast64kMode == true, palette is of type T64KPixel
       
   260 		if(iGifImageControl && iGifImageControl->iTransparentColorIndex != KErrNotFound && !iFast64kMode)
       
   261 			{
       
   262 			// reset the transparency index
       
   263 			if (iTranspColIdx != KTranspColIdxNotPresent)
       
   264 				{
       
   265 				const_cast<TRgb*>(&iPalette[iTranspColIdx])->SetAlpha(0xFF);
       
   266 				}
       
   267 			}
       
   268 		
       
   269 		return EFrameComplete;
       
   270 		}
       
   271 
       
   272 	return EFrameIncomplete;
       
   273 	}
       
   274 
       
   275 void CGifReadCodec::InitFrameL(TFrameInfo& aFrameInfo, CFrameImageData& aFrameImageData, TBool aDisableErrorDiffusion, CFbsBitmap& aDestination, CFbsBitmap* aDestinationMask)
       
   276 	{
       
   277   	iFrameInfo = &aFrameInfo;
       
   278   	iFrameData = &aFrameImageData;
       
   279 
       
   280 	//Make the first frame's size equal to the image size
       
   281 	if(CurrentFrame()==0)
       
   282 		{
       
   283 		iFrameSize = iFirstFrameSize;
       
   284 		iFrameOffset = iFirstFrameCoords.iTl;
       
   285 		}
       
   286 	else
       
   287 		{
       
   288 		iFrameSize = iFrameInfo->iOverallSizeInPixels;
       
   289 		iFrameOffset = TPoint(0,0);
       
   290 		}
       
   291 	iFrameCoords = iFrameInfo->iFrameCoordsInPixels;
       
   292 
       
   293 	// If the width or height is zero return. A similar test in ProcessFrameL() will complete the image
       
   294 	if ((iFrameSize.iWidth == 0) || (iFrameSize.iHeight == 0))
       
   295 		{
       
   296 		return;
       
   297 		}
       
   298 
       
   299 	if(iPixelBuffer == NULL || CurrentFrame() == 0)
       
   300 		{
       
   301 		iPixBufferSize = iFrameSize.iWidth * 8;//allocate buffer for first 8 lines
       
   302 		if (iPixBufferSize > KPixelBufMaxSize) 
       
   303 			{
       
   304 			iPixBufferSize = KPixelBufMaxSize;
       
   305 			}
       
   306 		if (aDestinationMask != NULL)
       
   307 			{
       
   308 			iPixBufferSize /= 2;//reserve space for mask
       
   309 			}
       
   310 		delete[] iPixelBuffer;
       
   311 		iPixelBuffer = new (ELeave) TUint32 [iPixBufferSize];
       
   312 		}
       
   313 
       
   314 	// Extract the image descriptor and control blocks.
       
   315 	iGifImageDesc = NULL;
       
   316 	iGifLZWInfo = NULL;
       
   317 	iGifImageControl = NULL;
       
   318 	iGifColorTable = NULL;
       
   319 
       
   320 	TInt frameDataCount = iFrameData->FrameDataCount();
       
   321 	for (TInt frameDataIndex = 0 ; frameDataIndex<frameDataCount ; frameDataIndex++)
       
   322 		{
       
   323 		TFrameDataBlock* frameData = iFrameData->GetFrameData(frameDataIndex);
       
   324 		if (frameData->DataType() == KGIFImageDescriptorUid)
       
   325 			{
       
   326 			iGifImageDesc = STATIC_CAST(TGifImageDescriptor*, frameData);
       
   327 			}
       
   328 		else if(frameData->DataType() == KGIFColorTableUid)
       
   329 			{
       
   330 			iGifColorTable = STATIC_CAST(TGifColorTable*, frameData);
       
   331 			}
       
   332 		else if(frameData->DataType() == KGIFLZWInfoUid)
       
   333 			{
       
   334 			iGifLZWInfo = STATIC_CAST(TGifLZWInfo*, frameData);
       
   335 			}
       
   336 		else if(frameData->DataType() == KGIFImageControlUid)
       
   337 			{
       
   338 			iGifImageControl = STATIC_CAST(TGifImageControl*, frameData);
       
   339 			}
       
   340 		}
       
   341 	iTranspColIdx = (iGifImageControl) ? iGifImageControl->iTransparentColorIndex : KTranspColIdxNotPresent;
       
   342 
       
   343 	// Set decode info
       
   344 	iPass = 1;
       
   345 	iYPosIncrement = KPass1YPosIncrement;
       
   346 	iBitBuffer = 0;
       
   347 	iBitBuffSize = 0;
       
   348 	iFirstChar = 0;
       
   349 	iPreviousCode = -1;
       
   350 	iComplete = EFalse;
       
   351 
       
   352 	ASSERT(iGifImageDesc);
       
   353 	ASSERT(iGifLZWInfo);
       
   354 
       
   355 	// Set palette to use
       
   356 	if(iGifImageDesc && iGifImageDesc->iLocalColorMap)
       
   357 		{
       
   358 		//Use of a frame palette was requested but was not found
       
   359 		if(iGifColorTable == NULL)
       
   360 			{
       
   361 			User::Leave(KErrCorrupt);
       
   362 			}
       
   363 		iPalette = iGifColorTable->iPalette;
       
   364 		}
       
   365 	else
       
   366 		{
       
   367 		iPalette = iGlobalPalette;
       
   368 		}
       
   369 
       
   370 	// Set table.Check for iClearCode value between 0 and 4096.
       
   371 	iClearCode = (1 << (iGifLZWInfo->iInitialCodeLength - 1));
       
   372 	if((iClearCode < 0) || (iClearCode > KGifConversionTableSize))
       
   373 		{
       
   374 		User::Leave(KErrCorrupt);
       
   375 		}
       
   376 	iEoiCode = iClearCode + 1;
       
   377 	for (TInt singleByteCodes = 0; singleByteCodes < iClearCode; singleByteCodes++)
       
   378 		{
       
   379 		iSuffixCode[singleByteCodes] = STATIC_CAST(TUint8,singleByteCodes);
       
   380 		}
       
   381 
       
   382 	TInt prefixLength = (KGifConversionTableSize + 1) * sizeof(TInt16);
       
   383 	Mem::Fill(iPrefixIndex, prefixLength, TChar(static_cast<TUint>(-1)));
       
   384 
       
   385 	iNextFree = ResetTableL();
       
   386 
       
   387 	iReductionFactor = 0;
       
   388 
       
   389 	CImageProcessor* imageProc = NULL;
       
   390 
       
   391 	const TSize destinationSize(aDestination.SizeInPixels());
       
   392 	
       
   393 	if(iUseFrameSizeInPixels)
       
   394 		{
       
   395 		iReductionFactor = ReductionFactor(iFrameInfo->iFrameSizeInPixels,destinationSize);
       
   396 		}
       
   397 	else
       
   398 		{
       
   399 		iReductionFactor = ReductionFactor(iFrameInfo->iOverallSizeInPixels,destinationSize);
       
   400 		}
       
   401 
       
   402     const TDisplayMode destMode = aDestination.DisplayMode();
       
   403     
       
   404     iFast64kMode = (iFastDecode &&
       
   405                     destMode == EColor64K && 
       
   406                     iReductionFactor == 0 && 
       
   407                     !iGifImageDesc->iInterlaced
       
   408                     );
       
   409                     
       
   410     if (iFast64kMode && i64KPalette==NULL)
       
   411         {
       
   412         i64KPalette = new (ELeave) T64KPixel[KGifColorTableMaxEntries];
       
   413         Mem::FillZ(i64KPalette, KGifColorTableMaxEntries*sizeof(T64KPixel) );
       
   414         }
       
   415         
       
   416 	
       
   417 	if (!iGifImageDesc->iInterlaced && iReductionFactor==0 &&
       
   418 	        (iFast64kMode || destMode == EColor16M || destMode == EColor16MU || destMode == EColor16MA) )
       
   419 	    {
       
   420 	    if (destMode == EColor16M) 
       
   421 	    	{
       
   422 	    	imageProc   = CRawImageUtilProcessor::NewL();
       
   423 	    	}
       
   424 		else
       
   425 			{
       
   426     		imageProc   = CRawImageProcessor::NewL();
       
   427 			}
       
   428 	    }
       
   429     
       
   430     if (iFast64kMode)
       
   431         {
       
   432 		// calculate fast 64K conversion palette		
       
   433         TInt idx = 0;
       
   434         do
       
   435             {
       
   436             i64KPalette[idx] = iPalette[idx]._Color64K();
       
   437             } 
       
   438             while (++idx < KGifColorTableMaxEntries);
       
   439         }
       
   440         
       
   441     if (imageProc == NULL)
       
   442         {
       
   443      	imageProc = ImageProcessorUtility::NewImageProcessorL(aDestination, iReductionFactor, iFast64kMode? EColor64K:ERgb, aDisableErrorDiffusion);    
       
   444         }
       
   445 
       
   446 	SetImageProcessor(imageProc);
       
   447 	iImgProc = imageProc;
       
   448 
       
   449 	iPositionOffset = TPoint(iFrameCoords.iTl.iX >> iReductionFactor,iFrameCoords.iTl.iY >> iReductionFactor);
       
   450 
       
   451 	TRect imageRegion(iPositionOffset + iFrameOffset,iPositionOffset + iFrameOffset + iFrameSize);
       
   452 	imageProc->PrepareL(aDestination,imageRegion);
       
   453 	imageProc->SetPos(iPositionOffset + iFrameOffset);
       
   454 	SetPos(iFrameOffset);
       
   455 
       
   456 	TInt lineLength	= (TDisplayModeUtils::NumDisplayModeBitsPerPixel( aDestination.DisplayMode() ) * aDestination.SizeInPixels().iWidth) >> 3;
       
   457 
       
   458 	
       
   459 	iFastAccessMode = (iReductionFactor == 0 && 
       
   460 						!iGifImageDesc->iInterlaced && 
       
   461 						imageRegion.Size() == aDestination.SizeInPixels() && 
       
   462 						lineLength == aDestination.ScanLineLength(aDestination.SizeInPixels().iWidth, aDestination.DisplayMode())
       
   463 						); // for direct access to bitmap buffer line length must be aligned to 4 bytes boundary
       
   464 
       
   465 	
       
   466 	if (iGifImageDesc->iInterlaced)
       
   467 		{
       
   468 		imageProc->SetYPosIncrement(iYPosIncrement);
       
   469 		if(!iGifImageControl || (iGifImageControl->iTransparentColorIndex==KErrNotFound))
       
   470 			{
       
   471 			imageProc->SetLineRepeat(KPass1LineRepeat);
       
   472 			}
       
   473 		}
       
   474 
       
   475 	CImageProcessor* maskProc = NULL;
       
   476 	SetMaskProcessor(NULL);
       
   477 	iMaskProc = NULL;
       
   478 
       
   479 	if(aDestinationMask != NULL)
       
   480 		{
       
   481 
       
   482 		ASSERT(aDestinationMask->SizeInPixels() == aDestination.SizeInPixels());
       
   483 			// this should be trapped at CImageDecoder::Convert()
       
   484 
       
   485 		if (iGifImageControl && (iGifImageControl->iTransparentColorIndex != KErrNotFound) && aDestinationMask->Handle())
       
   486 			{
       
   487 			ASSERT(MaskProcessor()==NULL);
       
   488 
       
   489 			if (iMaskBuffer == NULL || CurrentFrame() == 0)
       
   490 			    {
       
   491 			    delete [] iMaskBuffer; 
       
   492 				iMaskBuffer     = new (ELeave) TUint32 [iPixBufferSize];
       
   493 			    }
       
   494 		
       
   495 			iOpaqueMask	= 0xFF;// default for 256 mask
       
   496 			//Create a mask processor  and disable error diffusion
       
   497 			if (iGifImageDesc->iInterlaced || iReductionFactor > 0)
       
   498 				{
       
   499 				maskProc = ImageProcessorUtility::NewImageProcessorL(*aDestinationMask, iReductionFactor, EGray2, ETrue);	
       
   500 				}
       
   501 			else
       
   502 				{
       
   503 				// use optimized processor for non interlaced mask
       
   504 				maskProc = CRawImageUtilProcessor::NewL();
       
   505 				if(aDestinationMask->DisplayMode() == EGray2)
       
   506 					{
       
   507 					iOpaqueMask = 1;
       
   508 					}
       
   509 				}
       
   510 			SetMaskProcessor(maskProc);
       
   511 			iMaskProc = maskProc;
       
   512 			maskProc->PrepareL(*aDestinationMask,imageRegion);
       
   513 			if (iGifImageDesc->iInterlaced)
       
   514 				{
       
   515 				maskProc->SetYPosIncrement(iYPosIncrement);
       
   516 				}
       
   517 			// fill mask with black, so by default unknown parts don't draw
       
   518 			ClearBitmapL(*aDestinationMask,KRgbBlack);
       
   519 			maskProc->SetPos(iPositionOffset + iFrameOffset);
       
   520 
       
   521 			lineLength	= (TDisplayModeUtils::NumDisplayModeBitsPerPixel( aDestinationMask->DisplayMode() ) * aDestinationMask->SizeInPixels().iWidth) >> 3;
       
   522 			
       
   523 			iFastAccessMode = iFastAccessMode && lineLength == aDestinationMask->ScanLineLength(aDestinationMask->SizeInPixels().iWidth, aDestinationMask->DisplayMode()); // for direct access 
       
   524 			// to bitmap buffer line length must be aligned to 4 bytes boundary
       
   525 				
       
   526 			}
       
   527 		}
       
   528     else
       
   529 		{
       
   530 		if(destMode == EColor16MA && iGifImageControl && iGifImageControl->iTransparentColorIndex != KErrNotFound)
       
   531 			{
       
   532 			if (iTranspColIdx != KTranspColIdxNotPresent)
       
   533 				{
       
   534 				const_cast<TRgb*>(&iPalette[iTranspColIdx])->SetAlpha(0);
       
   535 				}
       
   536 			}
       
   537 		delete [] iMaskBuffer;
       
   538 		iMaskBuffer = NULL;
       
   539 		}
       
   540 
       
   541 	if ( iGifImageControl && (iGifImageControl->iDisposalMethod == TGifImageControl::ERestoreToBackground) ||
       
   542 		maskProc==NULL)
       
   543 		{
       
   544 		// Clear to background colour if requested or if we have no mask, so that
       
   545 		// on streamed partial decodes are background
       
   546 		ClearBitmapL(aDestination,iFrameInfo->iBackgroundColor);
       
   547 		}
       
   548 
       
   549 	}
       
   550 
       
   551 void CGifReadCodec::SetUseFrameSizeInPixels(TBool aUseFrameSizeInPixels)
       
   552 	{
       
   553 	iUseFrameSizeInPixels = aUseFrameSizeInPixels;
       
   554 	}
       
   555 
       
   556 
       
   557 void CGifReadCodec::DoProcessInfoL(const TUint8*& aDataPtr,const TUint8* aDataPtrLimit)
       
   558 	{
       
   559 	if(!iReadingExtensionBlock)
       
   560 		{
       
   561 		iBlockId = aDataPtr[0];
       
   562 		while (!iBlockId)
       
   563 			{
       
   564 			aDataPtr++;
       
   565 			if (aDataPtr >= aDataPtrLimit)
       
   566 				{
       
   567 				User::Leave(KErrUnderflow);
       
   568 				}
       
   569 			
       
   570 			iBlockId = aDataPtr[0];
       
   571 			}
       
   572 		}
       
   573 
       
   574 	while (iBlockId == KGifExtensionId || iReadingExtensionBlock)
       
   575 		{
       
   576 		iReadingExtensionBlock = ETrue;
       
   577 		DoProcessExtensionL(aDataPtr,aDataPtrLimit);
       
   578 		iReadingExtensionBlock = EFalse;
       
   579 		
       
   580 		// we skip empty blocks here
       
   581 		while( aDataPtr < aDataPtrLimit && (iBlockId = *aDataPtr) == 0)
       
   582 		    {
       
   583 		    ++aDataPtr;
       
   584 		    }
       
   585 
       
   586 		if (aDataPtr >= aDataPtrLimit)
       
   587 			{
       
   588 			User::Leave(KErrUnderflow);
       
   589 			}
       
   590 		}
       
   591 
       
   592 	if (iBlockId == KGifImageDescriptorId)
       
   593 		{
       
   594 		DoProcessImageDescriptorL(aDataPtr,aDataPtrLimit);
       
   595 		}
       
   596 	else if (iBlockId == KGifTerminatorId)
       
   597 		{
       
   598 		User::Leave(KErrCompletion);
       
   599 		}
       
   600 	else
       
   601 		{
       
   602 		User::Leave(KErrCorrupt);
       
   603 		}
       
   604 	}
       
   605 
       
   606 void CGifReadCodec::DoProcessExtensionL(const TUint8*& aDataPtr,const TUint8* aDataPtrLimit)
       
   607 	{
       
   608 	// Make sure we leave a block id for DoProcessInfoL()
       
   609 	aDataPtrLimit--;
       
   610 
       
   611 	TInt blockLength;
       
   612 	TInt dataPtrVal;
       
   613 	const TUint8* dataPtr = aDataPtr;
       
   614 	if (iReadingCommentExtensionBlock)
       
   615 		{
       
   616 		if ((aDataPtr + 2) > aDataPtrLimit)
       
   617 			{
       
   618 			User::Leave(KErrUnderflow);
       
   619 			}
       
   620 
       
   621 		dataPtrVal = KGifCommentExtensionId;
       
   622 		blockLength = aDataPtr[0];
       
   623 
       
   624 		if ((aDataPtr + blockLength + 2) > aDataPtrLimit)
       
   625 			{
       
   626 			User::Leave(KErrUnderflow);
       
   627 			}
       
   628 		}
       
   629 	else if (iReadingOtherExtensionBlock)
       
   630 		{
       
   631 		if ((aDataPtr + 2) > aDataPtrLimit)
       
   632 			{
       
   633 			User::Leave(KErrUnderflow);
       
   634 			}
       
   635 
       
   636 		dataPtrVal = KGifApplicationExtensionId;
       
   637 		blockLength = aDataPtr[0];
       
   638 
       
   639 		if ((aDataPtr + blockLength + 2) > aDataPtrLimit)
       
   640 			{
       
   641 			User::Leave(KErrUnderflow);
       
   642 			}
       
   643 		}
       
   644 	else
       
   645 		{
       
   646 		// we start reading block, there should be at least 3 bytes - id, ext. id, length
       
   647 		if ((aDataPtr + KGifExtBlkHeaderSize) > aDataPtrLimit)
       
   648 			{
       
   649 			User::Leave(KErrUnderflow);
       
   650 			}
       
   651 			
       
   652 		++dataPtr;
       
   653 		dataPtrVal  = *dataPtr; // get the ext. ID
       
   654 		++dataPtr;
       
   655 		blockLength = *dataPtr;
       
   656 		
       
   657 		// ensure that we've got all the block data in the buffer
       
   658 		// that's possible since max. block length for GIF is 255 bytes
       
   659 		if ((dataPtr + blockLength) > aDataPtrLimit)
       
   660 			{
       
   661 			User::Leave(KErrUnderflow);
       
   662 			}
       
   663 		}
       
   664 
       
   665 	switch (dataPtrVal)
       
   666 		{
       
   667 	case KGifApplicationExtensionId:
       
   668 	case KGifPlainTextExtensionId:
       
   669 		{
       
   670 		aDataPtr = dataPtr;
       
   671 		iReadingOtherExtensionBlock = ETrue;
       
   672 
       
   673 		while (blockLength != 0) 
       
   674 		    {
       
   675 			if (dataPtr + blockLength >= aDataPtrLimit)
       
   676 				{
       
   677 				aDataPtr = dataPtr;
       
   678 				User::Leave(KErrUnderflow);
       
   679 				}
       
   680 		    if (iReadingLoopIterationExtensionBlock)
       
   681                 {
       
   682                 TInt loopIterations = dataPtr[2] + (dataPtr[3] << 8);
       
   683                 TGifLoopIterations* iterationsDataBlock = new(ELeave) TGifLoopIterations;
       
   684                 CleanupStack::PushL(iterationsDataBlock);
       
   685                 iterationsDataBlock->iLoopIterations = loopIterations;
       
   686                 User::LeaveIfError(iFrameData->AppendImageData(iterationsDataBlock));
       
   687                 CleanupStack::Pop(iterationsDataBlock);
       
   688                 iReadingLoopIterationExtensionBlock = EFalse;
       
   689                 }
       
   690             else if (blockLength == KAppIdBlockLength)
       
   691                 {
       
   692                 TPtrC8 appId(dataPtr + 1, KAppIdLength);
       
   693                 TPtrC8 appAuthenticCode(dataPtr + 1 + KAppIdLength, KAppAuthenticCodeLength);
       
   694                 if ((appId == KAppIdNetscape) && (appAuthenticCode == KAppAuthenticCode2_0))
       
   695                     {
       
   696                     iReadingLoopIterationExtensionBlock = ETrue;
       
   697                     }
       
   698                 }
       
   699 
       
   700 			dataPtr += blockLength + 1;
       
   701 			if (dataPtr >= aDataPtrLimit)
       
   702 			    {
       
   703 			    User::Leave(KErrUnderflow);
       
   704 			    }
       
   705 			blockLength = dataPtr[0];
       
   706 			} 
       
   707 
       
   708 		iReadingOtherExtensionBlock = EFalse;
       
   709 		aDataPtr = dataPtr;
       
   710 		}
       
   711 		break;
       
   712 
       
   713 	case KGifCommentExtensionId:
       
   714 		{ // The problem here is a Block header is expected when were actually half way through the block!!!!!!!
       
   715 		if (!iReadingCommentExtensionBlock)
       
   716 			{
       
   717 			if(iCommentIndex < KSetCommentsLimit)
       
   718 				{
       
   719     		    ASSERT(iComment.Count()==iCommentIndex);
       
   720 	            HBufC8* comment = HBufC8::NewL(blockLength);
       
   721     			CleanupStack::PushL(comment);
       
   722     			User::LeaveIfError(iComment.Append(comment));
       
   723     			CleanupStack::Pop(comment);
       
   724 				}
       
   725 			iReadingCommentExtensionBlock = ETrue;
       
   726 			}
       
   727 		else
       
   728 			{
       
   729 			ASSERT(iComment.Count()==iCommentIndex+1);
       
   730 			HBufC8* comment = iComment[iCommentIndex];
       
   731 			iComment[iCommentIndex] = comment->ReAllocL(comment->Length()+blockLength);
       
   732 			}
       
   733 			
       
   734 		TPtr8 commentPtr(NULL,0);
       
   735 		if(iCommentIndex < KSetCommentsLimit)
       
   736 			{
       
   737 	 		commentPtr.Set( iComment[iCommentIndex]->Des() );
       
   738 			}
       
   739 		while (blockLength != 0)
       
   740 			{
       
   741 			// Append the block.
       
   742 			TPtrC8 newBlock(&dataPtr[1], blockLength);
       
   743 			if(iCommentIndex < KSetCommentsLimit)
       
   744 				{
       
   745 				commentPtr.Append(newBlock);
       
   746 				}
       
   747 
       
   748 			// Calculate the new block/comment length.
       
   749 			dataPtr += blockLength + 1;
       
   750 			if(dataPtr > aDataPtrLimit)
       
   751 				{
       
   752 				aDataPtr = dataPtr;
       
   753 				User::Leave(KErrUnderflow);
       
   754 				}
       
   755 			blockLength = dataPtr[0];
       
   756 
       
   757 			// Leave if the data for the new block is not present.
       
   758 			if (blockLength && ((dataPtr+blockLength+1) >= aDataPtrLimit))
       
   759 				{
       
   760 				aDataPtr = dataPtr;
       
   761 				User::Leave(KErrUnderflow);
       
   762 				}
       
   763 
       
   764 			// Re-allocate the comment, if there is another block.
       
   765 			if (blockLength != 0&&(iCommentIndex < KSetCommentsLimit))
       
   766 				{
       
   767 				HBufC8* comment = iComment[iCommentIndex];
       
   768 				iComment[iCommentIndex] = comment->ReAllocL(comment->Length()+blockLength);
       
   769 				commentPtr.Set(iComment[iCommentIndex]->Des());
       
   770 				}
       
   771 			}
       
   772 
       
   773 		iCommentIndex++;
       
   774 
       
   775 		aDataPtr = dataPtr;
       
   776 		}
       
   777 
       
   778 		iReadingCommentExtensionBlock = EFalse;
       
   779 		break;
       
   780 
       
   781 	case KGifGraphicControlExtensionId:
       
   782 		if (aDataPtr + blockLength + KGifExtBlkHeaderSize + 1 >= aDataPtrLimit)
       
   783 	        {
       
   784 	        User::Leave(KErrUnderflow);
       
   785 	        }
       
   786 	    
       
   787 	    aDataPtr += (KGifExtBlkHeaderSize + blockLength);
       
   788 	    // we ignore malformed extension block
       
   789 	    if (blockLength < KMinGifGraphicControlBlkLen)
       
   790 	        {
       
   791 	        break;
       
   792 	        }
       
   793 
       
   794 		++dataPtr; //go into block data
       
   795 		TUint8 flags = *dataPtr++;
       
   796 		
       
   797 		TGifImageControl* gifImageControl = new(ELeave) TGifImageControl;
       
   798 		CleanupStack::PushL(gifImageControl);
       
   799 
       
   800 		gifImageControl->iDelayTimeInCentiseconds = *dataPtr++;
       
   801 		gifImageControl->iDelayTimeInCentiseconds |= (*dataPtr++) << 8;
       
   802 		if (flags & 0x01)
       
   803 			gifImageControl->iTransparentColorIndex = *dataPtr++;
       
   804 		else
       
   805 			{
       
   806 			gifImageControl->iTransparentColorIndex = KErrNotFound;
       
   807 			dataPtr++;
       
   808 			}
       
   809 
       
   810 		gifImageControl->iDisposalMethod = TGifImageControl::TDisposalMethod((flags & 0x1c) >> 2);
       
   811 		gifImageControl->iUserInputFlag = (flags & 0x02) != 0;
       
   812 	
       
   813 		User::LeaveIfError(iFrameData->AppendFrameData(gifImageControl));
       
   814 
       
   815 		CleanupStack::Pop(); // gifImageControl
       
   816 		iFrameImageControl = gifImageControl;
       
   817 		break;
       
   818 		}
       
   819 
       
   820 	if (aDataPtr[0]!=0)
       
   821 		{
       
   822 		User::Leave(KErrCorrupt);
       
   823 		}
       
   824 		
       
   825 	aDataPtr++; // Absorb trailing zero
       
   826 	}
       
   827 
       
   828 void CGifReadCodec::DoProcessImageDescriptorL(const TUint8*& aDataPtr,const TUint8* aDataPtrLimit)
       
   829 	{
       
   830 	if (iFrameImageDesc != NULL)
       
   831 		{
       
   832 		User::Leave(KErrCorrupt);
       
   833 		}
       
   834 
       
   835 	if (aDataPtr + KGifImageInformationSize + KGifInitialCodeLengthSize > aDataPtrLimit)
       
   836 		{
       
   837 		User::Leave(KErrUnderflow);
       
   838 		}
       
   839 
       
   840 	TPoint topLeftCorner;
       
   841 	topLeftCorner.iX = aDataPtr[1] + (aDataPtr[2] << 8);
       
   842 	topLeftCorner.iY = aDataPtr[3] + (aDataPtr[4] << 8);
       
   843 
       
   844 	TSize imageSize;
       
   845 	imageSize.iWidth = aDataPtr[5] + (aDataPtr[6] << 8);
       
   846 	imageSize.iHeight = aDataPtr[7] + (aDataPtr[8] << 8);
       
   847 
       
   848 	//Save the first frame's real dimensions, but use the complete
       
   849 	//image size for the first frame
       
   850 	if(CurrentFrame()==0)
       
   851 		{
       
   852 		iFirstFrameSize = imageSize;
       
   853 		// TPoint (0,0) means that iFrameOffset is set to 0 as all frames are now treated the same for offset data
       
   854 		// But real (firstframe) imageSize is saved here as clients use first frames overallsizeinPixels
       
   855 		iFirstFrameCoords.SetRect(TPoint(0,0),imageSize);
       
   856 		const TSize screenSize(iScreenSize);
       
   857 		// there is leniency here for rogue gifs with first frames bigger than global screen size from gif header
       
   858 		TSize lenientImageSize = TSize(Max(imageSize.iWidth,screenSize.iWidth),
       
   859 				Max(imageSize.iHeight,screenSize.iHeight));	
       
   860 		iFrameInfo->iOverallSizeInPixels = lenientImageSize; 
       
   861 		//if the first frame has an offset, put it in the frame info
       
   862 		// this will be translated into the iPositionOffset variable
       
   863 		iFrameInfo->iFrameCoordsInPixels.SetRect(topLeftCorner,lenientImageSize);
       
   864 		}
       
   865 	else
       
   866 		{
       
   867 		iFrameInfo->iOverallSizeInPixels = imageSize;
       
   868 		iFrameInfo->iFrameCoordsInPixels.SetRect(topLeftCorner,imageSize);
       
   869 		}
       
   870 	iFrameInfo->iFrameSizeInPixels = imageSize;
       
   871 	
       
   872 	//adjust iFrameCoordsInPixels for proper behaviour
       
   873 	if(iUseFrameSizeInPixels)
       
   874 		{
       
   875 		iFrameInfo->iFrameCoordsInPixels.SetSize(iFrameInfo->iFrameSizeInPixels);
       
   876 		}
       
   877 
       
   878 	TUint8 flags = aDataPtr[9];
       
   879 
       
   880 	TGifImageDescriptor* gifImageDesc = new(ELeave) TGifImageDescriptor;
       
   881 	CleanupStack::PushL(gifImageDesc);
       
   882 
       
   883 	gifImageDesc->iLocalColorMap = flags & 0x80;
       
   884 	gifImageDesc->iInterlaced = flags & 0x40;
       
   885 	gifImageDesc->iSortedLocalMap = flags & 0x20;
       
   886 	if (gifImageDesc->iLocalColorMap)
       
   887 		{
       
   888 		iFrameInfo->iBitsPerPixel = (flags & 0x07) + 1;
       
   889 		TInt paletteEntries = 1 << iFrameInfo->iBitsPerPixel;
       
   890 		TInt paletteBytes = paletteEntries * KGifPaletteEntrySize;
       
   891 		if (aDataPtr + KGifImageInformationSize + paletteBytes + KGifInitialCodeLengthSize > aDataPtrLimit)
       
   892 			{
       
   893 			User::Leave(KErrUnderflow);
       
   894 			}
       
   895 
       
   896 		aDataPtr += KGifImageInformationSize;
       
   897 		const TUint8* paletteLimit = aDataPtr + paletteBytes;
       
   898 
       
   899 		TGifColorTable* gifColorTable = new(ELeave) TGifColorTable;
       
   900 		CleanupStack::PushL(gifColorTable);
       
   901 		TRgb* rgbPtr = gifColorTable->iPalette;
       
   902 		while (aDataPtr < paletteLimit)
       
   903 			{
       
   904 			*rgbPtr++ = TRgb(aDataPtr[0],aDataPtr[1],aDataPtr[2]);
       
   905 			aDataPtr += 3;
       
   906 			}
       
   907 		User::LeaveIfError(iFrameData->AppendFrameData(gifColorTable));
       
   908 		CleanupStack::Pop(gifColorTable);
       
   909 		}
       
   910 	else
       
   911 		{
       
   912 		aDataPtr += KGifImageInformationSize;
       
   913 		}
       
   914 
       
   915 	User::LeaveIfError(iFrameData->AppendFrameData(gifImageDesc));
       
   916 	CleanupStack::Pop(gifImageDesc);
       
   917 	
       
   918 	TGifLZWInfo* gifLZWInfo = new(ELeave) TGifLZWInfo;
       
   919 	CleanupStack::PushL(gifLZWInfo);
       
   920 
       
   921 	gifLZWInfo->iInitialCodeLength = aDataPtr[0] + 1;
       
   922 	User::LeaveIfError(iFrameData->AppendFrameData(gifLZWInfo));
       
   923 	aDataPtr++;
       
   924 
       
   925 	CleanupStack::Pop(gifLZWInfo);
       
   926 	iFrameImageDesc = gifImageDesc;
       
   927 	iFrameLZWInfo = gifLZWInfo;
       
   928 	}
       
   929 
       
   930 void CGifReadCodec::DoSaveCommentsL()
       
   931 	{
       
   932 	//If we have comments add it
       
   933 	TInt noOfComments = iComment.Count();
       
   934 	//If we have more than KSetCommentsLimit comments just restrict them as KSetCommentsLimit
       
   935 	if (noOfComments > KSetCommentsLimit)
       
   936 		{
       
   937 		noOfComments = KSetCommentsLimit;
       
   938 		}
       
   939 	for(TInt commentNo=0; commentNo<noOfComments; commentNo++)
       
   940 		{
       
   941 		TGifComment* comment = new(ELeave) TGifComment;
       
   942 		CleanupStack::PushL(comment);
       
   943 		comment->iComment = iComment[0];
       
   944 		User::LeaveIfError(iFrameData->AppendImageData(comment));
       
   945 		CleanupStack::Pop(); // comment
       
   946 
       
   947 		User::LeaveIfError(iFrameData->AppendImageBuffer(iComment[0]));
       
   948 		iComment.Remove(0);
       
   949 		}
       
   950 	}
       
   951 
       
   952 void CGifReadCodec::DoProcessDataL()
       
   953 	{
       
   954 	TInt nextFree = iNextFree;
       
   955 	TInt prevCode = iPreviousCode;
       
   956 	TBitBuffer bBuf = iBitBuffer;
       
   957 	TInt bbSize = iBitBuffSize;
       
   958 	TInt curCodeLen = iCurrentCodeLength;
       
   959 	iLatestPixSize = iFast64kMode ? sizeof(TUint16) : sizeof (TRgb);
       
   960 	
       
   961 	do
       
   962 		{
       
   963 		TInt code = NextCode(bBuf, bbSize, curCodeLen);
       
   964 		if (code == KErrNotFound)  
       
   965 			{
       
   966 			break; // not enought data in the buffer to get the code
       
   967 			}
       
   968 			
       
   969 	    if (iTableReset)
       
   970 			{
       
   971 			iTableReset = EFalse;
       
   972 			WriteCodeL(code);
       
   973 			prevCode    = code;
       
   974 			}
       
   975 		else if (code == iClearCode)
       
   976 			{
       
   977 			nextFree    = ResetTableL();
       
   978 			curCodeLen  = iCurrentCodeLength;
       
   979 			iTableReset = ETrue;
       
   980 			}
       
   981 		else if (code == iEoiCode)
       
   982 			{
       
   983 			iComplete = ETrue;
       
   984 			break;
       
   985 			}
       
   986 		else
       
   987 			{
       
   988 			if (prevCode >= nextFree)
       
   989 				{
       
   990 				User::Leave(KErrCorrupt);
       
   991 				}
       
   992 				
       
   993 			if ( (nextFree == (1 << curCodeLen)-1) &&  curCodeLen < KGifMaxBits)
       
   994 				{
       
   995 				++curCodeLen;
       
   996 				}
       
   997 				
       
   998 			if (code < nextFree)
       
   999 				{
       
  1000 				WriteCodeL(code);
       
  1001 				if (prevCode != -1)
       
  1002 					{					
       
  1003 				    iPrefixIndex[nextFree] = STATIC_CAST(TInt16,prevCode);
       
  1004 				    iSuffixCode[nextFree] = iFirstChar;
       
  1005 				    if (nextFree < KGifConversionTableSize )
       
  1006 				        {
       
  1007 				        nextFree++;    
       
  1008 				        }
       
  1009 					}
       
  1010 				}
       
  1011 			else
       
  1012 				{
       
  1013 				iPrefixIndex[nextFree] = STATIC_CAST(TInt16,prevCode);
       
  1014 				iSuffixCode[nextFree] = iFirstChar;
       
  1015 				WriteCodeL(nextFree);
       
  1016 			    if (nextFree < KGifConversionTableSize )
       
  1017 			        {
       
  1018 			        nextFree++;    
       
  1019 			        }
       
  1020 				}
       
  1021 				
       
  1022 			if(code < nextFree)
       
  1023 				{
       
  1024 				prevCode = code;
       
  1025 				}
       
  1026 			else
       
  1027 				{
       
  1028 				if(nextFree <= 1)
       
  1029 					{
       
  1030 					User::Leave(KErrCorrupt);
       
  1031 					}
       
  1032 				prevCode = iPrefixIndex[nextFree-1];
       
  1033 				}
       
  1034 			
       
  1035 			}
       
  1036 		} 
       
  1037 		while (iDataPtr <= iDataPtrLimit);
       
  1038 		
       
  1039 	ASSERT(iDataPtr <= iDataPtrLimit);
       
  1040 	
       
  1041 	SetCurrentCodeLengthL(curCodeLen);
       
  1042 	iBitBuffer      = bBuf;
       
  1043 	iBitBuffSize    = bbSize;
       
  1044 	iNextFree       = nextFree;
       
  1045 	iPreviousCode   = prevCode;
       
  1046 	}
       
  1047 
       
  1048 inline
       
  1049 TInt CGifReadCodec::ResetTableL()
       
  1050 	{
       
  1051 	const TInt nFree = iEoiCode + 1;
       
  1052 	
       
  1053 	SetCurrentCodeLengthL(iGifLZWInfo->iInitialCodeLength);
       
  1054 	return nFree;
       
  1055 	}
       
  1056 	
       
  1057 #if defined(__ARMCC__)
       
  1058 __forceinline
       
  1059 #else
       
  1060 inline 
       
  1061 #endif
       
  1062 TInt CGifReadCodec::NextCode(TBitBuffer& aBitBuffer, TInt& aBitBufSize,const TInt aCurCodeLen )
       
  1063 	{
       
  1064 	
       
  1065 	if (aCurCodeLen > aBitBufSize)
       
  1066 	    {
       
  1067 	    const TUint8* dataPtr = iDataPtr;
       
  1068 	    ASSERT( dataPtr <= iDataPtrLimit );
       
  1069 	    
       
  1070 	    TInt bytesToRead = (sizeof(TBitBuffer) * 8 - aBitBufSize) >> 3;
       
  1071 	    if (dataPtr + bytesToRead >= iDataPtrLimit)
       
  1072 	        {
       
  1073 	        bytesToRead = iDataPtrLimit - dataPtr;
       
  1074 	        if (bytesToRead == 0)
       
  1075 	            {
       
  1076 	            return KErrNotFound;
       
  1077 	            }
       
  1078 	        }
       
  1079 	    
       
  1080 	    do
       
  1081 	        {
       
  1082 	        aBitBuffer |= *dataPtr++ << aBitBufSize;
       
  1083 	        aBitBufSize +=8;
       
  1084 	        } 
       
  1085 	        while (--bytesToRead > 0);
       
  1086 	    
       
  1087 	    iDataPtr    = dataPtr;
       
  1088 	    if (aBitBufSize < aCurCodeLen)
       
  1089 	        {
       
  1090 	        return KErrNotFound;
       
  1091 	        }
       
  1092 
       
  1093 	    }
       
  1094     TInt code   = aBitBuffer;
       
  1095     aBitBuffer >>= aCurCodeLen;
       
  1096     code &= (1 << aCurCodeLen) - 1;
       
  1097     aBitBufSize -= aCurCodeLen;
       
  1098 
       
  1099     return code;
       
  1100 	}
       
  1101 
       
  1102 template <class TPalType, TInt aPtrDelta>
       
  1103 inline 
       
  1104 TUint8* CGifReadCodec::WriteGifBuffer(TUint8* aOutputStringPtr, TUint8* aOutputStringLimit)
       
  1105 	{
       
  1106 	TInt bufUsed = iPixBufCount;
       
  1107 	TInt bufFree = iPixBufferSize - bufUsed;
       
  1108 	
       
  1109 	if ((aOutputStringLimit-aOutputStringPtr) > bufFree) 
       
  1110 		{
       
  1111 		aOutputStringLimit = aOutputStringPtr+bufFree;
       
  1112 		}
       
  1113 	
       
  1114 	register TPalType* pixelBufferPtr = reinterpret_cast<TPalType*>( iPixelBuffer ) + bufUsed;
       
  1115 	const TPalType* tmp = pixelBufferPtr;
       
  1116 	const TPalType* palette;
       
  1117 
       
  1118 	if (aPtrDelta == 4)
       
  1119 		{
       
  1120 		palette = reinterpret_cast<const TPalType*>( iPalette );
       
  1121 		}
       
  1122 	else
       
  1123 		{
       
  1124 		palette = reinterpret_cast<const TPalType*>( i64KPalette );	
       
  1125 		}
       
  1126 
       
  1127 	if (iMaskProc)
       
  1128 		{
       
  1129 		register TUint32* maskPixelBufferPtr = iMaskBuffer + bufUsed;
       
  1130 		const TUint16 KTranspIdx= iTranspColIdx;
       
  1131 		const TUint32 KTranspMask = 0;
       
  1132     	const TUint32 KOpaqueMask = iOpaqueMask;
       
  1133 		const TPalType bgCol    = palette[ KTranspIdx ];
       
  1134 			
       
  1135 		while (aOutputStringPtr < aOutputStringLimit)
       
  1136 			{ 
       
  1137 			const TUint8 code = *aOutputStringPtr;
       
  1138 			if (code == KTranspIdx)
       
  1139 				{
       
  1140 				*pixelBufferPtr = bgCol; 
       
  1141 				*maskPixelBufferPtr = KTranspMask;
       
  1142 				}
       
  1143 			else 
       
  1144 				{
       
  1145 				*pixelBufferPtr = palette[code]; 
       
  1146 				*maskPixelBufferPtr = KOpaqueMask;
       
  1147 				}
       
  1148 			maskPixelBufferPtr++;
       
  1149 			pixelBufferPtr++;
       
  1150 			aOutputStringPtr++;
       
  1151 			}
       
  1152 		}
       
  1153 	else
       
  1154 		{
       
  1155 
       
  1156 		while (aOutputStringPtr < aOutputStringLimit)
       
  1157 			{ 
       
  1158 			*pixelBufferPtr = palette[*aOutputStringPtr]; 
       
  1159 			pixelBufferPtr++;
       
  1160 			aOutputStringPtr++;
       
  1161 			}
       
  1162 		}                                          
       
  1163 
       
  1164 	iPixBufCount += pixelBufferPtr-tmp;
       
  1165 	return aOutputStringPtr;	
       
  1166 	}
       
  1167 
       
  1168 /**
       
  1169     That shall only leave with KErrCorrupt
       
  1170     which means that image decoding is not possible
       
  1171 */
       
  1172 void CGifReadCodec::WriteCodeL(TInt aCode)
       
  1173 	{
       
  1174 	TUint8* outputStringLimit = iOutputString + KGifConversionTableSize;
       
  1175 	register TUint8* outputStringPtr = outputStringLimit;
       
  1176 	register TUint16 latestChar=0;
       
  1177 
       
  1178 	while (aCode >= 0)
       
  1179 		{
       
  1180 		ASSERT((aCode >= 0) && (aCode <= KGifConversionTableSize));
       
  1181 		
       
  1182 		outputStringPtr--;
       
  1183 		latestChar = iSuffixCode[aCode];
       
  1184 		outputStringPtr[0] = latestChar;
       
  1185 		aCode = iPrefixIndex[aCode];
       
  1186 		}                     
       
  1187 
       
  1188 	iFirstChar = latestChar; 
       
  1189 	if (aCode != KErrNotFound)
       
  1190 		{
       
  1191 		User::Leave(KErrCorrupt);
       
  1192 		}
       
  1193 
       
  1194 	while (true) 
       
  1195 		{
       
  1196 		if (iFast64kMode)
       
  1197 	    	{
       
  1198 	    	outputStringPtr = WriteGifBuffer<TUint16, sizeof(TUint16)>(outputStringPtr, outputStringLimit);
       
  1199 	    	}
       
  1200 		else
       
  1201 	    	{
       
  1202 	    	outputStringPtr = WriteGifBuffer<TRgb, sizeof(TRgb)>(outputStringPtr, outputStringLimit);    
       
  1203 	    	}
       
  1204 	
       
  1205     	if (outputStringPtr != outputStringLimit)
       
  1206         	{
       
  1207 			FlushPixBuffer(iLatestPixSize);
       
  1208         	}
       
  1209         else
       
  1210         	{
       
  1211         	break;	
       
  1212         	}
       
  1213 		}
       
  1214 	}
       
  1215 
       
  1216 inline
       
  1217 void CGifReadCodec::FlushPixBuffer(TInt aPixSize)
       
  1218     {
       
  1219     if (iPixBufCount)
       
  1220         {
       
  1221         if (iMaskProc)        	
       
  1222             {
       
  1223             WriteStringWithTransparency(reinterpret_cast<TUint8*>(iPixelBuffer), aPixSize, iMaskBuffer, iPixBufCount);
       
  1224             }        
       
  1225         else
       
  1226             {
       
  1227             WriteStringWithoutTransparency(reinterpret_cast<TUint8*>(iPixelBuffer), aPixSize, iPixBufCount);
       
  1228             }
       
  1229         
       
  1230         iPixBufCount = 0;
       
  1231         }    
       
  1232     }
       
  1233 
       
  1234 void CGifReadCodec::WriteStringWithoutTransparency(TUint8* aOutputString, TInt aPixSize, TInt aNumOfPixels)
       
  1235 	{
       
  1236 	CImageProcessor*const imageProc = iImgProc;
       
  1237 
       
  1238 	if (iFastAccessMode) 
       
  1239 		{
       
  1240 		imageProc->SetPixels(reinterpret_cast<TRgb*>(aOutputString), aNumOfPixels);
       
  1241 		iPixRead += aNumOfPixels;
       
  1242 		aNumOfPixels = 0;
       
  1243 		return;
       
  1244 		}
       
  1245 
       
  1246 	const TInt KImgXLimit = iFrameSize.iWidth + iFrameOffset.iX;
       
  1247 	
       
  1248 	while ( aNumOfPixels )
       
  1249 		{
       
  1250 		TInt rowPixels = Min(KImgXLimit - iPPos->iX, aNumOfPixels);
       
  1251 
       
  1252 		imageProc->SetPixels(reinterpret_cast<TRgb*>(aOutputString), rowPixels);
       
  1253 		aNumOfPixels    -= rowPixels;
       
  1254 		aOutputString   += rowPixels * aPixSize;
       
  1255 
       
  1256 		iPPos->iX += rowPixels;
       
  1257 		if (iPPos->iX == KImgXLimit)
       
  1258 			{
       
  1259 			imageProc->FlushPixels();
       
  1260 			UpdateYPos();
       
  1261 			imageProc->SetPos( TPoint(iPPos->iX+iPositionOffset.iX, iPPos->iY+iPositionOffset.iY) );
       
  1262 			}
       
  1263 		}
       
  1264 	}
       
  1265 
       
  1266 void CGifReadCodec::WriteStringWithTransparency(TUint8* aOutputString, TInt aPixSize, TUint32* aMaskString, TInt aNumOfPixels)
       
  1267 	{
       
  1268 	CImageProcessor*const imageProc = iImgProc;
       
  1269 	CImageProcessor*const maskProc  = iMaskProc;
       
  1270 	
       
  1271 	if (iFastAccessMode) 
       
  1272 		{
       
  1273 		imageProc->SetPixels(reinterpret_cast<TRgb*>(aOutputString), aNumOfPixels);
       
  1274 		if(maskProc) // For non-single 16MA bitmaps
       
  1275 			{
       
  1276 			maskProc->SetMonoPixels(reinterpret_cast<TUint32*>(aMaskString), aNumOfPixels);	
       
  1277 			}
       
  1278 		
       
  1279 		iPixRead += aNumOfPixels;
       
  1280 		aNumOfPixels = 0;
       
  1281 		return;
       
  1282 		}
       
  1283 
       
  1284 	const TInt KImgXLimit = iFrameSize.iWidth + iFrameOffset.iX;
       
  1285 	
       
  1286 	while ( aNumOfPixels )
       
  1287 		{
       
  1288 		TInt rowPixels = Min(KImgXLimit - iPPos->iX, aNumOfPixels);
       
  1289 
       
  1290 		imageProc->SetPixels(reinterpret_cast<TRgb*>(aOutputString), rowPixels);
       
  1291 		maskProc->SetMonoPixels(reinterpret_cast<TUint32*>(aMaskString), rowPixels);
       
  1292 
       
  1293 		iPPos->iX       += rowPixels;
       
  1294 		aOutputString   += rowPixels * aPixSize;
       
  1295 		aMaskString     += rowPixels;
       
  1296 		aNumOfPixels    -= rowPixels;
       
  1297 
       
  1298 		if (iPPos->iX == KImgXLimit)
       
  1299 			{
       
  1300 			imageProc->FlushPixels();
       
  1301 			UpdateYPos();
       
  1302 			const TPoint newPos(iPPos->iX+iPositionOffset.iX, iPPos->iY+iPositionOffset.iY);
       
  1303 			imageProc->SetPos(newPos);
       
  1304 			maskProc->SetPos(newPos);
       
  1305 			}
       
  1306 		}
       
  1307 	}
       
  1308 
       
  1309 inline
       
  1310 void CGifReadCodec::SetCurrentCodeLengthL(TInt aCodeLength)
       
  1311 	{
       
  1312 	if ((aCodeLength > KGifMaxBits) || (aCodeLength < 0))
       
  1313 		{
       
  1314 		User::Leave(KErrCorrupt);
       
  1315 		}
       
  1316 	iCurrentCodeLength = aCodeLength;
       
  1317 	}
       
  1318 
       
  1319 inline
       
  1320 void CGifReadCodec::UpdateYPos()
       
  1321 	{
       
  1322 	iPPos->iX = iFrameOffset.iX;
       
  1323 
       
  1324 	if (!iGifImageDesc->iInterlaced)
       
  1325 		{
       
  1326 		iPPos->iY++;
       
  1327 		return;
       
  1328 		}
       
  1329 		
       
  1330 	UpdateYPosInterlaced();
       
  1331 	}
       
  1332 
       
  1333 void CGifReadCodec::UpdateYPosInterlaced()
       
  1334     {
       
  1335     iPPos->iY += iYPosIncrement;
       
  1336 
       
  1337 	CImageProcessor*const imageProc = ImageProcessor();
       
  1338 	while (iPPos->iY >= iFrameSize.iHeight + iFrameOffset.iY)
       
  1339 		{
       
  1340 		iPass++;
       
  1341 		TInt lineRepeat;
       
  1342 		if (iPass == 2)
       
  1343 			{
       
  1344 			iPPos->iY = iFrameOffset.iY + KPass2StartLine;
       
  1345 			iYPosIncrement = KPass2YPosIncrement;
       
  1346 			lineRepeat = KPass2LineRepeat;
       
  1347 			}
       
  1348 		else if (iPass == 3)
       
  1349 			{
       
  1350 			iPPos->iY = iFrameOffset.iY + KPass3StartLine;
       
  1351 			iYPosIncrement = KPass3YPosIncrement;
       
  1352 			lineRepeat = KPass3LineRepeat;
       
  1353 			}
       
  1354 		else if (iPass == 4)
       
  1355 			{
       
  1356 			iPPos->iY = iFrameOffset.iY + KPass4StartLine;
       
  1357 			iYPosIncrement = KPass4YPosIncrement;
       
  1358 			lineRepeat = KPass4LineRepeat;
       
  1359 			}
       
  1360 		else
       
  1361 			break;
       
  1362 		imageProc->SetYPosIncrement(iYPosIncrement);
       
  1363 		if(!iGifImageControl || (iGifImageControl->iTransparentColorIndex==KErrNotFound))
       
  1364 		    {
       
  1365 		    imageProc->SetLineRepeat(lineRepeat);
       
  1366 		    }
       
  1367 		}
       
  1368 	}
       
  1369 
       
  1370 // CGifWriteCodec
       
  1371 CGifWriteCodec* CGifWriteCodec::NewL(const CGifEncoder& aEncoder)
       
  1372 	{
       
  1373 	CGifWriteCodec* self = new(ELeave) CGifWriteCodec(aEncoder);
       
  1374 	CleanupStack::PushL(self);
       
  1375 	self->ConstructL();
       
  1376 	CleanupStack::Pop(self); 
       
  1377 	return self;
       
  1378 	}
       
  1379 
       
  1380 CGifWriteCodec::CGifWriteCodec(const CGifEncoder& aEncoder)
       
  1381 	:iEncoder(aEncoder)
       
  1382 	{
       
  1383 	}
       
  1384 
       
  1385 TFrameState CGifWriteCodec::ProcessFrameL(TBufPtr8& aDst)
       
  1386 	{
       
  1387 	iDestStartPtr = CONST_CAST(TUint8*,aDst.Ptr());
       
  1388 	iDestPtr = iDestStartPtr;
       
  1389 	iDestPtrLimit = iDestPtr + aDst.MaxLength();
       
  1390 
       
  1391 	FillBufferL(*Source());
       
  1392 
       
  1393 	if (iImageComplete)
       
  1394 		{
       
  1395 		while (iBufferSize > 0)
       
  1396 			{
       
  1397 			if (!WriteBuffer())
       
  1398 				{
       
  1399 				aDst.SetLength(iDestPtr - iDestStartPtr);
       
  1400 				return EFrameIncomplete;
       
  1401 				}
       
  1402 			}
       
  1403 		TBool terminatorWritten = WriteTerminator();
       
  1404 		aDst.SetLength(iDestPtr - iDestStartPtr);
       
  1405 		
       
  1406 		return (terminatorWritten) ? EFrameComplete : EFrameIncomplete;
       
  1407 		}
       
  1408 	else
       
  1409 		{
       
  1410 		WriteBuffer();
       
  1411 		}
       
  1412 
       
  1413 	aDst.SetLength(iDestPtr - iDestStartPtr);
       
  1414 	return EFrameIncomplete;
       
  1415 	}
       
  1416 
       
  1417 void CGifWriteCodec::FillBufferL(const CFbsBitmap& aFrame)
       
  1418 	{
       
  1419 	TUint pixelsScanned =0;
       
  1420 	TBool pixelWritten = EFalse;
       
  1421 
       
  1422 	const CPalette* palette = iEncoder.Palette();
       
  1423 	while (iPos.iY < iSourceRect.iBr.iY)
       
  1424 		{
       
  1425 		TRgb pixelColor;
       
  1426 		aFrame.GetPixel(pixelColor,iPos);
       
  1427 		iPos.iX++;
       
  1428 		if (iPos.iX == iSourceRect.iBr.iX)
       
  1429 			{
       
  1430 			iPos.iX = iSourceRect.iTl.iX;
       
  1431 			iPos.iY++;
       
  1432 			}
       
  1433 		TUint8 nextColorIndex;
       
  1434 		if (palette)
       
  1435 			{
       
  1436 			nextColorIndex = palette->NearestIndex(pixelColor);	
       
  1437 			}
       
  1438 		else
       
  1439 			{
       
  1440 			nextColorIndex = STATIC_CAST(TUint8, pixelColor.Color256());
       
  1441 			}
       
  1442 
       
  1443 		TUint32 hashValue=0;
       
  1444 		TInt index=-1;
       
  1445 		if (!TableEntry(iWaitingCode,nextColorIndex,index,hashValue))
       
  1446 			{
       
  1447 			if(index!=KErrNotFound)
       
  1448 				{
       
  1449 				pixelWritten = ETrue;
       
  1450 				WriteData(iWaitingCode);
       
  1451 				AddToTableL(index,hashValue);
       
  1452 
       
  1453 				if (iNextFree > iNextLimit)
       
  1454 					{
       
  1455 					iCodeLength++;
       
  1456 					if (iCodeLength > KGifMaxBits)
       
  1457 						{
       
  1458 						iCodeLength=KGifMaxBits;
       
  1459 						ResetTable();
       
  1460 						}
       
  1461 					iNextLimit = 1 << iCodeLength;
       
  1462 					}
       
  1463 				}
       
  1464 			iWaitingCode = nextColorIndex;
       
  1465 			}
       
  1466 		else
       
  1467 			{
       
  1468 			iWaitingCode = iHashCode[index];	
       
  1469 			}
       
  1470 
       
  1471 		if ((iBufferFull) || ((pixelsScanned++ > KLZWLimit) && pixelWritten !=EFalse))
       
  1472 		{
       
  1473 			return;
       
  1474 		}
       
  1475 
       
  1476 	}
       
  1477 
       
  1478 
       
  1479 	if (iPos.iY == iSourceRect.iBr.iY)
       
  1480 		{
       
  1481 		if (iWaitingCode != KErrNotFound)
       
  1482 			{
       
  1483 			WriteData(iWaitingCode);
       
  1484 			}
       
  1485 		WriteData(iClearCode + 1); // End-Of-Information
       
  1486 		if (iBitOffset > 0)
       
  1487 			{
       
  1488 			iBufferSize++;
       
  1489 			iBitOffset = 0;
       
  1490 			}
       
  1491 		iCodeLength = 8;
       
  1492 		iBufferPtr++;
       
  1493 		iImageComplete = ETrue;
       
  1494 		}
       
  1495 	}
       
  1496 
       
  1497 void CGifWriteCodec::InitFrameL(TBufPtr8& aDst, const CFbsBitmap& aSource)
       
  1498 	{
       
  1499 	SetSource(&aSource);
       
  1500 
       
  1501 	iDestStartPtr = CONST_CAST(TUint8*,aDst.Ptr());
       
  1502 	iDestPtr = iDestStartPtr;
       
  1503 	iDestPtrLimit = iDestPtr + aDst.MaxLength();
       
  1504 
       
  1505 	iSourceRect = TRect(aSource.SizeInPixels());
       
  1506 	iPos.SetXY(0,0);
       
  1507 
       
  1508 	iBitsPerPixel = 8;
       
  1509 
       
  1510 	iBufferPtr = iBuffer;
       
  1511 	iBufferSize = 0;
       
  1512 
       
  1513 	iClearCode = 1 << iBitsPerPixel;
       
  1514 	iCodeLength = iBitsPerPixel + 1;
       
  1515 	iWaitingCode = -1;
       
  1516 
       
  1517 	ResetTable();
       
  1518 
       
  1519 	*iDestPtr++ = KGifImageDescriptorId; // Image Separator Header
       
  1520 	*iDestPtr++ = 0; // Coordinate Left Border
       
  1521 	*iDestPtr++ = 0; // Coordinate Left Border
       
  1522 	*iDestPtr++ = 0; // Coordinate Top Border
       
  1523 	*iDestPtr++ = 0; // Coordinate Top Border
       
  1524 	*iDestPtr++ = TUint8(iSourceRect.Width());
       
  1525 	*iDestPtr++ = TUint8(iSourceRect.Width() >> 8);
       
  1526 	*iDestPtr++ = TUint8(iSourceRect.Height());
       
  1527 	*iDestPtr++ = TUint8(iSourceRect.Height() >> 8);
       
  1528 	*iDestPtr++ = 0; // Flags
       
  1529 
       
  1530 	*iDestPtr++ = TUint8(iCodeLength - 1); // Initial Code Length - 1
       
  1531 
       
  1532 	aDst.SetLength(iDestPtr - iDestStartPtr);
       
  1533 	}
       
  1534 
       
  1535 void CGifWriteCodec::AddToTableL(TInt aIndex, TUint32 aHashValue)
       
  1536 	{
       
  1537 	ASSERT(aIndex<KGifHashTableSize);
       
  1538 	ASSERT(iNextFree<=KGifConversionTableSize);
       
  1539 	iHashCode[aIndex] = static_cast<TInt16>(iNextFree++);
       
  1540 	iHashValue[aIndex] = aHashValue;
       
  1541 	}
       
  1542 
       
  1543 // The hash algoritm use open addressing double hashing (no chaining)
       
  1544 // on the prefix code / suffix character combination. A variant of Knuth's
       
  1545 // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
       
  1546 // secondary probe.
       
  1547 TBool CGifWriteCodec::TableEntry(TInt16 aWaitingCode, TUint8 aNewCode, TInt& aIndex, TUint32& aHashValue)
       
  1548 	{
       
  1549 	TInt offset;
       
  1550 
       
  1551 	ASSERT(aWaitingCode>=KErrNotFound && aWaitingCode<KGifConversionTableSize);
       
  1552 
       
  1553 	aIndex = KErrNotFound;
       
  1554 
       
  1555 	//Very first code
       
  1556 	if(aWaitingCode==KErrNotFound)
       
  1557 		return EFalse;
       
  1558 
       
  1559 	aIndex = static_cast<TInt>(aNewCode<<(KGifMaxBits-8)) + aWaitingCode;
       
  1560 	if(aIndex>=KGifHashTableSize)
       
  1561 		aIndex -= KGifHashTableSize;
       
  1562 	ASSERT(aIndex < KGifHashTableSize);
       
  1563 
       
  1564 	//hash function
       
  1565 	aHashValue = static_cast<TUint32>(aWaitingCode<<8)|aNewCode;
       
  1566 
       
  1567 	if(iHashCode[aIndex]==KErrNotFound) //slot is empty
       
  1568 		return EFalse;
       
  1569 
       
  1570 	//slot has an entry
       
  1571 	if(iHashValue[aIndex]==aHashValue) //symbol already in table
       
  1572 		return ETrue;
       
  1573 
       
  1574 	if(aIndex==0)	// secondary hash (after G. Knott)
       
  1575 		offset = 1; 
       
  1576 	else
       
  1577 		offset = KGifHashTableSize - aIndex;
       
  1578 
       
  1579 	FOREVER
       
  1580 		{
       
  1581 		aIndex -= offset;
       
  1582 		if(aIndex<0)
       
  1583 			aIndex += KGifHashTableSize;
       
  1584 
       
  1585 		if(iHashCode[aIndex]==KErrNotFound)
       
  1586 			return EFalse; //slot is empty
       
  1587 
       
  1588 		if(iHashValue[aIndex]==aHashValue) //symbol already in table
       
  1589 			return ETrue;
       
  1590 		}
       
  1591 	}
       
  1592 
       
  1593 void CGifWriteCodec::ResetTable()
       
  1594 	{
       
  1595 	WriteData(iClearCode); // Send reset code
       
  1596 
       
  1597 	iNextFree = iClearCode + 2;
       
  1598 	iCodeLength = iBitsPerPixel + 1;
       
  1599 	iNextLimit = 1 << iCodeLength;
       
  1600 
       
  1601 	for (TInt index = 0; index < KGifHashTableSize; index++)
       
  1602 		iHashCode[index] = KErrNotFound;
       
  1603 	}
       
  1604 
       
  1605 void CGifWriteCodec::WriteData(TInt aIndex)
       
  1606 	{
       
  1607 	aIndex <<= iBitOffset;
       
  1608 	iBufferPtr[0] |= TUint8(aIndex);
       
  1609 	iBufferPtr[1] |= TUint8(aIndex >> 8);
       
  1610 	iBufferPtr[2] |= TUint8(aIndex >> 16);
       
  1611 
       
  1612 	TInt newBitOffset = iBitOffset + iCodeLength;
       
  1613 	iBitOffset = newBitOffset & 7;
       
  1614 	TInt byteOffset = newBitOffset >> 3;
       
  1615 	iBufferPtr += byteOffset;
       
  1616 	iBufferSize += byteOffset;
       
  1617 
       
  1618 	if (iBufferSize >= KGifBlockSize)
       
  1619 		{
       
  1620 		ASSERT(iBufferSize <= KGifBufferSize);
       
  1621 		iBufferFull = ETrue;
       
  1622 		}
       
  1623 	}
       
  1624 
       
  1625 TBool CGifWriteCodec::WriteBuffer()
       
  1626 	{
       
  1627 	ASSERT(iBufferSize <= KGifBufferSize);
       
  1628 	if (iBufferSize == 0)
       
  1629 		return ETrue;
       
  1630 
       
  1631 	TInt blockSize = Min(KGifBlockSize,iBufferSize);
       
  1632 	if (iDestPtrLimit - iDestPtr < blockSize + 1)
       
  1633 		return EFalse;
       
  1634 
       
  1635 	*iDestPtr++ = STATIC_CAST(TUint8,blockSize);
       
  1636 	Mem::Copy(iDestPtr,iBuffer,blockSize);
       
  1637 	iDestPtr += blockSize;
       
  1638 	iBufferFull = EFalse;
       
  1639 
       
  1640 	iBufferSize -= blockSize;
       
  1641 	iBufferPtr = iBuffer + iBufferSize;
       
  1642 
       
  1643 	TInt bitBufferSize = iBufferSize;
       
  1644 	if (iBitOffset)
       
  1645 		bitBufferSize++;
       
  1646 	Mem::Copy(iBuffer,&iBuffer[blockSize],bitBufferSize);
       
  1647 	Mem::FillZ(iBuffer + bitBufferSize,KGifBufferSize - bitBufferSize);
       
  1648 
       
  1649 	return ETrue;
       
  1650 	}
       
  1651 
       
  1652 TBool CGifWriteCodec::WriteTerminator()
       
  1653 	{
       
  1654 	if (iDestPtrLimit - iDestPtr < 2)
       
  1655 		return EFalse;
       
  1656 
       
  1657 	*iDestPtr++ = TUint8(0);
       
  1658 	*iDestPtr++ = TUint8(KGifTerminatorId);
       
  1659 	return ETrue;
       
  1660 	}