printingservices/printerdriversupport/src/FBSDRV.CPP
author Faisal Memon <faisal.memon@nokia.com>
Fri, 14 May 2010 15:41:33 +0100
branchNewGraphicsArchitecture
changeset 64 5c983aa672ea
parent 0 5d03bc08d59c
child 69 3365349494cc
permissions -rw-r--r--
Merge 1. Pull in cpp files in the performance enhanced Khronos RI OVG files which are newly added. I've ignored platform-specific cpp files for linux, macosx, and null operating systems because this local solution has its own platform glue (i.e. facility to target Bitmaps but no full windowing support). I've ignored sfEGLInterface.cpp because this is used as a bridge to go from EGL to Nokia's Platsim which offers an EGL service. That's not relevant to this implementation because this is ARM side code, not Intel side. I just left a comment to sfEGLInterface.cpp in case we need to pick up this later on. The current code compiles on winscw. Prior to this fix, the code works on winscw, and can launch the SVG tiger (tiger.exe). That takes about 20 seconds to render. I hope to always be able to show this icon on each commit, and the plan is for the render time to reduce with this series of submissions. On this commit, the tiger renders ok in 20 seconds.

// Copyright (c) 1997-2009 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:
//

#include "PDRSTD.H"
#include <fbs.h>
#include <bitdev.h>
#include <banddev.h>
#include <pdrstore.h>
#include "pdrtext.h"

EXPORT_C CFbsDrvDevice::CFbsDrvDevice()
	{
	__DECLARE_NAME(_S("CFbsDrvDevice"));
	}

EXPORT_C CFbsDrvDevice::~CFbsDrvDevice()
	{
	delete iFbsTypefaceStore;
	delete iGenTypefaceFontsList;
	delete iGenTypefaceFontsType;
	}

/** Creates a font from those available in the printer device's 
typeface store that most closely matches a font specification. 

When the font is no longer needed, call ReleaseFont().

This function is replaced by GetNearestFontToDesignHeightInTwips()

@param aFont On return, points to the font which most closely matches the 
specified font.
@param aFontSpec An absolute font specification. Its iHeight member is 
interpreted as being in twips.
@return KErrNone if successful; otherwise, another one of the system-wide error 
codes.
@deprecated */
EXPORT_C TInt CFbsDrvDevice::GetNearestFontInTwips(CFont*& aFont, const TFontSpec& aFontSpec)
	{
	return GetNearestFontToDesignHeightInTwips(aFont, aFontSpec);
	}

/** Creates a font from those available in the printer device's 
typeface store that most closely matches a font specification. 

When the font is no longer needed, call ReleaseFont().

This function replaces GetNearestFontInTwips()

@param aFont On return, points to the font which most closely matches the 
specified font.
@param aFontSpec An absolute font specification. Its iHeight member is 
interpreted as being in twips.
@return KErrNone if successful; otherwise, another one of the system-wide error 
codes. */
EXPORT_C TInt CFbsDrvDevice::GetNearestFontToDesignHeightInTwips(CFont *&aFont, const TFontSpec &aFontSpec)
	{
    TRAPD(errCode, LoadTypeFaceListL());
	if(errCode != KErrNone)
		{
		return errCode;
		}
	TInt count = iGenTypefaceFontsList->Count();
	TInt count_fbs = 0;
	TTypefaceSupport support ;				// holds typeface from iGenTypefaceFontsList
	TTypeface typeface = aFontSpec.iTypeface;	// holds typeface from aFontSpec
	TBuf<KMaxTypefaceNameLength> support_name;
	TBuf<KMaxTypefaceNameLength> typeface_name;
	TBuf<KMaxTypefaceNameLength> aname;
	typeface_name.Copy(typeface.iName);
	TInt loop;
	TInt found = 0;
	TInt listindex = 0;
	TTypefaceSupport lsupport;
	// Try to match specified font name with name from typeface font list
	for (loop = 0; (loop < count) && (typeface.iName.CompareF(support.iTypeface.iName)); loop++)
		{
		TInt index = iGenTypefaceFontsList->At(loop);
		TInt type = iGenTypefaceFontsType->At(loop);
		if (type == 0)
			{
			iTypefaceStore->TypefaceSupport(support,index);
			support_name.Copy(support.iTypeface.iName);
			}
		else if(type == 1)
			{
			iFbsTypefaceStore->TypefaceSupport(support,index);
			if(support.iIsScalable)
				{
				count_fbs++;
				support_name.Copy(support.iTypeface.iName);
				}
			}
		if (!typeface.iName.CompareF(support.iTypeface.iName))
			{
			typeface_name.Copy(support.iTypeface.iName);
			found = 1;
			}
		}

	if (found)
		{
		if (loop <= iFbsTypefaceCount)
			{
			TFontSpec fontspec(aFontSpec);
			fontspec.iTypeface=support.iTypeface;
			return iFbsTypefaceStore->GetNearestFontToDesignHeightInTwips(aFont, fontspec);
			}
		else if (loop <= count)
			{
			TFontSpec fontspec(aFontSpec);
			fontspec.iTypeface=support.iTypeface;
			return iTypefaceStore->GetNearestFontToDesignHeightInTwips(aFont, fontspec);
			}
		}
	else 
		{
		if (!typeface.IsSymbol())
			{	// To match first non-symbol, serif, proportional
			TypefaceSupport(lsupport, 0);
			while ((listindex < count) && ((lsupport.iTypeface.IsSymbol() ||
				(typeface.IsProportional() != lsupport.iTypeface.IsProportional()) ||
				(typeface.IsSerif() != lsupport.iTypeface.IsSerif()))))
				{
				TypefaceSupport(lsupport, listindex);
				aname.Copy(lsupport.iTypeface.iName);
				listindex++;
				}
			if (listindex == count)
				{	// try to match first non-symbol.proportional
				listindex = 0;
				do
					{
					TypefaceSupport(lsupport, listindex);
					aname.Copy(lsupport.iTypeface.iName);
					listindex++;
					}
				while ((listindex < count) && (lsupport.iTypeface.IsSymbol() ||
					(typeface.IsProportional() != lsupport.iTypeface.IsProportional())));
				}
			if (listindex == count)
				{	// try to match first non-symbol
				listindex = 0;
				do
					{
					TypefaceSupport(lsupport, listindex);
					aname.Copy(lsupport.iTypeface.iName);
					listindex++;
					}
				while ((listindex < count) && lsupport.iTypeface.IsSymbol());
				}
			}
		else
			{	// try to match first symbol typeface
			listindex = 0;
			TypefaceSupport(lsupport, 0);

			while ((listindex < count) && !lsupport.iTypeface.IsSymbol())
				{
				TypefaceSupport(lsupport, listindex);
				aname.Copy(lsupport.iTypeface.iName);
				listindex++;
				}
			}
		if (listindex == count)
			{
			listindex = 0;
			TypefaceSupport(lsupport, listindex);
			}
		}
		
	if (listindex <= iFbsTypefaceCount)
		{
		TFontSpec fontspec(aFontSpec);
		fontspec.iTypeface = lsupport.iTypeface;
		TBuf<KMaxTypefaceNameLength> fontspec_name;
		fontspec_name.Copy(fontspec.iTypeface.iName);
		return iFbsTypefaceStore->GetNearestFontToDesignHeightInTwips(aFont, fontspec);
		}
	else
		{
		TFontSpec fontspec(aFontSpec);
		fontspec.iTypeface = lsupport.iTypeface;
		TBuf<KMaxTypefaceNameLength> fontspec_name;
		fontspec_name.Copy(fontspec.iTypeface.iName);
		return iTypefaceStore->GetNearestFontToDesignHeightInTwips(aFont, fontspec);
		}
	}

EXPORT_C void CFbsDrvDevice::ReleaseFont(CFont* aFont)
	{
	if (aFont)
		{
		if (aFont->TypeUid() != KCFbsFontUid)
			{
			iTypefaceStore->ReleaseFont(aFont);
			}
		else
			{
			iFbsTypefaceStore->ReleaseFont(aFont);
			}
		}
	}

EXPORT_C TInt CFbsDrvDevice::NumTypefaces() const
	{
	return iGenTypefaceFontsList->Count();
	}

/**
@deprecated Interface is deprecated because it is unsafe as it may leave. It is available for backward compatibility reasons only.
@see CFbsDrvDevice::LoadTypeFaceListL
*/

EXPORT_C void CFbsDrvDevice::LoadTypeFaceList()
	{
	// Trap and Ignore the ERROR code as its a non-leaving method.
	TRAP_IGNORE(LoadTypeFaceListL());
	}

/**
New Updated LoadTypeFaceList() method
@publishedAll
@released
*/
EXPORT_C void CFbsDrvDevice::LoadTypeFaceListL()
	{
	iFbsTypefaceCount = 0;
	iPdrTypefaceCount = 0;
	if (iGenTypefaceFontsList)
		iGenTypefaceFontsList->Reset();
	else
		iGenTypefaceFontsList = new (ELeave) CArrayFixFlat<TInt>(1);

	if (iGenTypefaceFontsType)
		iGenTypefaceFontsType->Reset();
	else
		iGenTypefaceFontsType = new (ELeave) CArrayFixFlat<TInt>(1);
		
	TInt loop;
	for(loop = 0; loop < iFbsTypefaceStore->NumTypefaces(); loop++)
		{
		TTypefaceSupport support;
		iFbsTypefaceStore->TypefaceSupport(support, loop);
			{
			if (support.iIsScalable)
				{
				iGenTypefaceFontsList->AppendL(loop);
				iGenTypefaceFontsType->AppendL(1);
				iFbsTypefaceCount++;
				}
			}
		}

	for (loop = 0; loop < iTypefaceStore->NumTypefaces(); loop++)
		{
		TTypefaceSupport support;
		iTypefaceStore->TypefaceSupport(support, loop);

		TBuf<KMaxTypefaceNameLength> name;
		name.Copy(support.iTypeface.iName);

		iGenTypefaceFontsList->AppendL(loop);
		iGenTypefaceFontsType->AppendL(0);
		iPdrTypefaceCount++;
		}
	}

EXPORT_C void CFbsDrvDevice::TypefaceSupport(TTypefaceSupport& aTypefaceSupport, TInt aTypefaceIndex) const
	{
	TInt index = iGenTypefaceFontsList->At(aTypefaceIndex);
	TInt type = iGenTypefaceFontsType->At(aTypefaceIndex);

	if (type == 0)
		iTypefaceStore->TypefaceSupport(aTypefaceSupport, index);
	else
		iFbsTypefaceStore->TypefaceSupport(aTypefaceSupport, index);
	}

EXPORT_C TInt CFbsDrvDevice::FontHeightInTwips(TInt aTypefaceIndex, TInt aHeightIndex) const
	{
	TInt index = iGenTypefaceFontsList->At(aTypefaceIndex);
	TInt type = iGenTypefaceFontsType->At(aTypefaceIndex);

	if (type == 0)
		return iTypefaceStore->FontHeightInTwips(index, aHeightIndex);
	else
		return iFbsTypefaceStore->FontHeightInTwips(index, aHeightIndex);
	}

EXPORT_C TInt CFbsDrvDevice::CreateContext(CGraphicsContext*& aGc)
	{
	__ASSERT_DEBUG(iControl, Panic(EPdrControlDoesNotExist));
	CPdrControl* control = (CPdrControl*)iControl;
	return control->CreateContext(aGc);
	}

EXPORT_C void CFbsDrvDevice::CreateControlL(CPrinterPort* aPrinterPort)
	{
	__ASSERT_ALWAYS(aPrinterPort, Panic(EPdrRequiresPrinterPort));
	__ASSERT_ALWAYS(!iControl, Panic(EPdrControlAlreadyExists));
	__ASSERT_DEBUG(iCurrentPageSpecInTwips.iPortraitPageSize.iWidth && iCurrentPageSpecInTwips.iPortraitPageSize.iHeight, Panic(EPdrPageSpecNotSet));
	iControl = CFbsDrvControl::NewL(this, aPrinterPort, *iStore, iModelInfo->iResourcesStreamId);
	}

/**
@deprecated Interface is deprecated because it is unsafe as it may leave. It is available for backward compatibility reasons only.
@see CFbsDrvDevice::SetModelL
*/
EXPORT_C TInt CFbsDrvDevice::SetModel(const TPrinterModelHeader& aModel, CStreamStore& aStore)
	{
	TInt ret = 0;
	TRAPD(errCode, ret=SetModelL(aModel, aStore));
	if(errCode != KErrNone)
		{
		return errCode;
		}
	return ret;
	}

EXPORT_C TInt CFbsDrvDevice::SetModelL(const TPrinterModelHeader& aModel, CStreamStore& aStore)
	{
	TInt ret = CPdrDevice::SetModel(aModel, aStore);
	if (ret == KErrNone)
		{
		iFbsTypefaceStore = CFbsTypefaceStore::NewL(this);
		LoadTypeFaceListL();
		}
	return ret;
	}

EXPORT_C TSize CFbsDrvDevice::KPixelSizeInTwips() const
	{
	return TSize(iModelInfo->iKPixelWidthInTwips, iModelInfo->iKPixelHeightInTwips);
	}

EXPORT_C void CFbsDrvDevice::Reserved_1()
	{
	}

EXPORT_C CFbsDrvControl* CFbsDrvControl::NewL(CPdrDevice* aPdrDevice, CPrinterPort* aPrinterPort, CStreamStore& aStore, TStreamId aResourcesStreamId)
	{
	CFbsDrvControl* control = new(ELeave) CFbsDrvControl(aPdrDevice, aPrinterPort);
	CleanupStack::PushL(control);
	control->ConstructL(aStore, aResourcesStreamId);
	CleanupStack::Pop();
	return control;
	}

EXPORT_C CFbsDrvControl::~CFbsDrvControl()
	{
	delete iScanLine;
	delete iCompressedScanLine;
	}

EXPORT_C CFbsDrvControl::CFbsDrvControl(CPdrDevice* aPdrDevice, CPrinterPort* aPrinterPort):
	CPdrControl(aPdrDevice, aPrinterPort),
	iScanLine(NULL),
	iCompressedScanLine(NULL)
	{
	__DECLARE_NAME(_S("CFbsDrvControl"));
	}

EXPORT_C void CFbsDrvControl::ConstructL(CStreamStore& aStore, TStreamId aResourcesStreamId)
	{
	CPdrControl::ConstructL(aStore, aResourcesStreamId);
	}

EXPORT_C void CFbsDrvControl::SetPageSizeL()
	{
	TCommandString des;
	des.Format(iResources->ResourceString(EPdrSetPageSize), iPdrDevice->CurrentPageSpecInTwips().iPortraitPageSize.iHeight / KTwipsPerInch);
	iPageBuffer->AddBytesL(des);
	}

/**
 @return ETrue if there are non-blank bytes in scanline. 
 */
EXPORT_C TBool CFbsDrvControl::TransformBuffer()
	{	
	TInt i;
	for (i = iScanLine->Des().Length() - 1; (i >= 0) && (iScanLine->Des()[i] == 0xFF); i--)
		{
		}
	TInt length = i + 1;
	iScanLine->Des().SetLength(length);
	TUint8* p = (TUint8*)iScanLine->Des().Ptr();
	TUint8* pEnd = p + length;
	for (; p < pEnd; p++)
		{
		TInt byte1 = *p;
		TInt byte2 = 0;
		for (TInt j = 0; j < 8; j++)
			{
			byte2 = byte2 << 1;
			byte2 |= (byte1 & 1);
			byte1 = byte1 >> 1;
			}
		*p = (TUint8)~byte2; 
		}
	return (length > 0);	// returns ETrue if there are non-blank bytes in scanline
	}

/**
 @return ETrue if the scanline is compressed successfully. 
 */
EXPORT_C TBool CFbsDrvControl::CompressBuffer()
	{
	TInt length1 = iScanLine->Des().Length();
	TInt length2 = 0;
	TUint8* p1 = (TUint8*)iScanLine->Des().Ptr();
	TUint8* p2 = (TUint8*)iCompressedScanLine->Des().Ptr();
	TUint8 repeat;
	for (TInt i = 0; (i < length1) && (length2 < length1); i += repeat + 1)
		{
		TUint8 byte = *(p1++);
		for (repeat = 0; ((i + repeat + 1) < length1) && (byte == *p1) && (repeat < 255);)
			{
			repeat++;
			p1++;
			}
		length2++;
		if (length2 < length1)
			{
			*(p2++) = repeat;
			length2++;
			if (length2 < length1)
				*(p2++) = byte;
			}
		}
	iCompressedScanLine->Des().SetLength(length2);
	return (length2 < length1);   // returns ETrue if the scanline is compressed successfully
	}

/**
 This function is intentionally a dummy. It has to be implemented because
 of an inherited pure virtual but it should always be overload by any class
 that derives from it.
*/
EXPORT_C void CFbsDrvControl::OutputBandL()
	{
	// I should probably put an assert in here.
	if (IsGraphicsBand())
		{
		TRect bandrect = iBandedDevice->BandRect();
		TSize size = bandrect.Size();
		TCommandString des;
		TBool datainband = EFalse;
		TInt numscanlines = size.iHeight;
		if (iBandedDevice->BandingDirection() == EBandingRightToLeft)
			numscanlines = size.iWidth;
		for (TInt i = 0; i < numscanlines; i++)
			{
			TInt x = bandrect.iTl.iX;
			TInt y = bandrect.iTl.iY + i;
			TPtr8 ptr = iScanLine->Des();
			if (iBandedDevice->BandingDirection() == EBandingTopToBottom)
				iBandedDevice->BandBitmap()->GetScanLine(ptr, TPoint(0, i), size.iWidth, iPdrDevice->DisplayMode());
			else
				{
				iBandedDevice->BandBitmap()->GetVerticalScanLine(ptr, numscanlines - (i + 1), iPdrDevice->DisplayMode());
				x = bandrect.iBr.iX - i;
				y = bandrect.iTl.iY;
				}
			if (TransformBuffer() && !datainband)
				{
				MoveToL(TPoint(x, y));
				if (iBandedDevice->BandingDirection() == EBandingLeftToRight)
					des.Format(iResources->ResourceString(EPdrBitmapStart), EFbsPhysicalPageOrientation);
				else
					des.Format(iResources->ResourceString(EPdrBitmapStart), EFbsLogicalPageOrientation);
				iPageBuffer->AddBytesL(des);
				datainband = ETrue;
				}
			if (datainband)
				{
				TCommandString buf = iResources->ResourceString(EPdrScanLine);
				if (CompressBuffer())
					{
					des.Format(buf, EFbsRunLength, iCompressedScanLine->Des().Length());
					iPageBuffer->AddBytesL(des);
					iPageBuffer->AddBytesL(iCompressedScanLine->Des());
					}
				else
					{
					des.Format(buf, EFbsNone, iScanLine->Des().Length());
					iPageBuffer->AddBytesL(des);
					iPageBuffer->AddBytesL(iScanLine->Des());
					}
				}
			}
		iPageBuffer->AddBytesL(iResources->ResourceString(EPdrBitmapEnd));

		iPosition.iX = iPdrDevice->OffsetInPixels().iX;
		TInt numentries = iPageText->NumEntries();
		if(numentries)
			{
			CPageTextEntry* entry;
			for(TInt y = bandrect.iTl.iY; y <= bandrect.iBr.iY; y++)
				{
				for(TInt index = 0; (index < numentries); index++)
					{
					entry = (*iPageText)[index];
					TPoint drawPos = entry->iDrawPos;
					if(drawPos.iY == y)
						OutputTextL(drawPos, entry->iTextWidthInPixels, *(entry->iTextFormat), *(entry->iText));										 //!!
					}
				}
			}
		}
	}

EXPORT_C void CFbsDrvControl::Reserved_1()
	{
	}