fontservices/referencefonts/utils/bdfharn.cpp
changeset 0 1fb32624e06b
child 41 ea44a32a96bc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fontservices/referencefonts/utils/bdfharn.cpp	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,412 @@
+/*
+* Copyright (c) 2003-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: 
+* Chris Cooper, 09 March 1999
+* This application loads a scaleable open font and extracts a particular
+* user-specified size from it which it then outputs as a BDF format font
+* file. This can then be turned into an EPOC bitmap font using other tools.
+* At the moment the required font name and PPEM size are specified in a
+* program statement, so this utility must be recompiled. It is intended to
+* change this to obtain the input from a text file - and to allow multiple
+* conversions to be specified at once.
+* This application has to be a Unicode build to function.
+* If this #define is enabled than, instead of getting a useable BDF file,
+* the hex char definitions are replaced by visible bitmaps of the chars.
+* It should, therefore, be commented out in normal use.
+*
+*/
+
+//#define SHOW_FONT_PICTURES_INSTEAD_OF_HEX
+
+#include <e32std.h>
+#include <e32test.h>
+#include <bitstd.h>
+#include <bitdev.h>
+#include <fbs.h>
+#include <f32file.h>
+
+
+#include "bdfharn.h"
+
+TPtrC CBDFHarness::iFacename(_L("DejaVu Sans Condensed"));
+TInt  CBDFHarness::iPixelSize = 8;
+TPtrC CBDFHarness::iFilename(_L("Swi8br"));
+TPtrC CBDFHarness::iUid(_L("268457817"));
+
+TFontPosture CBDFHarness::iPosture = EPostureUpright;
+//TFontPosture CBDFHarness::iPosture = EPostureItalic;
+
+//TFontStrokeWeight CBDFHarness::iStrokeWeight = EStrokeWeightNormal;
+TFontStrokeWeight CBDFHarness::iStrokeWeight = EStrokeWeightBold;
+
+TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosNormal;
+//TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosSuperscript;
+//TFontPrintPosition CBDFHarness::iPrintPosition = EPrintPosSubscript;
+
+TBuf<256> buffer;
+
+// this function is a hack to take a Unicode string containing
+// only chars <= 255 and put out the 8 bit version to the file
+void FileWrite8(RFile& aFile, const TDesC& aText)
+	{
+	// It's Unicode so we've got to step down from 16 bit desc to 8 bit file
+	TInt length = aText.Length();
+	HBufC8* buffer8 = HBufC8::NewMaxL(length);
+	TPtr8 p = buffer8->Des();
+	TUint16 c;
+	TUint8 b;
+
+	int k = 0;
+	for (int r = 0; r < length; r++)
+		{
+		c = aText[r];
+		b = (TUint8)c;
+		p[k++] = b;
+		}
+	aFile.Write(*buffer8);
+	delete buffer8;
+	}
+
+
+CBDFHarness::CBDFHarness(const TDesC &aTitle, const TDesC &aHeading): iTest(aTitle)
+	{
+	iTest.Title();
+	iTest.Start(aHeading);
+	}
+
+
+CBDFHarness* CBDFHarness::NewL(const TDesC &aTitle, const TDesC &aHeading)
+	{
+	CBDFHarness* t = new (ELeave)CBDFHarness(aTitle, aHeading);
+	CleanupStack::PushL(t);
+	t->ConstructL();
+	CleanupStack::Pop();
+	return t;
+	}
+
+
+void CBDFHarness::ConstructL()
+	{
+	RFbsSession::Connect();
+	iFbs = RFbsSession::GetSession();
+	if (iFbs == NULL)
+		User::Leave(KErrGeneral);
+	iDev = CFbsScreenDevice::NewL(_L("scdv"),EGray4);
+	iDev->ChangeScreenDevice(NULL);
+	iDev->SetAutoUpdate(ETrue);
+	iDev->CreateContext(iGc);
+
+	TFontSpec fs(iFacename, iPixelSize);
+	fs.iFontStyle.SetPosture(iPosture);
+	fs.iFontStyle.SetStrokeWeight(iStrokeWeight);
+	fs.iFontStyle.SetPrintPosition(iPrintPosition);
+	TInt error = iDev->GetNearestFontInPixels((CFont*&)iStandardFont,fs);
+	if (error)
+		User::Panic(_L("Could not create this font"),error);
+	}
+
+
+CBDFHarness::~CBDFHarness()
+	{
+	if (iStandardFont)
+		iDev->ReleaseFont(iStandardFont);
+	delete iGc;
+	delete iDev;
+	RFbsSession::Disconnect();
+	iTest.Close();
+	}
+
+
+void CBDFHarness::MakeBDFFont()
+	{
+	TOpenFontFaceAttrib attrib;
+	iStandardFont->GetFaceAttrib(attrib);
+	TPtrC familyName = attrib.FamilyName();
+	TPtrC fullName = attrib.LocalFullName();
+	TOpenFontMetrics fMetrics;
+	iStandardFont->GetFontMetrics(fMetrics);
+	iPPEM = fMetrics.Size();
+
+	// Open file session
+	RFs file_session;
+	file_session.Connect();
+	file_session.MkDir(_L("\\BDFfonts\\"));
+	// Open file
+	RFile file;
+	buffer.Format(_L("\\BDFfonts\\%S %d.bdf"), &fullName, iPPEM);
+	file.Replace(file_session, buffer, EFileShareAny);
+	// Extract global info
+	// STARTFONT 2.2
+	buffer.Format(_L("STARTFONT 2.2\r\n"));
+	FileWrite8(file, buffer);
+	// COMMENT <font name> [(Bold) ][(Italic) ]at <nn> pixels per em
+	buffer.Format(_L("COMMENT %S "), &familyName);
+	FileWrite8(file, buffer);
+	if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold)
+		{
+		buffer.Format(_L("(Bold) "));
+		FileWrite8(file, buffer);
+		}
+	if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic)
+		{
+		buffer.Format(_L("(Italic) "));
+		FileWrite8(file, buffer);
+		}
+	buffer.Format(_L("at %d pixels per em\r\n"), iPPEM);
+	FileWrite8(file, buffer);
+	// COMMENT Generated by the EPOC BDF creator
+	buffer.Format(_L("COMMENT Generated by the EPOC BDF creator\r\n"));
+	FileWrite8(file, buffer);
+	// FONT <font name>
+	buffer.Format(_L("FONT %S\r\n"), &iFilename);
+	FileWrite8(file, buffer);
+	// SIZE <ppem> 72 72
+	buffer.Format(_L("SIZE %d 72 72\r\n"), iPPEM);
+	FileWrite8(file, buffer);
+	// FONTBOUNDINGBOX <bbox pixel width> <bbox pixel height> <bbox x pixel offset> <bbox y pixel offset>
+	TInt bbw = fMetrics.MaxWidth();
+	TInt bbh = fMetrics.MaxHeight() + fMetrics.MaxDepth();
+	TInt bbxo = 0;
+	TInt bbyo = -1 * fMetrics.MaxDepth();
+	buffer.Format(_L("FONTBOUNDINGBOX %d %d %d %d\r\n"), bbw, bbh, bbxo, bbyo);
+	FileWrite8(file, buffer);
+	// STARTPROPERTIES
+	TInt numproperties = 5;
+	if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold)
+		numproperties++;
+	if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic)
+		numproperties++;
+	buffer.Format(_L("STARTPROPERTIES %d\r\n"), numproperties);
+	FileWrite8(file, buffer);
+	buffer.Format(_L("Uid %S\r\n"), &iUid);
+	FileWrite8(file, buffer);
+	buffer.Format(_L("MaxNormalCharWidth "));
+	FileWrite8(file, buffer);
+	TInt maxWidth = bbw;
+	buffer.Format(_L("%d\r\n"), maxWidth);
+	FileWrite8(file, buffer);
+	buffer.Format(_L("MaxConsecutiveFillChars 5\r\n"));
+	FileWrite8(file, buffer);
+	if (iStandardFont->FontSpecInTwips().iFontStyle.StrokeWeight() == EStrokeWeightBold)
+		{
+		buffer.Format(_L("Bold 1\r\n"));
+		FileWrite8(file, buffer);
+		}
+	if (iStandardFont->FontSpecInTwips().iFontStyle.Posture() == EPostureItalic)
+		{
+		buffer.Format(_L("Italic 1\r\n"));
+		FileWrite8(file, buffer);
+		}
+	// FONT_ASCENT
+	buffer.Format(_L("FONT_ASCENT %d\r\n"), fMetrics.Ascent());
+	FileWrite8(file, buffer);
+	// FONT_DESCENT
+	buffer.Format(_L("FONT_DESCENT %d\r\n"), fMetrics.Descent());
+	FileWrite8(file, buffer);
+	// ENDPROPERTIES
+	buffer.Format(_L("ENDPROPERTIES\r\n"));
+	FileWrite8(file, buffer);
+	// CHARS <number of glyphs>
+	// Work out how many chars in font
+	TInt charCount = 0;
+	TInt i = 0;
+	for ( i = 0; i <= 0xFFFF; i++ )
+		{
+		if ( iStandardFont->HasCharacter(i) )
+			charCount++;
+		}
+	buffer.Format(_L("CHARS %d\r\n"), charCount);
+	FileWrite8(file, buffer);
+
+	for ( i = 0; i <= 0xFFFF; i++ )
+		{
+		if ( iStandardFont->HasCharacter(i) )
+			{
+			// STARTCHAR <Unn in hex>
+			buffer.Format(_L("STARTCHAR U%x\r\n"), i);
+			FileWrite8(file, buffer);
+			// ENCODING <usually nn decimal>
+			buffer.Format(_L("ENCODING %d\r\n"), i);
+			FileWrite8(file, buffer);
+			// SWIDTH <swidth> 0
+			// DWIDTH <swidth * (pointsize / 1000) * (device resolution / 72)> 0
+			// DWIDTH <swidth * (ppem / 1000) * (72 / 72)> 0
+			// but DWIDTH  = <advance in pixels> which we know
+			// so SWIDTH = (DWIDTH * 1000) / ppem
+			TOpenFontCharMetrics cMetrics;
+			const TUint8* bitmapPtr;
+			TSize dummy;
+			iStandardFont->GetCharacterData(i, cMetrics, bitmapPtr, dummy);
+			TInt dwidth = cMetrics.HorizAdvance();
+			TReal dwidthReal = dwidth;
+			TInt swidth = (TInt)(((dwidthReal * 1000) / iPPEM) + 0.5);
+			buffer.Format(_L("SWIDTH %d 0\r\n"), swidth);
+			FileWrite8(file, buffer);
+			buffer.Format(_L("DWIDTH %d 0\r\n"), dwidth);
+			FileWrite8(file, buffer);
+			// BBX <bmap pixel width> <bmap pixel height> <bmap x pixel offset> <bmap y pixel offset>
+			TInt bpw = cMetrics.Width();
+			TInt bph = cMetrics.Height();
+			TInt bxo = cMetrics.HorizBearingX();
+			TInt byo = cMetrics.HorizBearingY() - bph; // Because openfont offsets are to top left and bdf is to bottom left
+			buffer.Format(_L("BBX %d %d %d %d\r\n"), bpw, bph, bxo, byo);
+			FileWrite8(file, buffer);
+			// BITMAP
+			buffer.Format(_L("BITMAP\r\n"));
+			FileWrite8(file, buffer);
+			TInt paddedWidth = ((bpw + 7) / 8);
+			if (bph * paddedWidth)
+				{
+				TUint8* bitmap = new TUint8 [sizeof(TUint8) * bph * paddedWidth];
+				DecodeBitmap(bpw, paddedWidth, bph, bitmapPtr, bitmap);
+				for (TInt j = 0; j < bph; j++)
+					{
+					// Output one line of bitmap
+#ifndef SHOW_FONT_PICTURES_INSTEAD_OF_HEX
+					// This branch is the standard version that produces useable BDF files
+					for (TInt k = paddedWidth - 1; k >= 0; k--)
+						{
+						TInt byte = *(bitmap + (j * paddedWidth) + k);
+
+						OutHex(byte / 16);
+						FileWrite8(file, buffer);
+						OutHex(byte % 16);
+						FileWrite8(file, buffer);
+						}
+					buffer.Format(_L("\r\n"));
+					FileWrite8(file, buffer);
+#else
+					// This branch shows the char bitmaps but does not produce useable BDF files
+					buffer.Format(_L("["));
+					FileWrite8(file, buffer);
+					iBitNum = ((j + 1) * paddedWidth * 8) - 1;
+					iBitMap = bitmap;
+
+					for (TInt k = 0; k < bpw; k++)
+						{
+						if (ReadBitBack())
+							buffer.Format(_L("@"));
+						else
+							buffer.Format(_L(" "));
+						FileWrite8(file, buffer);
+						}
+					for (k = bpw; k < 8 * paddedWidth; k++)
+						{
+						buffer.Format(_L("."));
+						FileWrite8(file, buffer);
+						}
+					buffer.Format(_L("]\r\n"));
+					FileWrite8(file, buffer);
+#endif
+					}
+				delete [] bitmap;
+				}
+			// ENDCHAR
+			buffer.Format(_L("ENDCHAR\r\n"));
+			FileWrite8(file, buffer);
+			}
+		}
+	// ENDFONT
+	buffer.Format(_L("ENDFONT\r\n"));
+	FileWrite8(file, buffer);
+	// Close file
+	file.Flush();
+	file.Close();
+	file_session.Close();
+
+	}
+
+TInt CBDFHarness::ReadBit()
+	{
+	TInt val = 1;
+	for (TInt i = 0; i < (iBitNum % 8); i++)
+		val *= 2;
+	val = iBitMap[iBitNum / 8] & val;
+	iBitNum++;
+	return val ? 1 : 0;
+	}
+
+TInt CBDFHarness::ReadBitBack()
+	{
+	TInt val = 1;
+	for (TInt i = 0; i < (iBitNum % 8); i++)
+		val *= 2;
+	val = iBitMap[iBitNum / 8] & val;
+	iBitNum--;
+	return val ? 1 : 0;
+	}
+
+void CBDFHarness::OutHex(TInt aOneHexDigit)
+	{
+	if (aOneHexDigit <= 9)
+		buffer.Format(_L("%c"), '0' + aOneHexDigit);
+	else
+		buffer.Format(_L("%c"), 'a' + aOneHexDigit - 10);
+	}
+
+void CBDFHarness::DecodeBitmap(TInt aWidth, TInt aPaddedWidth, TInt aHeight, const TUint8* aCodedBitmap, TUint8* aBitMap)
+	{
+	// Zero the bitmap
+	for (TInt i = 0; i < aPaddedWidth * aHeight; i++)
+		aBitMap[i] = 0;
+	TInt repeats = 0;
+	iBitNum = 0;
+	iBitMap = aCodedBitmap;
+	for (TInt linesRead = 0; linesRead < aHeight; linesRead += repeats)
+		{
+		TInt repeating = !(ReadBit());
+		
+		// Intended behavior is for the line of code below to be evaluated left to right.
+		//    repeats = (1 * ReadBit()) + (2 * ReadBit()) + (4 * ReadBit()) + (8 * ReadBit());
+		// However, the order in which calls to ReadBit() above are evaluated is undefined,
+		// and is compiler dependent.
+		// The following code ensures that the correct code is used:
+		TInt bit1 = ReadBit();
+		TInt bit2 = ReadBit();
+		TInt bit3 = ReadBit();
+		TInt bit4 = ReadBit();
+		repeats = (1 * bit1) + (2 * bit2) + (4 * bit3) + (8 * bit4);
+
+		TInt padVal = (aPaddedWidth * 8) - aWidth;
+		if (repeating)
+			{
+			for (TInt j = padVal + aWidth - 1; j >= padVal; j--)
+				{
+				TInt value = ReadBit();
+				for (TInt k = 0; k < (j % 8); k++)
+					value *= 2;
+				for (TInt l = 0; l < repeats; l++)
+					{
+					aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] =
+						TUint8(aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] + value);
+					}
+				}
+			}
+		else
+			{
+			for (TInt l = 0; l < repeats; l++)
+				{
+				for (TInt j = padVal + aWidth - 1; j >= padVal; j--)
+					{
+					TInt value = ReadBit();
+					for (TInt k = 0; k < (j % 8); k++)
+						value *= 2;
+					aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] =
+						TUint8(aBitMap[((linesRead + l) * aPaddedWidth) + (j / 8)] + value);
+					}
+				}
+			}
+		}
+	}
+