graphicstools/bitmapfonttools/src/FNTREADR.CPP
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstools/bitmapfonttools/src/FNTREADR.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1013 @@
+/*
+* 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: 
+* Header FNTREADR.CPP
+*
+*/
+
+
+#include "FNTREADR.H"
+
+const int KMarkFirstCharacterInTypeface = -1;
+const int KBytesAddedForMetricIndex = 2;
+const int KBytesForIndexForFillCharacters = 2;
+const int KReportRateFrequencyInPercent = 10;
+
+// class CroppedValues
+
+class CroppedValues
+	{
+public:
+	CroppedValues();
+public:
+	int iTopCrop;
+	int iBottomCrop;
+	int iLeftCrop;
+	int iRightCrop;
+	};
+
+CroppedValues::CroppedValues()
+ :	iTopCrop(0), iBottomCrop(0), iLeftCrop(0), iRightCrop(0)
+	{}
+
+// class FontReader
+
+FontReader::FontReader()
+ :	Reader(),
+	iFontStore(),
+	iFontStoreFile(NULL),
+	iCharacterMetrics(NULL),
+	iCodeSection(NULL),
+	iFontBitmap(NULL),
+	iTypeface(NULL),
+	iReadFileFormat(ESymbianGDFFormat),
+	iBitmapWidth(0),
+	iBitmapHeight(0),
+	iDefaultXMoveInPixels(KUndefinedInteger),
+	iDefaultYMoveInPixels(KUndefinedInteger)
+	{
+	}
+
+boolean FontReader::Read(const String& aFilename)
+	{
+	iFileName = aFilename;
+	boolean state = Open(iFileName.Text());
+
+	while (!_EOF() && state)
+		{
+		if (IdentComp(IdentBDFFileHeader) || IdentComp(IdentBDFComment))
+			{
+			state = ReadBDFFontBitmap();
+			iReadFileFormat = EBDFFormat;
+			}
+		else if (IdentComp(IdentTypeface))
+			state = ReadTypeface();
+		else if (IdentComp(IdentFontStoreFile))
+			state = ReadFontStoreFile();
+		else
+			{
+			Error("Resource identifier expected");
+			state = efalse;
+			}
+		if (state)
+			state = NewLine();
+		}
+	return state;
+	}
+
+boolean FontReader::ReadMetricFromBDFCharacter(CharacterMetrics* aCharacterMetrics, CroppedValues* aCropped=  NULL)
+	{
+	int xMoveInPixels = 0;
+	int yMoveInPixels = 0;
+	int bitmapXOffset = 0;
+	int bitmapYOffset = 0;
+
+	boolean state = true;
+
+	if (iDefaultXMoveInPixels != KUndefinedInteger)
+		xMoveInPixels = iDefaultXMoveInPixels;
+	if (iDefaultYMoveInPixels != KUndefinedInteger)
+		yMoveInPixels = iDefaultYMoveInPixels;
+	
+	while (!IdentComp(IdentBDFEndChar) && !_EOF() && state)
+		{
+		iLexAnal->ReadNextLine(); // Skip to next line
+		if (iLex->iType == ELexIdent)
+			{
+			if (IdentComp(IdentBDFCursorMove))
+				{
+				state = Number(xMoveInPixels);
+				if (state)
+					state = Number(yMoveInPixels);
+				}
+			else if (IdentComp(IdentBDFBitmapSizeAndDisplacement))
+				{
+				state = Number(iBitmapWidth);
+				if (state)
+					{
+					state = Number(iBitmapHeight);
+					state = Number(bitmapXOffset);
+					state = Number(bitmapYOffset);
+					}
+				}
+			else if (IdentComp(IdentBDFStartBitmap) && state)
+				{
+				int line = 0;
+				for (line = 0; line < iBitmapHeight; line++)
+					{
+					iLexAnal->ReadNextLine();	// Skip to next line
+					int bits = 0;
+					int bitOffset = 0;
+					int byteValue = 0;
+					for (bits = 0; bits < iBitmapWidth; bits++)
+						{
+						if (bitOffset == 0)
+							{
+							Lexical lex;
+							strncpy(lex.iText, &iLexAnal->iLine[bits >> 2], 2);
+							lex.iText[2] = '\0';
+							byteValue = lex.CovertStringToHex();
+							bitOffset = 8;
+							}
+
+						bitOffset--;
+						int bitValue = (byteValue >> bitOffset) & 1;
+						iBitArray[bits][line] = bitValue;
+						}
+					}
+				}
+			}
+		else
+			{
+			Error("Fontbitmap identifier expected");
+			state = efalse;
+			}
+		}
+
+	if (state)
+		state = NewLine();
+//
+// Make sure that bitmap is fully cropped
+//
+	int leftCrop = 0;
+	int rightCrop = 0;
+	int topCrop = 0;
+	int bottomCrop = 0;
+	
+	int line = 0;
+	while (BitmapLineEmpty(line) && line < iBitmapHeight)
+		{
+		topCrop++;;
+		line++;
+		}
+	line = iBitmapHeight - 1;
+	while (BitmapLineEmpty(line) && line > topCrop)
+		{
+		bottomCrop++;
+		line--;
+		}
+	int column = iBitmapWidth - 1;
+	while (BitmapColumnEmpty(column) && column >= 0)
+		{
+		rightCrop++;
+		column--;
+		}
+	column = 0;
+	while (BitmapColumnEmpty(column) && column < iBitmapWidth - 1 - rightCrop)
+		{
+		leftCrop++;
+		column++;
+		}
+
+	int croppedBitmapHeight = iBitmapHeight - topCrop - bottomCrop;
+	int croppedBitmapWidth = iBitmapWidth - leftCrop - rightCrop;
+	int croppedLeftAdjust = bitmapXOffset + leftCrop;
+	int croppedRightAdjust = (xMoveInPixels - croppedLeftAdjust - croppedBitmapWidth);
+	int croppedAscent = croppedBitmapHeight + bitmapYOffset + bottomCrop;
+
+	if(state)
+		{
+		aCharacterMetrics->iAscentInPixels = (chardim) croppedAscent;
+		aCharacterMetrics->iHeightInPixels = (chardim) croppedBitmapHeight;
+		aCharacterMetrics->iLeftAdjustInPixels = (chardim) croppedLeftAdjust;
+		aCharacterMetrics->iMoveInPixels = (chardim) xMoveInPixels;
+		aCharacterMetrics->iRightAdjustInPixels = (chardim) croppedRightAdjust;
+		if (aCropped)
+			{
+			aCropped->iBottomCrop = bottomCrop;
+			aCropped->iLeftCrop = leftCrop;
+			aCropped->iRightCrop = rightCrop;
+			aCropped->iTopCrop = topCrop;
+			}
+		}
+	return state;
+	}
+
+boolean FontReader::ReadBDFCharacter(int /*aCode*/)
+	{
+	boolean state = etrue;
+	ObjectList<String*> character;
+	iCharacterMetrics = new CharacterMetrics;
+	CroppedValues* croppedValues = new CroppedValues;
+
+	state = ReadMetricFromBDFCharacter(iCharacterMetrics, croppedValues);
+
+	if (state)
+		{
+		BitmapOffset* offset = new BitmapOffset((uint16)iCodeSection->iCharactersBitmap.iByteList.Length());
+		
+		
+		iCodeSection->iCharactersBitmap.iByteList.NewByte();
+		iCodeSection->iCharacters.iBitmapOffsetList.Add(offset);
+
+		int index = iFontBitmap->iCharacterMetrics->Index(*iCharacterMetrics);
+		if (index == -1)
+			{
+			Error("Internal Compiler Error");
+			state = 0;
+			}
+		delete iCharacterMetrics;
+
+		if (state)
+			{
+			iCodeSection->iCharactersBitmap.AddIndex(index);
+
+			int line = croppedValues->iTopCrop;
+			boolean repeatLines;
+			int countLines = 0;
+			const int bottomCrop = croppedValues->iBottomCrop;
+			while (line < (iBitmapHeight - bottomCrop))
+				{
+				if ((line + 1) == (iBitmapHeight - bottomCrop))
+					{
+					repeatLines = efalse;
+					countLines = 1;
+					}
+				else if (!CompareBitmapLines(line, line + 1))
+					{
+					repeatLines = efalse;
+					for (countLines = 2; ((line + countLines) < (iBitmapHeight - bottomCrop)) && (countLines < KMaxNumberRepeatedLines); countLines++)
+						{
+						if (CompareBitmapLines(line + countLines - 1, line + countLines))
+							break;
+						}
+					}
+				else
+					{
+					repeatLines = etrue;
+					for (countLines = 2; ((line + countLines) < (iBitmapHeight - bottomCrop)) && (countLines < KMaxNumberRepeatedLines); countLines++)
+						{
+						if (!CompareBitmapLines(line, line + countLines))
+							break;
+						}
+					}
+				char bit;
+				if (repeatLines)
+					bit = 0;
+				else
+					bit = 1;
+				iCodeSection->iCharactersBitmap.iByteList.AddBit(bit);
+				for (int digit = 0; digit < 4; digit++)
+					{
+					bit = char(countLines >> digit);
+					iCodeSection->iCharactersBitmap.iByteList.AddBit(bit);
+					}
+				int lineFromTop;
+				for (lineFromTop = line; lineFromTop < (line + countLines); lineFromTop++)
+					{
+					if ((!repeatLines) || (lineFromTop == line))
+						{
+						int column;
+						for (column = croppedValues->iLeftCrop;
+							column < iBitmapWidth - croppedValues->iRightCrop; column++)
+							{
+							if (iBitArray[column][lineFromTop] == 1)
+								bit = 1;
+							else
+								bit = 0;
+							iCodeSection->iCharactersBitmap.iByteList.AddBit(bit);
+							}
+						}
+					}
+				line = line+countLines;
+				}
+			}
+		}
+	delete croppedValues;
+	return state;
+	}
+
+boolean FontReader::ReadBDFChars(const int aNumberOfGlyphsInFile, const int aMaxConsecutiveFillChars)
+	{
+	boolean state = etrue;
+	boolean newCodeSection = etrue;
+	int currentEncodingValue = 0; // each glyph has an unique encoding value
+	int lastEncodingValue = KMarkFirstCharacterInTypeface;
+	const int maxCharacterBitmapsize =
+		((KMaxBitmapWidth * KMaxBitmapHeight) / KNumberOfBitsInByte) + KBytesAddedForMetricIndex + KBytesForIndexForFillCharacters;
+
+	iCodeSection = NULL;
+	for (int numberGlyphsRead = 0; state && numberGlyphsRead < aNumberOfGlyphsInFile && !_EOF(); numberGlyphsRead++)
+		{
+		if (state && iCodeSection && iCodeSection->iCharactersBitmap.iByteList.Length() + maxCharacterBitmapsize >= KMaxSizeCodeSectionBitmap)
+			{
+			newCodeSection = etrue;
+			}
+
+		state = IdentComp(IdentBDFCharLabel);
+		if (!state)
+			ErrorIdentifierExpected(IdentBDFCharLabel);
+		if (state)
+			iLexAnal->ReadNextLine(); // Skip to next line
+
+ 		if (IdentComp(IdentBDFChar))
+			{
+			state = Number(currentEncodingValue);
+			}
+		else
+			{
+			state = efalse;
+			ErrorIdentifierExpected(IdentBDFChar);
+			}
+
+		if (KLowestPermittedCharacterEncoding > currentEncodingValue ||
+			KHighestPermittedCharacterEncoding < currentEncodingValue)
+			{
+			while (!IdentComp(IdentBDFEndChar) && !_EOF() && state) 
+				// Skip fill character.
+				{
+				iLexAnal->ReadNextLine(); // Skip to next line
+				}
+			iLexAnal->ReadNextLine();
+			continue;
+			}
+
+		if (!iCodeSection || state && (currentEncodingValue > (lastEncodingValue + 1 + aMaxConsecutiveFillChars)))
+			{
+			// First character skip to new code section
+			newCodeSection = etrue;
+			}
+		else if (state && !newCodeSection && (currentEncodingValue > lastEncodingValue + 1))
+			{
+			WriteFillCharacters(currentEncodingValue - (lastEncodingValue + 1));
+			}
+		else if (state && currentEncodingValue <= lastEncodingValue)
+			{
+			Error("CodeSection out of sequence");
+			state = efalse;
+			}
+
+		if (state && newCodeSection)
+			{
+			if (iCodeSection)
+				{
+				iCodeSection->iEnd = (uint16) lastEncodingValue;
+				iFontBitmap->iCodeSectionList.Add(iCodeSection);
+				PrintoutCodeSection(iCodeSection);
+				}
+			iCodeSection = new BitmapCodeSection;
+			iCodeSection->iStart = (uint16) currentEncodingValue;
+			}
+
+		if (state)
+			state = ReadBDFCharacter(currentEncodingValue);
+
+		newCodeSection = efalse;
+		lastEncodingValue = currentEncodingValue;
+		}
+
+	if (state)
+		{
+		iCodeSection->iEnd = (uint16) lastEncodingValue;
+		iFontBitmap->iCodeSectionList.Add(iCodeSection);
+		PrintoutCodeSection(iCodeSection);
+		}
+
+	return state;
+	}
+
+void FontReader::PrintoutCodeSection(const BitmapCodeSection* aCodeSection) const
+	{
+	cout << hex << "Codesection 0x" << aCodeSection->iStart << ": 0x" << aCodeSection->iEnd << " read" << endl;
+	cout.flush();
+	}
+
+boolean FontReader::ReadBDFFontBitmap()
+	{
+	boolean state = etrue;
+	String label;
+	iFontBitmap = new FontBitmap;
+	int pointSize;
+	int xresolution; // in dots per inch
+	int yresolution; // in dots per inch
+	int widthBoundingBox = 0; // In pixels
+	int heightBoundingBox = 0; // in pixels
+	int boundingBoxXOffset = 0; // From origin (cursor position at baseline)
+	int boundingBoxYOffset = 0;	// From origin (cursor position at baseline)
+	int numberChars = 0;
+	String fontLabel;
+	int maxNormalCharWidth = KUndefinedInteger;
+	uid fontUid = KNullUid;
+	int posture = PostureUpright;
+	int strokeWeight = StrokeWeightNormal;
+	int defaultXMoveInPixels = KUndefinedInteger;
+	int defaultYMoveInPixels = KUndefinedInteger;
+	int writingDirection = 0;
+	int maxConsecutiveFillChars = 0;	// Max permitted "fill" characters with zero size to prevent
+										// break between code sections.
+	int fontAscent = 0;
+	int fontDescent = 0;
+
+	while (!IdentComp(IdentBDFNumChars) && !_EOF() && state)
+		{
+		iLexAnal->ReadNextLine(); // Skip to next line
+		if (iLex->iType == ELexIdent)
+			{
+			if (IdentComp(IdentBDFFontBitmap))
+				{
+				state = IdentCopy(fontLabel);
+				}
+			if (IdentComp(IdentBDFPointSize))
+				{
+				state = Number(pointSize);
+				if (state)
+					state = Number(xresolution);
+				if (state)
+					state = Number(yresolution);
+				}
+			else if (IdentComp(IdentBDFFontDesignBox))
+				{
+				state = Number(widthBoundingBox);
+				if (state)
+					state = Number(heightBoundingBox);
+				if (state)
+					state = Number(boundingBoxXOffset);
+				if (state)
+					state = Number(boundingBoxYOffset);
+				}
+			else if (IdentComp(IdentBDFWritingDirection))
+				{
+				Number(writingDirection);
+				if (writingDirection != 0)
+					cout << "Warning: Only left to right writing direction supported by EPOC32";
+				}
+			else if (IdentComp(IdentBDFCursorMove))
+				{
+				state = Number(defaultXMoveInPixels);
+				if (state)
+					state = Number(defaultYMoveInPixels);
+				}
+			else if (IdentComp(IdentBDFStartProperties))	// Adding additional properties
+				{
+				int numberOfProperties;
+				state = Number(numberOfProperties);
+				if (state)
+					state = NewLine();
+				{for (int properties = 0; properties < numberOfProperties && !_EOF() && state; properties++)
+					{
+					if (IdentComp(IdentBDFPropertyUid) || IdentComp(IdentUid))
+						state = Number(fontUid);
+					else if (IdentComp(IdentBDFPropertyBold) || IdentComp(IdentBold))
+						state = Number(strokeWeight);
+					else if (IdentComp(IdentBDFPropertyItalic) || IdentComp(IdentItalic))
+						state = Number(posture);
+					else if (IdentComp(IdentBDFPropertyFontAscent))
+						state = Number(fontAscent);
+					else if (IdentComp(IdentBDFPropertyFontDescent))
+						state = Number(fontDescent);
+					else if	(IdentComp(IdentBDFPropertyMaxNormalCharWidth) || IdentComp(IdentMaxNormalCharWidth))
+						state = Number(maxNormalCharWidth);
+					else if (IdentComp(IdentBDFPropertyMaxConsecutiveFillChars) || IdentComp(IdentMaxConsecutiveFillChars))
+						state = Number(maxConsecutiveFillChars);
+
+					iLexAnal->ReadNextLine();	// Skip to next line
+					}
+				}
+				if (state)
+					{
+					state = IdentComp(IdentBDFEndProperties);
+					if (!state)
+						ErrorIdentifierExpected(IdentBDFEndProperties);
+					}
+				}
+
+			}
+		else
+			{
+			Error("Identifier expected");
+			state = efalse;
+			}
+		}
+//
+// Check that maximum size of bitmap glyph not exceeded.
+//
+	if (widthBoundingBox>KMaxBitmapWidth || widthBoundingBox>KMaxBitmapWidth)
+		{
+		state = efalse;
+		cout << "Error: A font bounding box dimension exceeds maximum permitted in EPOC32";
+		}
+
+// Check that have everthing that we need and set some bitmap properties.
+
+	iFontBitmap->iMaxCharWidthInPixels = (chardim) widthBoundingBox;
+	if (fontAscent + fontDescent)
+		{
+		iFontBitmap->iCellHeightInPixels =( chardim) (fontAscent+fontDescent);
+		iFontBitmap->iAscentInPixels = (chardim) (fontAscent);
+		}
+	else
+		{	// Old file so use the old calculation
+		iFontBitmap->iCellHeightInPixels =( chardim) heightBoundingBox;
+		iFontBitmap->iAscentInPixels = (chardim) (heightBoundingBox + boundingBoxYOffset);
+		}
+	iFontBitmap->iPosture = (boolean) posture;
+	iFontBitmap->iStrokeWeight =( boolean) strokeWeight;
+	iFontBitmap->iLabel = fontLabel;
+
+	iDefaultXMoveInPixels = defaultXMoveInPixels;
+	iDefaultYMoveInPixels = defaultYMoveInPixels;
+
+	if (fontUid != KNullUid)
+		iFontBitmap->iUid = fontUid;
+	else
+		{
+		cerr << "Warning: No font bitmap UID specified in properties\n";
+		iFontBitmap->iUid = rand();
+		}
+
+	if (maxNormalCharWidth != KUndefinedInteger)
+		iFontBitmap->iMaxNormalCharWidthInPixels = (chardim) maxNormalCharWidth;
+	else
+		{
+		cerr << "Warning: No Maximum Normal Character Width specified in properties\n";
+		iFontBitmap->iMaxNormalCharWidthInPixels = iFontBitmap->iMaxCharWidthInPixels;
+		}
+
+	if (state)
+		state = Number(numberChars);
+	if (state)
+		state = NewLine();
+	else
+		return state;
+
+	// store position of Lex here and then set it back for the reading of the BDF chars!
+	int saveLineNo = iLexAnal->iLineNo;
+	
+	ParseMetricsFromBDF(numberChars, maxConsecutiveFillChars);
+	// now reset the lexical
+	state = Open(iFileName.Text());
+	do
+		{
+		iLexAnal->Read();
+		}
+	while(saveLineNo > iLexAnal->iLineNo);
+
+	ReadBDFChars(numberChars, maxConsecutiveFillChars);
+
+	if (state)
+		{
+		state = IdentComp(IdentBDFEndFontBitmap);
+		if (!state)
+			Error("ENDFONT identifier expected");
+		}
+
+	int globalMove = KUndefinedInteger;
+	int monospaced= etrue;
+	if (state)
+		{
+		for (int i = 0; i <iFontBitmap->iCodeSectionList.Size(); i++)
+			{
+			const int end = iFontBitmap->iCharacterMetrics->iCharacterMetricsList.Size();
+			for (int j = 0; j< end; j++)
+				{
+				int move = iFontBitmap->iCharacterMetrics->iCharacterMetricsList[j]->Metric()->iMoveInPixels;
+				if (globalMove == KUndefinedInteger)
+					globalMove = move;
+				if (move > iFontBitmap->iMaxCharWidthInPixels)
+					iFontBitmap->iMaxCharWidthInPixels = (chardim) move;
+				if (globalMove!= move)
+					monospaced = efalse;
+				}
+			}
+		}
+	if (monospaced)
+		iFontBitmap->iIsProportional = efalse;
+	else
+		iFontBitmap->iIsProportional = etrue;
+
+	if (state)
+		{
+		iFontStore.AddFontBitmap(iFontBitmap);
+		cout << "FONT read\n";
+		}
+	else
+		delete iFontBitmap;
+	return state;
+	}
+
+boolean FontReader::ReadTypeface()
+	{
+	boolean state = etrue;
+	iTypeface = new FntTypeface;
+	String label;
+	int num;
+	state = IdentCopy(iTypeface->iLabel);
+	if (state)
+		state = NewLine();
+	while (!IdentComp(IdentEndTypeface) && !_EOF() && state)
+		{
+		if (IdentComp(IdentName))
+			{
+			state = StringCopy(iTypeface->iName);
+			while ((iLex->iType != ELexNL) && !_EOF() && state)
+				{
+				if (IdentComp(IdentTypefaceProportional))
+					iTypeface->iFlags = (boolean) (iTypeface->iFlags | Proportional);
+				else if (IdentComp(IdentSerif))
+					iTypeface->iFlags = (boolean) (iTypeface->iFlags | Serif);
+				else if (IdentComp(IdentSymbol))
+					iTypeface->iFlags = (boolean) (iTypeface->iFlags | Symbol);
+				else
+					{ 
+					Error("Typeface identifier or newline expected");
+					state = efalse;
+					}
+				}
+			}
+		else if (IdentComp(IdentFontBitmaps))
+			{
+			state = NewLine();
+			while (!IdentComp(IdentEndFontBitmaps) && !_EOF() && state)
+				{
+				TypefaceFontBitmap* typefacefontbitmap = NULL;
+				if (iLex->iType == ELexIdent)
+					{
+					state = IdentCopy(label);
+					FontBitmap* fontbitmap = (FontBitmap*) iFontStore.FindFontBitmap(label);
+					if (fontbitmap)
+						{
+						typefacefontbitmap = new TypefaceFontBitmap(fontbitmap);
+						state = etrue;
+						}
+					else
+						{
+						Error("Fontbitmap not found");
+						state = efalse;
+						}
+					}
+				else
+					{
+					uid fontbitmapuid;
+					state = Number(fontbitmapuid);
+					if (state)
+						typefacefontbitmap = new TypefaceFontBitmap(fontbitmapuid);
+					}
+				if (state)
+					{
+					while ((iLex->iType != ELexNL) && !_EOF() && state)
+						{
+						if (IdentComp(IdentWidthFactor))
+							{
+							state = Number(num);
+							typefacefontbitmap->iWidthFactor = (char) num;
+							}
+						else if (IdentComp(IdentHeightFactor))
+							{
+							state = Number(num);
+							typefacefontbitmap->iHeightFactor =( char) num;
+							}
+						else
+							{ 
+							Error("Typefacefontbitmap identifier or newline expected");
+							state = efalse;
+							}
+						}
+					if (state)
+						iTypeface->iTypefaceFontBitmapList.Add(typefacefontbitmap);
+					else
+						delete typefacefontbitmap;
+					}
+				if (state)
+					state = NewLine();
+				}
+			}
+		else
+			{
+			Error("Typeface identifier expected");
+			state = efalse;
+			}
+		if (state)
+			state = NewLine();
+		}
+	if (state)
+		{
+		iFontStore.AddTypeface(iTypeface);
+		cout << "Typeface read\n";
+		}	
+	else
+		delete iTypeface;
+	return state;
+	}
+
+boolean FontReader::ReadFontStoreFile()
+	{
+	boolean state = etrue;
+	int num;
+	if (iFontStoreFile)
+		{
+		state = efalse;
+		Error("Fontstorefile already read");
+		}
+	else
+		{
+		iFontStoreFile = new FontStoreFile;
+		String label;
+		Record* typeface;
+		state = NewLine();
+		while (!IdentComp(IdentEndFontStoreFile) && !_EOF() && state)
+			{
+			if (IdentComp(IdentCollectionUid))
+				{
+				state = Number(iFontStoreFile->iCollectionUid);
+				}
+			else if (IdentComp(IdentKPixelAspectRatio))
+				{
+				state = Number(num);
+				if (state)
+					iFontStoreFile->iKPixelAspectRatio = num;
+				}
+			else if (IdentComp(IdentCopyrightInfo))
+				{
+				state = NewLine();
+				while (!IdentComp(IdentEndCopyrightInfo) && !_EOF() && state)
+					{
+					String* string = new String;
+					state = StringCopy(*string);
+					if (state)
+						iFontStoreFile->iCopyrightInfo.Add(string);
+					else
+						delete string;
+					state = NewLine();
+					}
+				}
+			else if (IdentComp(IdentTypefaces))
+				{
+				state = NewLine();
+				while (!IdentComp(IdentEndTypefaces) && !_EOF() && state)
+					{
+					state =IdentCopy(label);
+					if (state)
+						{
+						typeface = iFontStore.FindTypeface(label);
+						if (typeface)
+							{
+							iFontStoreFile->AddTypeface((FntTypeface*) typeface);
+							}
+						else
+							{
+							Error("Typeface not found");
+							state = efalse;
+							}
+						}
+					if (state)
+						state = NewLine();
+					}
+				}
+			else if (IdentComp(IdentExtraFontBitmaps))
+				{
+				state = NewLine();
+				while (!IdentComp(IdentEndExtraFontBitmaps) && !_EOF() && state)
+					{
+					state = IdentCopy(label);
+					FontBitmap* fontbitmap = (FontBitmap*) iFontStore.FindFontBitmap(label);
+					if (fontbitmap)
+						{
+						iFontStoreFile->AddFontBitmap((FontBitmap*) fontbitmap);
+						}
+					else
+						{
+						Error("Fontbitmap not found");
+						state = efalse;
+						}
+					if (state)
+						state = NewLine();
+					}
+				}
+			else
+				{
+				Error("Fontstorefile identifier expected");
+				state = efalse;
+				}
+			if (state)
+				state = NewLine();
+			}
+		if (state)
+			{
+			iFontStore.AddFontStoreFile(iFontStoreFile);
+			cout << "Fontstorefile read\n";
+			}
+		else
+			delete iFontStoreFile;
+		}
+	return state;
+	}
+
+int FontReader::Store(const String& aFilename)
+	{
+	boolean state = etrue;
+	if (!iFontStoreFile)
+		{
+		state = efalse;
+		Error("No fontstore file record");
+		}
+	else
+		state = iFontStore.Store(aFilename);
+	return state;
+	}
+
+boolean FontReader::CharLine(String& aCharLine)
+	{
+	boolean state = etrue;
+	while (state && (iLex->iType != ELexNL))
+		{
+		char ch;
+		state = Operator(ch);
+		if (state)
+			{
+			if ((ch == '.') || (ch == '*'))
+				aCharLine += ch;
+			else
+				{
+				state = efalse;
+				Error("Operator '.' or '*' expected");
+				}
+			}
+		}
+	return state;
+	}
+
+void FontReader::ErrorIdentifierExpected(const String& aIdentifier)
+	{
+	cerr << "Error: Identifier Expected " << aIdentifier;
+	iLexAnal->Report();
+	while ((iLex->iType != ELexNL) && (iLex->iType != ELexEOF))
+		iLexAnal->Read();
+	}
+
+boolean FontReader::CompareBitmapLines(int aLine1, int aLine2)
+	{
+
+	int column = 0;
+	boolean identical = etrue;
+	for (column=0; column < iBitmapWidth; column++)
+		{
+		if (iBitArray[column][aLine1] != iBitArray[column][aLine2])
+			{
+			identical = efalse;
+			break;
+			}
+		}
+
+	return identical;
+	}
+
+boolean FontReader::BitmapLineEmpty(int aLine)
+	{
+
+	int column = 0;
+	boolean empty = etrue;
+	for (column = 0; column < iBitmapWidth; column++)
+		{
+		if (iBitArray[column][aLine] != 0)
+			{
+			empty = efalse;
+			break;
+			}
+		}
+
+	return empty;
+	}
+
+boolean FontReader::BitmapColumnEmpty(int aColumn)
+	{
+
+	int line = 0;
+	boolean empty = etrue;
+	for (line = 0; line < iBitmapHeight; line++)
+		{
+		if (iBitArray[aColumn][line] != 0)
+			{
+			empty = efalse;
+			break;
+			}
+		}
+
+	return empty;
+	}
+
+void FontReader::WriteFillCharacters(int aNumberConsecutive)
+	{
+	for (int counter = 0; counter < aNumberConsecutive; counter++)
+		{
+		BitmapOffset* offset = new BitmapOffset(KFillCharacterOffset);
+		iCodeSection->iCharacters.iBitmapOffsetList.Add(offset);
+		}
+	}
+
+boolean FontReader::ParseMetricsFromBDF(int aNumberCharsInFile, int aMaxConsecutiveFillChars)
+	{
+	boolean state = etrue;
+	int character = 0;
+	int numberCharactersRead;
+	int lastCharacter = KMarkFirstCharacterInTypeface;
+	int reportRate = ((aNumberCharsInFile - 1) / KReportRateFrequencyInPercent) + 1;
+
+	CharacterMetrics* metric = 0;
+	
+	cout << "Analysing character metrics...\n";
+	cout.flush();
+
+	for (numberCharactersRead = 0; numberCharactersRead < aNumberCharsInFile && !_EOF() && state; numberCharactersRead++)
+		{
+		state = IdentComp(IdentBDFCharLabel);
+		if (!state)
+			ErrorIdentifierExpected(IdentBDFCharLabel);
+		if (state)
+			iLexAnal->ReadNextLine();	// Skip to next line
+
+		if (IdentComp(IdentBDFChar))
+			{
+			state = Number(character);
+			}
+		else
+			{
+			state = efalse;
+			ErrorIdentifierExpected(IdentBDFChar);
+			}
+
+		if (character < KLowestPermittedCharacterEncoding || character > KHighestPermittedCharacterEncoding)
+			{
+			while (!IdentComp(IdentBDFEndChar) && !_EOF() && state) 
+				// Skip fill character.
+				{
+				iLexAnal->ReadNextLine(); // Skip to next line
+				}
+				iLexAnal->ReadNextLine();
+			continue;
+			}
+
+		if (character<lastCharacter)
+			{
+			Error("CodeSection out of sequence");
+			state = efalse;
+			}
+
+		if ((character > lastCharacter + 1) 
+			&& (character <= lastCharacter + 1 + aMaxConsecutiveFillChars) && state)
+			{
+			// Would result in fill characters being used if not at end of code section!
+			metric = new CharacterMetrics;
+			metric->iLeftAdjustInPixels = (chardim)0;
+			metric->iMoveInPixels = (chardim)0;
+			metric->iRightAdjustInPixels = (chardim)0;
+			metric->iAscentInPixels = (chardim)0;
+			metric->iHeightInPixels = (chardim)0;
+			iFontBitmap->iCharacterMetrics->AddOrIncrementMetric(*metric);
+			delete metric;
+			metric = 0;
+			}
+
+		if (state)
+			{
+			metric = new CharacterMetrics;
+			state = ReadMetricFromBDFCharacter(metric);
+			iFontBitmap->iCharacterMetrics->AddOrIncrementMetric(*metric);
+			delete metric;
+			metric = 0;
+			}
+		
+		lastCharacter = character;
+		if(numberCharactersRead == ((numberCharactersRead / reportRate) * reportRate))
+			{
+			cout << "Done " << (numberCharactersRead * 100 / aNumberCharsInFile) << "% \n";
+			cout.flush();
+			}
+		}
+
+	if (state)
+		{
+		iFontBitmap->iCharacterMetrics->SortMetricsByFrequency();
+		}
+	return state;
+	}