ImagePrint/ImagePrintEngine/DeviceProtocols/xhtmlfilecomposer/src/cxhtmlfilecomposer.cpp
/*
* 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 <imageconversion.h>
#ifdef _DEBUG
#include <driveinfo.h>
#include <pathinfo.h>
#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<CImageInfo>& 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<TSizeReal> 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<KDefaultRealWidth> 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<TSizeReal>& 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<TSizeReal>& 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<TSizeReal>& 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