diff -r 159fc2f68139 -r d59c248c9d36 ImagePrint/ImagePrintEngine/DeviceProtocols/xhtmlfilecomposer/src/cxhtmlfilecomposer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ImagePrint/ImagePrintEngine/DeviceProtocols/xhtmlfilecomposer/src/cxhtmlfilecomposer.cpp Wed Sep 01 12:30:38 2010 +0100 @@ -0,0 +1,992 @@ +/* +* Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Defines the CXhtmlFileComposer class. +* +*/ + + +#include + +#ifdef _DEBUG +#include +#include +#endif + +#include "cxhtmlfilecomposer.h" +#include "printcapabilitycodes.h" +#include "cxfclogger.h" + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::NewL +// +//-------------------------------------------------------------------------------------------- +EXPORT_C CXhtmlFileComposer* CXhtmlFileComposer::NewL(const TDesC& aPath) + { + CXhtmlFileComposer *self = NewLC(aPath); + CleanupStack::Pop(); // self + + return self; + } + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::NewLC +// +//-------------------------------------------------------------------------------------------- +EXPORT_C CXhtmlFileComposer* CXhtmlFileComposer::NewLC(const TDesC& aPath) + { + CXhtmlFileComposer *self = new (ELeave) CXhtmlFileComposer(); + CleanupStack::PushL(self); + + if(0 >= aPath.Length()) + { + self->ConstructL(KXFCDefaultResultPath()); + } + else + { + self->ConstructL(aPath); + } + + return self; + } + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::CreateXhtmlFileL +// +//-------------------------------------------------------------------------------------------- +EXPORT_C void CXhtmlFileComposer::CreateXhtmlFileL(const RArray& aImages, const TInt aLayout, + const TInt aPaperSize, const TInt /*aQuality*/, + const TDesC& aXhtmlPrintFile,TInt& aPageCount, TBool aDataFile) +{ + LOG("[CXhtmlFileComposer]\t WriteJobControlFileL"); + + // Get page and layout related data + PageData(aPaperSize); + + RArray positions; + CleanupClosePushL(positions); + LayoutData(aLayout, positions); + + ReadTemplateFileL(); + + // init counter variables + aPageCount = 0; + TInt posIx = 0; + TInt copies = 0; + TInt currentImgNum = 0; + TInt imageCount = aImages.Count(); + + // loop for images + for(TInt imgIx = 0; imgIx < aImages.Count(); imgIx++) + { + /**** Handle copies ****/ + copies = aImages[imgIx].Copies(); + imageCount += copies - 1; // decrease current image from copies + + // Create template blocks for each copy + while(1 <= copies && imageCount > currentImgNum) + { + AddPageL(currentImgNum, posIx, aPageCount); + AddTemplateStringL(iFrameTemplate, KFrame()); + + // add frame position template once per position for all pages + if(1 == aPageCount) + { + AddTemplateStringL(iPositionTemplate, KFramePosition()); + ComposePositionL(posIx, positions); + } + ComposeTemplateL(posIx+1, KPosId()); + --copies; + ++currentImgNum; + } + + // add image details + AddTemplateStringL(iImageTemplate, KImgDetails()); + ComposeTemplateL(1+imgIx, KDetId()); + + // Get correct name for the image + TFileName8 imageName; + GetImageNameL(aImages[imgIx], imageName, aDataFile); + + /**** Image size and orientation ****/ + TSizeReal imageSize(0,0); + TBool framePortrait = EFalse; + + SizeAndOrientationL(aImages[imgIx], imageSize, framePortrait); + + /**** Image scaling & cropping ****/ + TSizeReal scaledSize; + GetRatioL(scaledSize, imageSize); + + // Turn frame and scaled size in correct orientation again + if(framePortrait != iImagePortrait) + { + scaledSize.Reverse(); + iImageFrame.Reverse(); + } + + ComposeFileL(imageName, scaledSize, aDataFile); + + }// End of loop for images + CleanupStack::PopAndDestroy( &positions ); + + // Compose the correct unit in file + ComposeUnitL(); + + /**** Create result file ****/ + RFile newFile; + CleanupClosePushL( newFile ); + User::LeaveIfError( newFile.Replace( iFsSession, aXhtmlPrintFile, EFileWrite) ); + newFile.Write( FinalizeBufferL() ); + CleanupStack::PopAndDestroy( &newFile ); +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::~CXhtmlFileComposer +// +//-------------------------------------------------------------------------------------------- +EXPORT_C CXhtmlFileComposer::~CXhtmlFileComposer() +{ + iFsSession.Close(); + if(iFileBuf) + delete iFileBuf; +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::UnitToPixel +// +//-------------------------------------------------------------------------------------------- +EXPORT_C TReal CXhtmlFileComposer::UnitToPixel(TReal aValue) +{ + TReal tmp = aValue; + if(EUAMillis == iPaperType) + tmp = aValue/(TReal)KInchDivider; + + tmp = tmp*(TReal)KDpiDivider; + + return tmp; +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::UnitToPixel +// +//-------------------------------------------------------------------------------------------- +EXPORT_C TSizeReal CXhtmlFileComposer::UnitToPixel(TSizeReal aValue) +{ + TSizeReal tmp = aValue; + if(EUAMillis == iPaperType) + tmp = aValue/(TReal)KInchDivider; + + tmp = tmp*(TReal)KDpiDivider; + + return tmp; +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::PixelToUnit +// +//-------------------------------------------------------------------------------------------- +EXPORT_C TReal CXhtmlFileComposer::PixelToUnit(TReal aValue) +{ + TReal tmp = aValue/(TReal)KDpiDivider; + if(EUAMillis == iPaperType) + tmp = tmp*(TReal)KInchDivider; + + return tmp; +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::PixelToUnit +// +//-------------------------------------------------------------------------------------------- +EXPORT_C TSizeReal CXhtmlFileComposer::PixelToUnit(TSizeReal aValue) +{ + TSizeReal tmp = aValue/(TReal)KDpiDivider; + if(EUAMillis == iPaperType) + tmp = tmp*(TReal)KInchDivider; + + return tmp; +} + +// PROTECTED + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::ConstructL +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::ConstructL(const TDesC& aPath) +{ + LOG("[CXhtmlFileComposer::ConstructL]\t"); + + User::LeaveIfError( iFsSession.Connect() ); + iFsSession.SetSessionPath( aPath ); + iFsSession.MkDirAll( aPath ); + + iPaperSize.SetSize(0,0); + iPaperType = 0; + iPageMargin = 0; + iImageFrame.SetSize(0,0); + iFileBuf = NULL; + iImagesPerPage = 0; + iImagePortrait=EFalse; + iPagePortrait = ETrue; + iPageTemplate.Copy(KNullDesC8()); + iFrameTemplate.Copy(KNullDesC8()); + iPositionTemplate.Copy(KNullDesC8()); + iImageTemplate.Copy(KNullDesC8()); + + LOG("[CXhtmlFileComposer::ConstructL]\t Done."); +} + +// PRIVATE + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::CXhtmlFileComposer +// +//-------------------------------------------------------------------------------------------- +CXhtmlFileComposer::CXhtmlFileComposer() +{ +} + + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::GetRatioL +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::GetRatioL(TSizeReal &aNewSize, TSizeReal aImageSize) +{ + LOG("[CXhtmlFileComposer::GetRatioL]\t ********************************"); + + TRealX margin = 0; + TXhtmlSetting marginStr, tmpStr; + + LOG2("[CXhtmlFileComposer::GetRatioL]\t aImageSize: %fx%f", PixelToUnit(aImageSize.iWidth), PixelToUnit(aImageSize.iHeight)); + LOG2("[CXhtmlFileComposer::GetRatioL]\t iImageFrame: %fx%f", PixelToUnit(iImageFrame.iWidth), PixelToUnit(iImageFrame.iHeight)); + LOG2("[CXhtmlFileComposer::GetRatioL]\t image ratio: %f vs. frame ratio %f", aImageSize.Ratio(), iImageFrame.Ratio()); + + TReal relativeRatio = aImageSize.Ratio() / iImageFrame.Ratio(); + LOG2("[CXhtmlFileComposer::GetRatioL]\t relativeRatio: %f, iPageMargin %f", relativeRatio, iPageMargin); + + // crop borderless: if iPageMargin == 0, the margin must be negative + if((1 < relativeRatio && iPageMargin) || (1 > relativeRatio && !iPageMargin)) + { + LOG("[CXhtmlFileComposer::GetRatioL]\t *Match width*"); + aNewSize.SetSize(iImageFrame.iWidth, iImageFrame.iWidth/aImageSize.Ratio()); + margin = (iImageFrame.iHeight-aNewSize.iHeight)/2; + + if((!iPagePortrait && !iPageMargin && iImagePortrait) || iPagePortrait) + marginStr.Copy(KTop()); + else + marginStr.Copy(KLeft()); + } + else + { + LOG("[CXhtmlFileComposer::GetRatioL]\t *Match height*"); + aNewSize.SetSize(iImageFrame.iHeight*aImageSize.Ratio(), iImageFrame.iHeight); + margin = (iImageFrame.iWidth-aNewSize.iWidth)/2; + + if((!iPagePortrait && !iPageMargin && iImagePortrait) || iPagePortrait) + marginStr.Copy(KLeft()); + else + marginStr.Copy(KTop()); + } + + FormatReal(PixelToUnit(margin), tmpStr); + marginStr.Append(tmpStr); + + LOG2("[CXhtmlFileComposer::GetRatioL]\t aNewSize: %fx%f", PixelToUnit(aNewSize.iWidth), PixelToUnit(aNewSize.iHeight)); + LOG81("[CXhtmlFileComposer::GetRatioL]\t \"%S\"", &marginStr); + + // margin not needed anymore: compose margin into file buffer + ComposeTemplateL(marginStr, KImgMargin()); + LOG("[CXhtmlFileComposer::GetRatioL]\t ********************************"); +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::ComposeUnitL +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::ComposeUnitL() +{ + LOG("[CXhtmlFileComposer]\t ComposeUnit"); + + if(EUAMillis == iPaperType) + { + _LIT8(KMm, "mm"); + ComposeTemplateL(KMm(), KUnit()); + } + else + { + _LIT8(KIn, "in"); + ComposeTemplateL(KIn(), KUnit()); + } +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::ComposeFile +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::ComposeFileL(const TDes8 &aImageName, TSizeReal aImgSize, TBool aDataFile) +{ + LOG("[CXhtmlFileComposer]\t ComposeFile"); + + // Format page settings in file + TXhtmlSetting pageWidthStr, pageHeightStr, pageMarginStr; + + FormatReal(PixelToUnit(iPaperSize.iWidth), pageWidthStr); + ComposeTemplateL(pageWidthStr, KPageWidth()); + + FormatReal(PixelToUnit(iPaperSize.iHeight), pageHeightStr); + ComposeTemplateL(pageHeightStr, KPageHeight()); + + FormatReal(iPageMargin, pageMarginStr); + ComposeTemplateL(pageMarginStr, KPageMargin()); + + // Format image frame settings in file + TXhtmlSetting imgFrameWidthStr, imgFrameHeightStr; + + FormatReal(PixelToUnit(iImageFrame.iWidth), imgFrameWidthStr); + ComposeTemplateL(imgFrameWidthStr, KImgFrameWidth()); + + FormatReal(PixelToUnit(iImageFrame.iHeight), imgFrameHeightStr); + ComposeTemplateL(imgFrameHeightStr, KImgFrameHeight()); + + // Format image settings in file + TXhtmlSetting imgWidthStr, imgHeightStr; + + FormatReal(PixelToUnit(aImgSize.iWidth), imgWidthStr); + ComposeTemplateL(imgWidthStr, KImgWidth()); + + FormatReal(PixelToUnit(aImgSize.iHeight), imgHeightStr); + ComposeTemplateL(imgHeightStr, KImgHeight()); + +/////////// + HBufC8* data = NULL; + if(aDataFile) + { + + TFileName imgFile; + imgFile.Copy(aImageName); + + LOG("[CXhtmlFileComposer]\t ComposeFileL - read image data"); + // Open the template file and read it into buffer + RFile file; + CleanupClosePushL(file); + + User::LeaveIfError( file.Open( iFsSession, imgFile, EFileRead | EFileShareReadersOnly ) ); + LOG("[CXhtmlFileComposer]\t ComposeFileL - file opened"); + + TInt fileSize = 0; + User::LeaveIfError( file.Size(fileSize) ); + LOG1("[CXhtmlFileComposer]\t ComposeFileL - file size %d",fileSize); + + _LIT8(KDataUrl, "data:image/jpeg;base64,"); + + data = HBufC8::NewLC(fileSize + KDataUrl().Length()); + TPtr8 dataPtr( data->Des() ); + + dataPtr.Zero(); + file.Read(dataPtr); + + dataPtr.Insert(0, KDataUrl()); + + ComposeTemplateL(dataPtr, KImgName()); + LOG("[CXhtmlFileComposer]\t ComposeFileL - file composed"); + + CleanupStack::PopAndDestroy(2); // data, file + } +/////////// + else + { + // Format image name in file + ComposeTemplateL(aImageName, KImgName()); + } +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::ComposeTemplateL +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::ComposeTemplateL(const TInt aValue, const TDesC8 &aTemplate) +{ +// LOG("[CXhtmlFileComposer]\t ComposeTemplateL"); + + TBuf8 valueStr; + valueStr.Zero(); + valueStr.AppendNum(aValue); + + ComposeTemplateL(valueStr, aTemplate); +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::ComposeTemplateL +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::ComposeTemplateL(const TDesC8 &aStr, const TDesC8 &aTemplate) +{ +// LOG("[CXhtmlFileComposer]\t ComposeTemplateL"); + + User::LeaveIfNull(iFileBuf); + + TInt pos = iFileBuf->Find(aTemplate); + while(KErrNotFound != pos) + { + TInt requiredSize = iFileBuf->Des().Length() + aStr.Length(); + if(iFileBuf->Des().MaxLength() < requiredSize) + { + iFileBuf = iFileBuf->ReAllocL(requiredSize); + } + iFileBuf->Des().Replace(pos, aTemplate.Length(), aStr); + pos = iFileBuf->Find(aTemplate); + } +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::SetPageTypeL +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::SetPageTypeL() +{ + LOG("[CXhtmlFileComposer]\t SetPageTypeL"); + + User::LeaveIfNull(iFileBuf); + + TXhtmlSetting pageType(KPageFirsts()); + + TInt pos = iFileBuf->Find(KPageType()); + if(KErrNotFound >= pos) + User::Leave(KErrCorrupt); + + while(KErrNotFound != pos) + { + // check if next exists to assign correct page type in template + TPtrC8 tmpBuf; + tmpBuf.Set(iFileBuf->Mid(pos+KPageType().Length())); + + if(KErrNotFound == tmpBuf.Find(KPageType())) + pageType.Copy(KPageLast()); + + // replace correct page type in first found position + TInt requiredSize = iFileBuf->Des().Length() + pageType.Length(); + if(iFileBuf->Des().MaxLength() < requiredSize) + { + iFileBuf = iFileBuf->ReAllocL(requiredSize); + } + iFileBuf->Des().Replace(pos, KPageType().Length(), pageType); + pos = iFileBuf->Find(KPageType()); + } +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::FinalizeBufferL +// +//-------------------------------------------------------------------------------------------- +TPtrC8 CXhtmlFileComposer::FinalizeBufferL() +{ + LOG("[CXhtmlFileComposer]\t FinalizeBufferL"); + + User::LeaveIfNull(iFileBuf); + + SetPageTypeL(); + + // Remove markers from the buffer + TInt pos = iFileBuf->Find(KPage()); + if(KErrNotFound != pos) + iFileBuf->Des().Delete(pos, KPage().Length()); + + pos = iFileBuf->Find(KFrame()); + if(KErrNotFound != pos) + iFileBuf->Des().Delete(pos, KFrame().Length()); + + pos = iFileBuf->Find(KImgDetails()); + if(KErrNotFound != pos) + iFileBuf->Des().Delete(pos, KImgDetails().Length()); + + pos = iFileBuf->Find(KFramePosition()); + if(KErrNotFound != pos) + iFileBuf->Des().Delete(pos, KFramePosition().Length()); + + // Cut the template to the end tag + pos = iFileBuf->Find(KEndTag()); + if(KErrNotFound == pos) + User::Leave(KErrCorrupt); + + TInt dataLen = pos + KEndTag().Length(); + TPtrC8 tail = iFileBuf->Des().Left(dataLen); + + return tail; +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::PageData +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::PageData(TInt aPaperSize) +{ + LOG("[CXhtmlFileComposer]\t PageData"); + + const TSizeReal KSizeA4(210.0, 297.0); + const TSizeReal KSizeA6(105.0, 148.5); + const TSizeReal KSizeLetter(8.5, 11.0); + const TSizeReal KSize4x6(4.0, 6.0); + const TSizeReal KSize5x7(5.0, 7.0); + + switch(aPaperSize) + { + case EPrintCapabPaperSizeA4: + iPaperType = CXhtmlFileComposer::EUAMillis; + iPaperSize = UnitToPixel(KSizeA4); + iPageMargin = 3.0; + break; + case EPrintCapabPaperSizeA6: + iPaperType = CXhtmlFileComposer::EUAMillis; + iPaperSize = UnitToPixel(KSizeA6); + iPageMargin = 3.0; + break; + case EPrintCapabPaperSizeLetter: + iPaperType = CXhtmlFileComposer::EUAInches; + iPaperSize = UnitToPixel(KSizeLetter); + iPageMargin = 0.12; + break; + case EPrintCapabPaperSize5x7: + iPaperType = CXhtmlFileComposer::EUAInches; + iPaperSize = UnitToPixel(KSize5x7); + iPageMargin = 0.12; + break; + case EPrintCapabPaperSizeAuto: + case EPrintCapabPaperSizeSticker: + case EPrintCapabPaperSize4x6: + default: + iPaperType = CXhtmlFileComposer::EUAInches; + iPaperSize = UnitToPixel(KSize4x6); + iPageMargin = 0.12; + break; + } +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::LayoutData +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::LayoutData(TInt aLayout, RArray& aPositions) +{ + LOG1("[CXhtmlFileComposer::LayoutData]\t aLayout: %d", aLayout); + + TSizeReal pos(0,0); + + switch(aLayout) + { + case EPrintCapabLayout1UpBorder: + iImagesPerPage = 1; + iPagePortrait = EFalse; + CreateMatrix(1/*rows*/, 1/*columns*/, aPositions); + break; + case EPrintCapabLayout2Up: + iImagesPerPage = 2; + iPagePortrait = ETrue; + CreateMatrix(2, 1, aPositions); + break; + case EPrintCapabLayout4Up: + iImagesPerPage = 4; + iPagePortrait = EFalse; + CreateMatrix(2, 2, aPositions); + break; + case EPrintCapabLayout6Up: + iImagesPerPage = 6; + iPagePortrait = ETrue; + CreateMatrix(3, 2, aPositions); + break; + case EPrintCapabLayout9Up: + iImagesPerPage = 9; + iPagePortrait = EFalse; + CreateMatrix(3, 3, aPositions); + break; + case EPrintCapabLayout12Up: + iImagesPerPage = 12; + iPagePortrait = ETrue; + CreateMatrix(4, 3, aPositions); + break; + case EPrintCapabLayout16Up: + iImagesPerPage = 16; + iPagePortrait = EFalse; + CreateMatrix(4, 4, aPositions); + break; + case EPrintCapabLayout1Up: + case EPrintCapabLayout1UpBorderless: + default: + iImagesPerPage = 1; + iPageMargin = 0; + iImageFrame = iPaperSize; + iPagePortrait = EFalse; + aPositions.Append(pos); + break; + } +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::CreateMatrix +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::CreateMatrix(TInt aRows, TInt aColumns, RArray& aPositions) +{ + LOG("[CXhtmlFileComposer]\t CreateMatrix"); + + TSizeReal pos; + TSizeReal matrix(aColumns,aRows); + TSizeReal relativeSize(KFrameRatio, 1); + + if(!iPagePortrait) + { + matrix.Reverse(); + relativeSize.Reverse(); + } + + // count print area: paper size - margins + TSizeReal margins(matrix); + margins += 1; + margins *= UnitToPixel(iPageMargin); + LOG2("[CXhtmlFileComposer::CreateMatrix]\t margins: %fx%f", PixelToUnit(margins.iWidth), PixelToUnit(margins.iHeight)); + + TSizeReal printArea = (iPaperSize - margins); + LOG2("[CXhtmlFileComposer::CreateMatrix]\t printArea: %fx%f", PixelToUnit(printArea.iWidth), PixelToUnit(printArea.iHeight)); + + // Count frame size + + iImageFrame = printArea/matrix; + LOG2("[CXhtmlFileComposer::CreateMatrix]\t iImageFrame bef. ratio: %fx%f", PixelToUnit(iImageFrame.iWidth), PixelToUnit(iImageFrame.iHeight)); + + LOG1("[CXhtmlFileComposer::CreateMatrix]\t frame ratio: %f", iImageFrame.Ratio()); + + // force frame ratio to KFrameRatio ratio + LOG1("[CXhtmlFileComposer::CreateMatrix]\t relativeRatio: %f", relativeSize.Ratio()); + + TReal relativeRatio = relativeSize.Ratio()/iImageFrame.Ratio(); + if(1 < relativeRatio) + { + iImageFrame.iHeight /= relativeRatio; + } + else if(1 > relativeRatio) + { + iImageFrame.iWidth *= relativeRatio; + } + + LOG2("[CXhtmlFileComposer::CreateMatrix]\t iImageFrame aft. ratio: %fx%f", PixelToUnit(iImageFrame.iWidth), PixelToUnit(iImageFrame.iHeight)); + LOG1("[CXhtmlFileComposer::CreateMatrix]\t --> ratio: %f (1.3325/0.7505)", iImageFrame.Ratio()); + + // Count the empty space on page to centerise the frame set + TSizeReal frameSetSize(iImageFrame*matrix); + TSizeReal emptySpace = (printArea - frameSetSize) / 2; + + LOG2("[CXhtmlFileComposer::CreateMatrix]\t frameSetSize:\t %fx%f", PixelToUnit(frameSetSize.iWidth), PixelToUnit(frameSetSize.iHeight)); + LOG2("[CXhtmlFileComposer::CreateMatrix]\t emptySpace:\t %fx%f", PixelToUnit(emptySpace.iWidth), PixelToUnit(emptySpace.iHeight)); + + // if only one image/page, no need to calculate positions. + if(0 >= aColumns || 0 >= aRows) + { + aPositions.Append(pos); + return; + } + + emptySpace.Reverse(); + + for(TInt row = 0; row < aRows; ++row) + { + LOG1("[CXhtmlFileComposer::CreateMatrix]\t row: %d", row); + pos.iWidth = (iImageFrame.iHeight+UnitToPixel(iPageMargin)) * row; + pos.iWidth += emptySpace.iWidth; + for(TInt col = 0; col < aColumns; ++col) + { + pos.iHeight = (iImageFrame.iWidth+UnitToPixel(iPageMargin)) * col; + pos.iHeight += emptySpace.iHeight; + LOG2("[CXhtmlFileComposer::CreateMatrix]\t col: %fx%f", PixelToUnit(pos.iWidth), PixelToUnit(pos.iHeight)); + aPositions.Append(pos); + } + } +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::ReadTemplateL +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::ReadTemplateFileL() +{ + LOG("[CXhtmlFileComposer]\t ReadTemplateL"); + // Open the template file and read it into buffer + RFile templateFile; + CleanupClosePushL(templateFile); + +#ifdef _DEBUG + //_LIT(KFile, "e:\\UPnPXHTMLTemplate.xhtml"); + _LIT(KFileName, "UPnPXHTMLTemplate.xhtml"); + TInt drive; + TFileName path; + + DriveInfo::GetDefaultDrive(DriveInfo::EDefaultRemovableMassStorage, drive); + PathInfo::GetRootPath(path, drive); + path.Append(KFileName()); + + TInt e = templateFile.Open( iFsSession, path, EFileRead); + if(KErrNone != e) +#endif + { + User::LeaveIfError( templateFile.Open( iFsSession, KXHTMLTemplate(), EFileRead) ); + } + TInt fileSize = 0; + TInt err = templateFile.Size(fileSize); + if(KErrNone != err) + fileSize = KXFCMaxFileSize; + + iFileBuf = HBufC8::NewL(fileSize); + TPtr8 bufferPtr( iFileBuf->Des() ); + + bufferPtr.Zero(); + templateFile.Read(bufferPtr); + + CleanupStack::PopAndDestroy(&templateFile); + + // Separate page, frame position, image details and frame + // template elements from the template buffer + GetTemplateStringL(KPageStart(), KPageEnd(), iPageTemplate); + GetTemplateStringL(KFrameStart(), KFrameEnd(), iFrameTemplate); + GetTemplateStringL(KPositionStart(), KPositionEnd(),iPositionTemplate); + GetTemplateStringL(KImgStart(), KImgEnd(), iImageTemplate); +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::GetTemplateStringL +// +//-------------------------------------------------------------------------------------------- +TPtrC8 CXhtmlFileComposer::GetTemplateStringL(const TDesC8 &aStart, const TDesC8 &aEnd, TDes8 &aTemplate) +{ + User::LeaveIfNull(iFileBuf); + + TInt start = iFileBuf->Find(aStart); + if(KErrNotFound == start) + User::Leave(KErrCorrupt); + + TInt end = iFileBuf->Find(aEnd); + if(KErrNotFound == end) + User::Leave(KErrCorrupt); + + TPtrC8 ptr = iFileBuf->Des().Mid(start+aStart.Length(), end-start-aStart.Length()); + + if(aTemplate.MaxLength() < ptr.Length()) + User::Leave(KErrOverflow); + + aTemplate = ptr; + iFileBuf->Des().Delete(start, ptr.Length()+aStart.Length()+aEnd.Length()); + return ptr; +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::AddTemplateStringL +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::AddTemplateStringL(const TDesC8 &aTemplate,const TDesC8 &aTag) +{ + User::LeaveIfNull(iFileBuf); + + TInt pos = iFileBuf->Find(aTag); + if(KErrNotFound == pos) + User::Leave(KErrCorrupt); + + TInt requiredSize = iFileBuf->Des().Length() + aTemplate.Length(); + if(iFileBuf->Des().MaxLength() < requiredSize) + { + iFileBuf = iFileBuf->ReAllocL(requiredSize); + } + iFileBuf->Des().Insert(pos, aTemplate); +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::GetImageDataL +// +//-------------------------------------------------------------------------------------------- +TSizeReal CXhtmlFileComposer::GetImageSizeL(CImageInfo aImage) +{ + TSizeReal imageSize(0,0); + TFileName name; + aImage.GetFilePathL(name); + if(name.Compare(KNullDesC())) + { + // Test file existing + TEntry data; + TInt err = iFsSession.Entry(name, data); + User::LeaveIfError(err); + + // Get image size in pixels + CImageDecoder *id = NULL; + TRAP(err, id = CImageDecoder::FileNewL(iFsSession, name, KMimeJpeg())); + + if(KErrNone == err) + { + TFrameInfo frameInfo; + frameInfo = id->FrameInfo(); + imageSize = frameInfo.iOverallSizeInPixels; + } + + if(id) + delete id; + } + LOG2("[CXhtmlFileComposer]\t Image size: %fx%f", imageSize.iWidth, imageSize.iHeight); + return imageSize; +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::AddPageL +// +//-------------------------------------------------------------------------------------------- +TBool CXhtmlFileComposer::AddPageL(TInt aCurrentImage, TInt& aPositionIndex, TInt& aPageCount) +{ + TBool ret = EFalse; + // increase position index by default and reset it in case of new page + ++aPositionIndex; + + User::LeaveIfNull(iFileBuf); + if(0 >= iImagesPerPage) + User::Leave(KErrArgument); + + TInt modulo = aCurrentImage % iImagesPerPage; + + if(0 == modulo) + { + //delete current page's frame marker before... + TInt pos = iFileBuf->Find(KFrame()); + if(KErrNotFound != pos) + iFileBuf->Des().Delete(pos, KFrame().Length()); + + // ...add the new page template and reset position index + AddTemplateStringL(iPageTemplate, KPage()); + aPositionIndex = 0; + ++aPageCount; + ret = ETrue; + } + return ret; +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::GetImageName +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::GetImageNameL(CImageInfo aImageInfo, TDes8 &aImageName, TBool aDataFile) +{ + aImageInfo.GetEncodedUriL(aImageName); + if(0 >= aImageName.Length() || aDataFile) + { + aImageInfo.GetFilePath(aImageName); + if(0 >= aImageName.Length()) + User::Leave(KErrArgument); + } + + LOG81("[CXhtmlFileComposer]\t Image: %S", &aImageName); +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::SizeAndOrientationL +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::SizeAndOrientationL(const CImageInfo aImageInfo, TSizeReal& aImageSize, TBool& aFramePortrait) +{ + aImageSize = GetImageSizeL(aImageInfo); + + // If the size of any of the sides is zero, set the size as frame size + if(0 >= aImageSize.iWidth) + aImageSize = iImageFrame; + + // orientations + iImagePortrait = (aImageSize.iWidth < aImageSize.iHeight ? ETrue : EFalse); + aFramePortrait = (iImageFrame.iWidth < iImageFrame.iHeight ? ETrue : EFalse); + + // Set orientation in degrees + TInt orientation = KXFCZeroDeg; + if(aFramePortrait != iImagePortrait) + orientation = KXFC90Deg; + + // Set orientation in template + TXhtmlSetting orientationStr; + orientationStr.Format(KDeg(), orientation); + ComposeTemplateL(orientationStr, KImgOrientation()); + + // Set image and image frame temporarily in same orientation + if(aFramePortrait != iImagePortrait) + iImageFrame.Reverse(); +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::GetImageName +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::ComposePositionL(TInt aPositionIndex, RArray& aPositions) +{ + TSizeReal position(0,0); + if(aPositions.Count() <= aPositionIndex) + aPositionIndex = 0; + + if(0 < aPositions.Count()) + position = aPositions[aPositionIndex]; + + // Format position + TXhtmlSetting positionTopStr, positionLeftStr; + + FormatReal(PixelToUnit(position.iWidth), positionTopStr); + ComposeTemplateL(positionTopStr, KPositionTop()); + + FormatReal(PixelToUnit(position.iHeight), positionLeftStr); + ComposeTemplateL(positionLeftStr, KPositionLeft()); +} + +//-------------------------------------------------------------------------------------------- +// +// CXhtmlFileComposer::FormatReal +// +//-------------------------------------------------------------------------------------------- +void CXhtmlFileComposer::FormatReal(TRealX aNumber, TDes8& aString) +{ + TRealFormat form; + form.iPlaces = 4; + form.iPoint = TChar('.'); + form.iType = KDoNotUseTriads | KRealFormatFixed; + + aString.Num(aNumber, form); + aString.Append(KUnit()); +} + +// End of file