sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32\sfile\sf_pgcompr.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include "sf_std.h" sl@0: #include "sf_ldr.h" sl@0: #include sl@0: #include "sf_image.h" sl@0: #include sl@0: #include sl@0: #include "sf_cache.h" sl@0: sl@0: #include "sf_pgcompr.h" sl@0: sl@0: extern TInt BytePairDecompress(TUint8* /*dst*/, TInt /*dstSize*/, TUint8* /*src*/, TInt /*srcSize*/, TUint8*& /*srcNext*/); sl@0: sl@0: sl@0: // CBytePairReader - reading from in-memory buffer sl@0: sl@0: sl@0: CBytePairReader* CBytePairReader::NewLC(TUint8* aBuffer, TUint32 aLength) sl@0: { sl@0: CBytePairReader* reader = new (ELeave) CBytePairReader(aBuffer, aLength); sl@0: CleanupStack::PushL(reader); sl@0: return reader; sl@0: } sl@0: sl@0: sl@0: CBytePairReader::CBytePairReader(TUint8* aBuffer, TUint32 aLength) sl@0: : iNextPage(aBuffer), iBytesLeft(aLength) sl@0: { sl@0: } sl@0: sl@0: sl@0: void CBytePairReader::SeekForwardL(TUint aBytes) sl@0: { sl@0: if (iBytesLeft < aBytes) sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: iNextPage += aBytes; sl@0: iBytesLeft -= aBytes; sl@0: } sl@0: sl@0: sl@0: void CBytePairReader::ReadInTableL() sl@0: { sl@0: if (KIndexTableHeaderSize > iBytesLeft) sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: Mem::Copy(&iHeader, iNextPage, KIndexTableHeaderSize); sl@0: iNextPage += KIndexTableHeaderSize; sl@0: iBytesLeft -= KIndexTableHeaderSize; sl@0: sl@0: __IF_DEBUG(Printf("numberOfPages:%d", iHeader.iNumberOfPages)); sl@0: sl@0: TUint size = iHeader.iNumberOfPages * sizeof(TUint16); sl@0: if (size > iBytesLeft) sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: // coverity[buffer_alloc] sl@0: iIndexTable = new (ELeave) TUint16[size/sizeof(TUint16)]; sl@0: Mem::Copy(iIndexTable, iNextPage, size); sl@0: iNextPage += size; sl@0: iBytesLeft -= size; sl@0: } sl@0: sl@0: sl@0: void CBytePairReader::ReleaseTable() sl@0: { sl@0: delete[] iIndexTable; sl@0: iIndexTable = NULL; sl@0: } sl@0: sl@0: sl@0: TUint CBytePairReader::GetPageL(TUint aPageNum, TUint8* aTarget, TInt aLength, TMemoryMoveFunction aMemMoveFn) sl@0: { sl@0: if (iIndexTable[aPageNum] > iBytesLeft) sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: iBytesLeft -= iIndexTable[aPageNum]; sl@0: aLength = Min(aLength, KBytePairPageSize); sl@0: sl@0: TInt size; sl@0: TUint8* nextPage; sl@0: sl@0: if (aMemMoveFn) sl@0: size = BytePairDecompress(iPageBuf, aLength, iNextPage, iIndexTable[aPageNum], nextPage); sl@0: else sl@0: size = BytePairDecompress(aTarget, aLength, iNextPage, iIndexTable[aPageNum], nextPage); sl@0: sl@0: User::LeaveIfError(size); sl@0: if (size != aLength) sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: if (iNextPage + iIndexTable[aPageNum] != nextPage) sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: sl@0: // If a memmove() was provided, use that to copy the data to its final target sl@0: if (aMemMoveFn) sl@0: aMemMoveFn(aTarget, iPageBuf, size); sl@0: sl@0: iNextPage = nextPage; sl@0: return size; sl@0: } sl@0: sl@0: sl@0: TUint CBytePairReader::DecompressPagesL(TUint8* aTarget, TInt aLength, TMemoryMoveFunction aMemMoveFn) sl@0: { sl@0: TUint decompressedSize = 0; sl@0: sl@0: ReadInTableL(); sl@0: sl@0: for (TUint curPage = 0; curPage < iHeader.iNumberOfPages; ++curPage) sl@0: { sl@0: TUint size = GetPageL(curPage, aTarget, aLength, aMemMoveFn); sl@0: sl@0: decompressedSize += size; sl@0: aTarget += size; sl@0: aLength -= size; sl@0: sl@0: __IF_DEBUG(Printf("decomp page size:%d\n", size )); sl@0: } sl@0: sl@0: __IF_DEBUG(Printf("decompressedSize:%d", decompressedSize)); sl@0: sl@0: ReleaseTable(); sl@0: sl@0: return decompressedSize; sl@0: } sl@0: sl@0: sl@0: void CBytePairReader::GetPageOffsetsL(TInt32 aInitialOffset, TInt& aPageCount, TInt32*& aPageOffsets) sl@0: { sl@0: ReadInTableL(); sl@0: aPageCount = iHeader.iNumberOfPages; sl@0: aPageOffsets = new (ELeave) TInt32[aPageCount+1]; sl@0: sl@0: TInt bytes = aInitialOffset + KIndexTableHeaderSize + aPageCount * sizeof(TUint16); sl@0: for (TInt i = 0; i < aPageCount; ++i) sl@0: { sl@0: aPageOffsets[i] = bytes; sl@0: bytes += iIndexTable[i]; sl@0: } sl@0: aPageOffsets[aPageCount] = bytes; sl@0: sl@0: ReleaseTable(); sl@0: } sl@0: sl@0: sl@0: // CBytePairFileReader - reading from file sl@0: sl@0: sl@0: CBytePairFileReader* CBytePairFileReader::NewLC(RFile& aFile) sl@0: { sl@0: CBytePairFileReader* reader = new (ELeave) CBytePairFileReader(aFile); sl@0: CleanupStack::PushL(reader); sl@0: return reader; sl@0: } sl@0: sl@0: sl@0: CBytePairFileReader::CBytePairFileReader(RFile& aFile) sl@0: : CBytePairReader(NULL, 0), iFile(aFile) sl@0: { sl@0: } sl@0: sl@0: sl@0: CBytePairFileReader::~CBytePairFileReader() sl@0: { sl@0: ReleaseTable(); sl@0: } sl@0: sl@0: sl@0: void CBytePairFileReader::SeekForwardL(TUint aBytes) sl@0: { sl@0: TInt bytes = aBytes; sl@0: User::LeaveIfError(iFile.Seek(ESeekCurrent, bytes)); sl@0: } sl@0: sl@0: sl@0: void CBytePairFileReader::ReadInTableL() sl@0: { sl@0: TPtr8 header((TUint8*)&iHeader, KIndexTableHeaderSize); sl@0: User::LeaveIfError(iFile.Read(header, KIndexTableHeaderSize)); sl@0: if (header.Length() != (TInt)KIndexTableHeaderSize) sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: sl@0: __IF_DEBUG(Printf("numberOfPages:%d", iHeader.iNumberOfPages)); sl@0: sl@0: TInt size = iHeader.iNumberOfPages * sizeof(TUint16); sl@0: iIndexTable = new (ELeave) TUint16[size/sizeof(TUint16)]; sl@0: TPtr8 indexTable((TUint8*)iIndexTable, size); sl@0: User::LeaveIfError(iFile.Read(indexTable, size)); sl@0: if (indexTable.Length() != size) sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: } sl@0: sl@0: sl@0: TUint CBytePairFileReader::DecompressPagesL(TUint8* aTarget, TInt aLength, TMemoryMoveFunction aMemMoveFn) sl@0: { sl@0: TUint decompressedSize = 0; sl@0: sl@0: ReadInTableL(); sl@0: sl@0: TUint curPage = 0; sl@0: while (curPage < iHeader.iNumberOfPages) sl@0: { sl@0: TUint bytes = 0; sl@0: TUint pages = 0; sl@0: while (curPage + pages < iHeader.iNumberOfPages && sl@0: bytes + iIndexTable[curPage+pages] < sizeof(iBuffer)) sl@0: { sl@0: bytes += iIndexTable[curPage+pages]; sl@0: ++pages; sl@0: } sl@0: if(!bytes) sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: TPtr8 data(iBuffer, bytes); sl@0: User::LeaveIfError(iFile.Read(data, bytes)); sl@0: if (data.Length() != (TInt)bytes) sl@0: LEAVE_FAILURE(KErrCorrupt); sl@0: iNextPage = iBuffer; sl@0: iBytesLeft = bytes; sl@0: sl@0: for (; pages; ++curPage, --pages) sl@0: { sl@0: TUint size = GetPageL(curPage, aTarget, aLength, aMemMoveFn); sl@0: sl@0: decompressedSize += size; sl@0: aTarget += size; sl@0: aLength -= size; sl@0: sl@0: __IF_DEBUG(Printf("decomp page size:%d\n", size )); sl@0: } sl@0: } sl@0: sl@0: __IF_DEBUG(Printf("decompressedSize:%d", decompressedSize)); sl@0: sl@0: ReleaseTable(); sl@0: sl@0: return decompressedSize; sl@0: }