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