ftp.nice.ch/pub/next/graphics/convertors/Convert.s.tar.gz#/Converters/Convert_FONT/FontConverter.m

This is FontConverter.m in view mode; [Download] [Up]

/***********************************************************************
Converter class for Convert FONT which converts Mac fonts to NeXT fonts.
Copyright (C) 1993 David John Burrowes

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

The author, David John Burrowes, can be reached at:
	davidjohn@kira.net.netcom.com
	David John Burrowes
	1926 Ivy #10
	San Mateo, CA 94403-1367
***********************************************************************/


#import "FontConverter.h"
#import "PSFile.h"

#import <architecture/byte_order.h>

#include <stdio.h>
#include <string.h>
#include <time.h>		// for ctime


#define	VERSIONSTRING	"Convert FONT 1.1"

@implementation FontConverter

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Method:		init
//	Parameters:	none
//	Returns: 	self
//	Stores:		none
//	Description:
//		This initalizes the instance, of course, including mainly the initalization of
//		the 256 entry array of names of the characters in the character set.  This is
//		used when building both the .afm and the font.
//	Bugs:
//	History:
//		93.01.10	djb	Added StoredName initialization.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- init
{
	Integer		index;

	[super init];
	StoredName = NullCString;
	EncodingVector[0] = "NUL";
	EncodingVector[1] = "SOH";
	EncodingVector[2] = "STX";
	EncodingVector[3] = "ETX";
	EncodingVector[4] = "EOT";
	EncodingVector[5] = "ENQ";
	EncodingVector[6] = "ACK";
	EncodingVector[7] = "BEL";
	EncodingVector[8] = "BS";
	EncodingVector[9] = "HT";
	EncodingVector[10] = "LF";
	EncodingVector[11] = "VT";
	EncodingVector[12] = "FF";
	EncodingVector[13] = "CR";
	EncodingVector[14] = "SO";
	EncodingVector[15] = "SI";
	EncodingVector[16] = "DLE";
	EncodingVector[17] = "DC1";
	EncodingVector[18] = "DC2";
	EncodingVector[19] = "DC3";
	EncodingVector[20] = "DC4";
	EncodingVector[21] = "NAK";
	EncodingVector[22] = "SYN";
	EncodingVector[23] = "ETB";
	EncodingVector[24] = "CAN";
	EncodingVector[25] = "EM";
	EncodingVector[26] = "SUB";
	EncodingVector[27] = "ESC";
	EncodingVector[28] = "FS";
	EncodingVector[29] = "GS";
	EncodingVector[30] = "RS";
	EncodingVector[31] = "US";
	EncodingVector[32] = "space";
	EncodingVector[33] = "exclam";
	EncodingVector[34] = "quotedbl";
	EncodingVector[35] = "numbersign";
	EncodingVector[36] = "dollar";
	EncodingVector[37] = "percent";
	EncodingVector[38] = "ampersand";
	EncodingVector[39] = "quotesingle";
	EncodingVector[40] = "parenleft";
	EncodingVector[41] = "parenright";
	EncodingVector[42] = "asterisk";
	EncodingVector[43] = "plus";
	EncodingVector[44] = "comma";
	EncodingVector[45] = "hyphen";
	EncodingVector[46] = "period";
	EncodingVector[47] = "slash";
	EncodingVector[48] = "zero";
	EncodingVector[49] = "one";
	EncodingVector[50] = "two";
	EncodingVector[51] = "three";
	EncodingVector[52] = "four";
	EncodingVector[53] = "five";
	EncodingVector[54] = "six";
	EncodingVector[55] = "seven";
	EncodingVector[56] = "eight";
	EncodingVector[57] = "nine";
	EncodingVector[58] = "colon";
	EncodingVector[59] = "semicolon";
	EncodingVector[60] = "less";
	EncodingVector[61] = "equal";
	EncodingVector[62] = "greater";
	EncodingVector[63] = "question";
	EncodingVector[64] = "at";
	EncodingVector[65] = "A";
	EncodingVector[66] = "B";
	EncodingVector[67] = "C";
	EncodingVector[68] = "D";
	EncodingVector[69] = "E";
	EncodingVector[70] = "F";
	EncodingVector[71] = "G";
	EncodingVector[72] = "H";
	EncodingVector[73] = "I";
	EncodingVector[74] = "J";
	EncodingVector[75] = "K";
	EncodingVector[76] = "L";
	EncodingVector[77] = "M";
	EncodingVector[78] = "N";
	EncodingVector[79] = "O";
	EncodingVector[80] = "P";
	EncodingVector[81] = "Q";
	EncodingVector[82] = "R";
	EncodingVector[83] = "S";
	EncodingVector[84] = "T";
	EncodingVector[85] = "U";
	EncodingVector[86] = "V";
	EncodingVector[87] = "W";
	EncodingVector[88] = "X";
	EncodingVector[89] = "Y";
	EncodingVector[90] = "Z";
	EncodingVector[91] = "bracketleft";
	EncodingVector[92] = "backslash";
	EncodingVector[93] = "bracketright";
	EncodingVector[94] = "asciicircum";
	EncodingVector[95] = "underscore";
	EncodingVector[96] = "grave";
	EncodingVector[97] = "a";
	EncodingVector[98] = "b";
	EncodingVector[99] = "c";
	EncodingVector[100] = "d";
	EncodingVector[101] = "e";
	EncodingVector[102] = "f";
	EncodingVector[103] = "g";
	EncodingVector[104] = "h";
	EncodingVector[105] = "i";
	EncodingVector[106] = "j";
	EncodingVector[107] = "k";
	EncodingVector[108] = "l";
	EncodingVector[109] = "m";
	EncodingVector[110] = "n";
	EncodingVector[111] = "o";
	EncodingVector[112] = "p";
	EncodingVector[113] = "q";
	EncodingVector[114] = "r";
	EncodingVector[115] = "s";
	EncodingVector[116] = "t";
	EncodingVector[117] = "u";
	EncodingVector[118] = "v";
	EncodingVector[119] = "w";
	EncodingVector[120] = "x";
	EncodingVector[121] = "y";
	EncodingVector[122] = "z";
	EncodingVector[123] = "braceleft";
	EncodingVector[124] = "bar";
	EncodingVector[125] = "braceright";
	EncodingVector[126] = "asciitilde";
	EncodingVector[127] = "DEL";
	EncodingVector[128] = "Adieresis";
	EncodingVector[129] = "Aring";
	EncodingVector[130] = "Ccedilla";
	EncodingVector[131] = "Eacute";
	EncodingVector[132] = "Ntilde";
	EncodingVector[133] = "Odieresis";
	EncodingVector[134] = "Udieresis";
	EncodingVector[135] = "aacute";
	EncodingVector[136] = "agrave";
	EncodingVector[137] = "acircumflex";
	EncodingVector[138] = "adieresis";
	EncodingVector[139] = "atilde";
	EncodingVector[140] = "aring";
	EncodingVector[141] = "ccedilla";
	EncodingVector[142] = "eacute";
	EncodingVector[143] = "egrave";
	EncodingVector[144] = "ecircumflex";
	EncodingVector[145] = "edieresis";
	EncodingVector[146] = "iacute";
	EncodingVector[147] = "igrave";
	EncodingVector[148] = "icircumflex";
	EncodingVector[149] = "idieresis";
	EncodingVector[150] = "ntilde";
	EncodingVector[151] = "oacute";
	EncodingVector[152] = "ograve";
	EncodingVector[153] = "ocircumflex";
	EncodingVector[154] = "odieresis";
	EncodingVector[155] = "otilde";
	EncodingVector[156] = "uacute";
	EncodingVector[157] = "ugrave";
	EncodingVector[158] = "ucircumflex";
	EncodingVector[159] = "udieresis";
	EncodingVector[160] = "dagger";
	EncodingVector[161] = "degree";
	EncodingVector[162] = "cent";
	EncodingVector[163] = "sterling";
	EncodingVector[164] = "section";
	EncodingVector[165] = "bullet";
	EncodingVector[166] = "paragraph";
	EncodingVector[167] = "germandbls";
	EncodingVector[168] = "registered";
	EncodingVector[169] = "copyright";
	EncodingVector[170] = "trademark";
	EncodingVector[171] = "acute";
	EncodingVector[172] = "dieresis";
	EncodingVector[173] = "notequal";
	EncodingVector[174] = "AE";
	EncodingVector[175] = "Oslash";
	EncodingVector[176] = "infinity";
	EncodingVector[177] = "plusminus";
	EncodingVector[178] = "lessequal";
	EncodingVector[179] = "greaterequal";
	EncodingVector[180] = "yen";
	EncodingVector[181] = "mu";
	EncodingVector[182] = "partialdiff";
	EncodingVector[183] = "summation";
	EncodingVector[184] = "product";
	EncodingVector[185] = "pi";
	EncodingVector[186] = "integral";
	EncodingVector[187] = "ordfeminine";
	EncodingVector[188] = "ordmasculine";
	EncodingVector[189] = "Omega";
	EncodingVector[190] = "ae";
	EncodingVector[191] = "oslash";
	EncodingVector[192] = "questiondown";
	EncodingVector[193] = "exclamdown";
	EncodingVector[194] = "logicalnot";
	EncodingVector[195] = "radical";
	EncodingVector[196] = "florin";
	EncodingVector[197] = "approxequal";
	EncodingVector[198] = "Delta";
	EncodingVector[199] = "guillemotleft";
	EncodingVector[200] = "guillemotright";
	EncodingVector[201] = "ellipsis";
	EncodingVector[202] = "nbspace";
	EncodingVector[203] = "Agrave";
	EncodingVector[204] = "Atilde";
	EncodingVector[205] = "Otilde";
	EncodingVector[206] = "OE";
	EncodingVector[207] = "oe";
	EncodingVector[208] = "endash";
	EncodingVector[209] = "emdash";
	EncodingVector[210] = "quotedblleft";
	EncodingVector[211] = "quotedblright";
	EncodingVector[212] = "quoteleft";
	EncodingVector[213] = "quoteright";
	EncodingVector[214] = "divide";
	EncodingVector[215] = "lozenge";
	EncodingVector[216] = "ydieresis";
	EncodingVector[217] = "Ydieresis";
	EncodingVector[218] = "fraction";
	EncodingVector[219] = "currency";
	EncodingVector[220] = "guilsinglleft";
	EncodingVector[221] = "guilsinglright";
	EncodingVector[222] = "fi";
	EncodingVector[223] = "fl";
	EncodingVector[224] = "daggerdbl";
	EncodingVector[225] = "periodcentered";
	EncodingVector[226] = "quotesinglbase";
	EncodingVector[227] = "quotedblbase";
	EncodingVector[228] = "perthousand";
	EncodingVector[229] = "Acircumflex";
	EncodingVector[230] = "Ecircumflex";
	EncodingVector[231] = "Aacute";
	EncodingVector[232] = "Edieresis";
	EncodingVector[233] = "Egrave";
	EncodingVector[234] = "Iacute";
	EncodingVector[235] = "Icircumflex";
	EncodingVector[236] = "Idieresis";
	EncodingVector[237] = "Igrave";
	EncodingVector[238] = "Oacute";
	EncodingVector[239] = "Ocircumflex";
	EncodingVector[240] = "apple";
	EncodingVector[241] = "Ograve";
	EncodingVector[242] = "Uacute";
	EncodingVector[243] = "Ucircumflex";
	EncodingVector[244] = "Ugrave";
	EncodingVector[245] = "dotlessi";
	EncodingVector[246] = "circumflex";
	EncodingVector[247] = "tilde";
	EncodingVector[248] = "macron";
	EncodingVector[249] = "breve";
	EncodingVector[250] = "dotaccent";
	EncodingVector[251] = "ring";
	EncodingVector[252] = "cedilla";
	EncodingVector[253] = "hungarumlaut";
	EncodingVector[254] = "ogonek";
	EncodingVector[255] = "caron";
	//
	//	93.03.14	Added all code for NSEncodingVector support
	//
	//
	//	Set up the NS encoding vector so that it uses the same names below 128.
	//
	for (index = 0; index < 128; index++)
		NSEncodingVector[index] = EncodingVector[index];
	//
	//	Now, insert those strings for the NeXT encoding vector above 128.
	//	If I had my act together, most of these could be set up as pointers to the
	//	strings set up above.
	//
	NSEncodingVector[39] = "quoteright";
	NSEncodingVector[96] = "quoteleft";
	NSEncodingVector[128] = "figsep";
	NSEncodingVector[129] = "Agrave";
	NSEncodingVector[130] = "Aacute";
	NSEncodingVector[131] = "Acircumflex";
	NSEncodingVector[132] = "Atilde";
	NSEncodingVector[133] = "Adieresis";
	NSEncodingVector[134] = "Aring";
	NSEncodingVector[135] = "Ccedilla";
	NSEncodingVector[136] = "Egrave";
	NSEncodingVector[137] = "Eacute";
	NSEncodingVector[138] = "Ecircumflex";
	NSEncodingVector[139] = "Edieresis";
	NSEncodingVector[140] = "Igrave";
	NSEncodingVector[141] = "Iacute";
	NSEncodingVector[142] = "Icircumflex";
	NSEncodingVector[143] = "Idieresis";
	NSEncodingVector[144] = "Eth";
	NSEncodingVector[145] = "Ntilde";
	NSEncodingVector[146] = "Ograve";
	NSEncodingVector[147] = "Oacute";
	NSEncodingVector[148] = "Ocircumflex";
	NSEncodingVector[149] = "Otilde";
	NSEncodingVector[150] = "Odieresis";
	NSEncodingVector[151] = "Ugrave";
	NSEncodingVector[152] = "Uacute";
	NSEncodingVector[153] = "Ucircumflex";
	NSEncodingVector[154] = "Udieresis";
	NSEncodingVector[155] = "Yacute";
	NSEncodingVector[156] = "Thorn";
	NSEncodingVector[157] = "mu";
	NSEncodingVector[158] = "multiply";
	NSEncodingVector[159] = "divide";
	NSEncodingVector[160] = "copyright";
	NSEncodingVector[161] = "exclamdown";
	NSEncodingVector[162] = "cent";
	NSEncodingVector[163] = "sterling";
	NSEncodingVector[164] = "fraction";
	NSEncodingVector[165] = "yen";
	NSEncodingVector[166] = "florin";
	NSEncodingVector[167] = "section";
	NSEncodingVector[168] = "currency";
	NSEncodingVector[169] = "quotesingle";
	NSEncodingVector[170] = "quotedblleft";
	NSEncodingVector[171] = "guillemotleft";
	NSEncodingVector[172] = "guilsinglleft";
	NSEncodingVector[173] = "guilsinglright";
	NSEncodingVector[174] = "fi";
	NSEncodingVector[175] = "fl";
	NSEncodingVector[176] = "registered";
	NSEncodingVector[177] = "endash";
	NSEncodingVector[178] = "dagger";
	NSEncodingVector[179] = "daggerdbl";
	NSEncodingVector[180] = "periodcentered";
	NSEncodingVector[181] = "brokenbar";
	NSEncodingVector[182] = "paragraph";
	NSEncodingVector[183] = "bullet";
	NSEncodingVector[184] = "quotesinglbase";
	NSEncodingVector[185] = "quotedblbase";
	NSEncodingVector[186] = "quotedblright";
	NSEncodingVector[187] = "guillemotright";
	NSEncodingVector[188] = "ellipsis";
	NSEncodingVector[189] = "perthousand";
	NSEncodingVector[190] = "logicalnot";
	NSEncodingVector[191] = "questiondown";
	NSEncodingVector[192] = "onesuperior";
	NSEncodingVector[193] = "grave";
	NSEncodingVector[194] = "acute";
	NSEncodingVector[195] = "circumflex";
	NSEncodingVector[196] = "tilde";
	NSEncodingVector[197] = "macron";
	NSEncodingVector[198] = "breve";
	NSEncodingVector[199] = "dotaccent";
	NSEncodingVector[200] = "dieresis";
	NSEncodingVector[201] = "twosuperior";
	NSEncodingVector[202] = "ring";
	NSEncodingVector[203] = "cedilla";
	NSEncodingVector[204] = "threesuperior";
	NSEncodingVector[205] = "hungarumlaut";
	NSEncodingVector[206] = "ogonek";
	NSEncodingVector[207] = "caron";
	NSEncodingVector[208] = "emdash";
	NSEncodingVector[209] = "plusminus";
	NSEncodingVector[210] = "onequarter";
	NSEncodingVector[211] = "onehalf";
	NSEncodingVector[212] = "threequarters";
	NSEncodingVector[213] = "agrave";
	NSEncodingVector[214] = "aacute";
	NSEncodingVector[215] = "acircumflex";
	NSEncodingVector[216] = "atilde";
	NSEncodingVector[217] = "adieresis";
	NSEncodingVector[218] = "aring";
	NSEncodingVector[219] = "ccedilla";
	NSEncodingVector[220] = "egrave";
	NSEncodingVector[221] = "eacute";
	NSEncodingVector[222] = "ecircumflex";
	NSEncodingVector[223] = "edieresis";
	NSEncodingVector[224] = "igrave";
	NSEncodingVector[225] = "AE";
	NSEncodingVector[226] = "iacute";
	NSEncodingVector[227] = "ordfeminine";
	NSEncodingVector[228] = "icircumflex";
	NSEncodingVector[229] = "idieresis";
	NSEncodingVector[230] = "eth";
	NSEncodingVector[231] = "ntilde";
	NSEncodingVector[232] = "Lslash";
	NSEncodingVector[233] = "Oslash";
	NSEncodingVector[234] = "OE";
	NSEncodingVector[235] = "ordmasculine";
	NSEncodingVector[236] = "ograve";
	NSEncodingVector[237] = "oacute";
	NSEncodingVector[238] = "ocircumflex";
	NSEncodingVector[239] = "otilde";
	NSEncodingVector[240] = "odieresis";
	NSEncodingVector[241] = "ae";
	NSEncodingVector[242] = "ugrave";
	NSEncodingVector[243] = "uacute";
	NSEncodingVector[244] = "ucircumflex";
	NSEncodingVector[245] = "dotlessi";
	NSEncodingVector[246] = "udieresis";
	NSEncodingVector[247] = "yacute";
	NSEncodingVector[248] = "lslash";
	NSEncodingVector[249] = "oslash";
	NSEncodingVector[250] = "oe";
	NSEncodingVector[251] = "germandbls";
	NSEncodingVector[252] = "thorn";
	NSEncodingVector[253] = "ydieresis";
	NSEncodingVector[254] = "noddefined";
	NSEncodingVector[255] = "asciicontrolchar";

	//
	//	93.04.03	djb
	//	Oh no!  Not another bloody array initalization!  What a WASTE!
	//	Yep.
	//	What the nasty thing for???
	//	This allows us to convert a Mac character to a NeXT character.
	//	But... What happened to your MacToNeXT converter object?
	//	Good thought, but it doesn't do quotes the way I need. And, this is easier than a subclass..
	//		I do'nt care THAT much anyway at this point.  Just wanna get it done.
	//
	//	(mac character names in ()'s, corresponding to the values in []'s
	//
	for (index = 0; index < 256; index++)
		MacToNeXTLookup[index] = index;

	MacToNeXTLookup[0x11] = NullCharacter;	// (commandsymbol)
	MacToNeXTLookup[0x12] = NullCharacter;	// (check)
	MacToNeXTLookup[0x13] = NullCharacter;	// (diamond)
	MacToNeXTLookup[0x14] = NullCharacter;	// (apple)

	MacToNeXTLookup[0x27] = 169;			// (quotesingle)
	MacToNeXTLookup[0x60] = 193;			// (grave)

	MacToNeXTLookup[0x80] = 0x85;			// (Adieresis)
	MacToNeXTLookup[0x81] = 0x86;			// (Aring)
	MacToNeXTLookup[0x82] = 0x87;			// (Ccedilla)
	MacToNeXTLookup[0x83] = 0x89;			// (Eacute)
	MacToNeXTLookup[0x84] = 0x91;			// (Ntilde)
	MacToNeXTLookup[0x85] = 0x96;			// (Odieresis)
	MacToNeXTLookup[0x86] = 0x9A;			// (Udieresis)
	MacToNeXTLookup[0x87] = 0xD6;			// (aacute)
	MacToNeXTLookup[0x88] = 0xD5;			// (agrave)
	MacToNeXTLookup[0x89] = 0xD7;			// (acircumflex)
	MacToNeXTLookup[0x8A] = 0xD9;			// (adieresis)
	MacToNeXTLookup[0x8B] = 0xD8;			// (atilde)
	MacToNeXTLookup[0x8C] = 0xDA;			// (aring)
	MacToNeXTLookup[0x8D] = 0xDB;			// (ccedilla)
	MacToNeXTLookup[0x8E] = 0xDD;			// (eacute)
	MacToNeXTLookup[0x8F] = 0xDC;			// (egrave)
	//	0x9X
	MacToNeXTLookup[0x90] = 0xDE;			// (ecircumflex)
	MacToNeXTLookup[0x91] = 0xDF;			// (dieresis)
	MacToNeXTLookup[0x92] = 0xE2;			// (iacute)
	MacToNeXTLookup[0x93] = 0xE0;			// (igrave)
	MacToNeXTLookup[0x94] = 0xE4;			// (icircumflex)
	MacToNeXTLookup[0x95] = 0xE5;			// (idieresis)
	MacToNeXTLookup[0x96] = 0xE7;			// (ntilde)
	MacToNeXTLookup[0x97] = 0xED;			// (oacute)
	MacToNeXTLookup[0x98] = 0xEC;			// (ograve)
	MacToNeXTLookup[0x99] = 0xEE;			// (ocircumflex)
	MacToNeXTLookup[0x9A] = 0xF0;			// (odieresis)
	MacToNeXTLookup[0x9B] = 0xEF;			// (otilde)
	MacToNeXTLookup[0x9C] = 0xF3;			// (uacute)
	MacToNeXTLookup[0x9D] = 0xF2;			// (ugrave)
	MacToNeXTLookup[0x9E] = 0xF4;			// (ucircumflex)
	MacToNeXTLookup[0x9F] = 0xF6;			// (udieresis)
	//	0xAX
	MacToNeXTLookup[0xA0] = 0xB2;			// (dagger)
	MacToNeXTLookup[0xA1] = NullCharacter;	// (degree)
	MacToNeXTLookup[0xA2] = 0xA2;			// (cent)
	MacToNeXTLookup[0xA3] = 0xA3;			// (sterling)
	MacToNeXTLookup[0xA4] = 0xA7;			// (section)
	MacToNeXTLookup[0xA5] = 0xB7;			// (bullet)
	MacToNeXTLookup[0xA6] = 0xB6;			// (paragraph)
	MacToNeXTLookup[0xA7] = 0xFB;			// (germandbls)
	MacToNeXTLookup[0xA8] = 0xB0;			// (registerserif)
	MacToNeXTLookup[0xA9] = 0xA0;			// (copyrightserif)
	MacToNeXTLookup[0xAA] = NullCharacter;	// (trademarkserif)
	MacToNeXTLookup[0xAB] = 0xC2;			// (acute)
	MacToNeXTLookup[0xAC] = 0xC8;			// (dieresis)
	MacToNeXTLookup[0xAD] = NullCharacter;	// (notequal)
	MacToNeXTLookup[0xAE] = 0xE1;			// (AE)
	MacToNeXTLookup[0xAF] = 0xE9;			// (Oslash)
	//	0xBX
	MacToNeXTLookup[0xB0] = NullCharacter;	//(infinity)
	MacToNeXTLookup[0xB1] = 0xD1;			// (plusminus)
	MacToNeXTLookup[0xB2] = NullCharacter;	// (lessequal)
	MacToNeXTLookup[0xB3] = NullCharacter;	// (greaterequal)
	MacToNeXTLookup[0xB4] = 0xA5;			// (yen)
	MacToNeXTLookup[0xB5] = 0x9D;			// (mu)
	MacToNeXTLookup[0xB6] = NullCharacter;	// (partialdiff)
	MacToNeXTLookup[0xB7] = NullCharacter;	// (summation)
	MacToNeXTLookup[0xB8] = NullCharacter;	// (product) 
	MacToNeXTLookup[0xB9] = NullCharacter;	// (pi)
	MacToNeXTLookup[0xBA] = NullCharacter;	// (integral)
	MacToNeXTLookup[0xBB] = 0xE3;			// (ordfeminine)
	MacToNeXTLookup[0xBC] = 0xEB;			// (ordmasculine)
	MacToNeXTLookup[0xBD] = NullCharacter;	// (Omega)
	MacToNeXTLookup[0xBE] = 0xF1;			// (ae)
	MacToNeXTLookup[0xBF] = 0xF9;			// (oslash)
	//	0xC0
	MacToNeXTLookup[0xC0] = 0xBF;			// (questiondown)
	MacToNeXTLookup[0xC1] = 0xA1;			// (exclamdown)
	MacToNeXTLookup[0xC2] = 0xBE;			// (logicalnot)
	MacToNeXTLookup[0xC3] = NullCharacter;	// (radical)
	MacToNeXTLookup[0xC4] = 0xA6;			// (florin)
	MacToNeXTLookup[0xC5] = NullCharacter;	// (approxequal)
	MacToNeXTLookup[0xC6] = NullCharacter;	// (delta)
	MacToNeXTLookup[0xC7] = 0xAB;			// (guillemotleft)
	MacToNeXTLookup[0xC8] = 0xBB;			// (guillemotright)
	MacToNeXTLookup[0xC9] = 0xBC;			// (elipsis)
	MacToNeXTLookup[0xCA] = 0x80;			// (nbspace)   next calls it: (figsp)
	MacToNeXTLookup[0xCB] = 0x81;			// (Agrave)
	MacToNeXTLookup[0xCC] = 0x84;			// (Atilde)
	MacToNeXTLookup[0xCD] = 0x95;			// (Otilde)
	MacToNeXTLookup[0xCE] = 0xEA;			// (OE)
	MacToNeXTLookup[0xCF] = 0xFA;			// (oe)
	//	0xD0
	MacToNeXTLookup[0xD0] = 0xB1;			// (endash)
	MacToNeXTLookup[0xD1] = 0xD0;			// (emdash)
	MacToNeXTLookup[0xD2] = 0xAA;			// (quotedblleft)
	MacToNeXTLookup[0xD3] = 0xBA;			// (quotedblright)
	MacToNeXTLookup[0xD4] = 0x60;			// (quoteleft)
	MacToNeXTLookup[0xD5] = 0x27;			// (quoteright)
	MacToNeXTLookup[0xD6] = 0x9F;			// (divide)
	MacToNeXTLookup[0xD7] = NullCharacter;	// (lozenge)
	MacToNeXTLookup[0xD8] = 0xFD;			// (ydieresis)
	MacToNeXTLookup[0xD9] = NullCharacter;	// (Ydieresis)  (usually a picture in IM fonts)
	MacToNeXTLookup[0xDA] = 0xA4;			// (fraction)
	MacToNeXTLookup[0xDB] = 0xA8;			// (currency)
	MacToNeXTLookup[0xDC] = 0xAC;			// (guilsinglleft)
	MacToNeXTLookup[0xDD] = 0xAD;			// (guilsinglright)
	MacToNeXTLookup[0xDE] = 0xAE;			// (fi)
	MacToNeXTLookup[0xDF] = 0xAF;			// (fl)
	//	0xE0
	MacToNeXTLookup[0xE0] = 0xB3;			// (daggerdbl)
	MacToNeXTLookup[0xE1] = 0xB4;			// (periodcentered)
	MacToNeXTLookup[0xE2] = 0xB8;			// (quotesinglebase)
	MacToNeXTLookup[0xE3] = 0xB9;			// (quotedblbase)
	MacToNeXTLookup[0xE4] = 0xBD;			// (perthousand)
	MacToNeXTLookup[0xE5] = 0x83;			// (Acircumflex)
	MacToNeXTLookup[0xE6] = 0x8A;			// (Ecircumflex)
	MacToNeXTLookup[0xE7] = 0x82;			// (Aacute)
	MacToNeXTLookup[0xE8] = 0x8B;			// (Edieresis)
	MacToNeXTLookup[0xE9] = 0x88;			// (Egrave)
	MacToNeXTLookup[0xEA] = 0x8D;			// (Iacute)
	MacToNeXTLookup[0xEB] = 0x8E;			// (Icircumflex)
	MacToNeXTLookup[0xEC] = 0x8F;			// (Idieresis)
	MacToNeXTLookup[0xED] = 0x8C;			// (Igrave)
	MacToNeXTLookup[0xEE] = 0x93;			// (Oacute)
	MacToNeXTLookup[0xEF] = 0x94;			// (Ocircumflex)
	//	0xF0
	MacToNeXTLookup[0xF0] = NullCharacter;	// (apple)
	MacToNeXTLookup[0xF1] = 0x92;			// (Ograve)
	MacToNeXTLookup[0xF2] = 0x98;			// (Uacute)
	MacToNeXTLookup[0xF3] = 0x99;			// (Ucircumflex)
	MacToNeXTLookup[0xF4] = 0x97;			// (Ugrave)
	MacToNeXTLookup[0xF5] = 0xF5;			// (dotlessi)
	MacToNeXTLookup[0xF6] = 0xC3;			// (circumflex)
	MacToNeXTLookup[0xF7] = 0xC4;			// (tilde)
	MacToNeXTLookup[0xF8] = 0xC5;			// (macron)
	MacToNeXTLookup[0xF9] = 0xC6;			// (breve)
	MacToNeXTLookup[0xFA] = 0xC7;			// (dotaccent)
	MacToNeXTLookup[0xFB] = 0xCA;			// (ring)
	MacToNeXTLookup[0xFC] = 0xCB;			// (cedilla)
	MacToNeXTLookup[0xFD] = 0xCD;			// (hungarumlaut)
	MacToNeXTLookup[0xFE] = 0xCE;			// (ogonek)
	MacToNeXTLookup[0xFF] = 0xCF;			// (caron)

	//
	//	Set the default of whether to use the NSEncoding to true
	//
	UseNSEncoding = YES;

	return self;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Method:		free
//	Parameters:	none
//	Returns: 	self
//	Stores:		none
//	Description:
//		This free's the stored name if appropaite.  We don't free the encoding vector
//		because it's all string constants.
//	Bugs:
//	History:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- free
{
	if (StoredName != NullCString)
		FreeCString(StoredName);
	return [super free];
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Method:		SetNSEncodingUse:
//	Parameters:	A boolean flag
//	Returns: 	self
//	Stores:		none
//	Description:
//		This quick hack of a routine allows the caller to specify whether this converter
//		should use the NeXTSTEP or the Apple encoding vector.  YES means use NS,
//		NO means use Apple.  Ideally, this should have a corresponding GetNSEncodingUse
//		method, and perhaps this should take a string to allow for other vectors.  But, as
//		indicated, this is only the code necessary to get the current job done.
//	Bugs:
//	History:
//		93.03.14	djb	Created
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- SetNSEncodingUse: (Boolean) NSEncodingFlag
{
	if (NSEncodingFlag == YES)
		UseNSEncoding = YES;
	else
		UseNSEncoding = NO;

	return self;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Method:		isThisAGoodFile
//	Parameters:	A file instance
//	Returns: 	YES if the file is good, NO if it is not or if it is questionable.
//	Stores:		the return value
//				A descriptive string
//	Description:
//		This routine tries to judge if the specified file is a good one or not.  It then
//		returns a string in storage and returns a result.
//		the first 16 bits of a font define what kinda font it is.  We look for the two types
//		that I've worked with, and hope that what we have is indeed a font.  note that
//		the bit flags of those 2 bytes are defined as follows by apple:
//			boolean = 1;					/* Reserved */
//			boolean		doExpandFont, dontExpandFont;
//			boolean		proportionalFont, fixedWidthFont;
//			boolean = 1;					/* Reserved */
//			unsigned bitstring[2] = 0;		/* Reserved */
//			boolean		blackFont, colorFont;
//			boolean		notSynthetic, isSynthetic;
//			boolean		nofctbRsrc, hasfctbRsrc;
//			unsigned bitstring[3] = 0;		/* Reserved */
//			unsigned bitstring[2]	oneBit, twoBit, fourBit, eightBit;
//										/* Font depth */
//			boolean		noCharWidthTable, hasCharWidthTable;
//			boolean		noImageHeightTable, hasImageHeightTable;
//	Bugs:
//		Actually, the last two bit fields don't matter at all, in that one can ignore them
//		safely (and I do).  it might be nice to improve the program at a later date so it
//		maintains the extra width info...
//		On further reflection, it would make a LOT more sense to read in the whole
//		font structure, and then assure that there are a positive number of characters,
//		that the asent is positive , nDescent negative or zero, etc.  In addtion to what
//		we're already doing.
//	History
//		93.01.09	djb	oops.  Was freeing buffer after had put it into the second result, which
//					meant sometimes freeing it before it could be used.
//		93.08.01	djb	Added NXSwap... call to hide endian issues...
//		93.08.15	djb	Argh!  I need to be casting the results!!!
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (Boolean) isThisAGoodFile: theFile
{
	FilePos			location	= 0;
	bits16			fontType;
	CString			buffer;
	Boolean			result	= NO;
	//
	//	First, get the integer that defines the type of font we are working with...
	//	(this is the best identifier we can get from the font data structure)
	//
	location = [theFile GetCurrentPosition];
	[theFile   MoveTo: 0];
	[theFile   Read: 2 BytesInto: (ByteString) &fontType];
	fontType = (INTEGER) NXSwapBigShortToHost(fontType);
	[theFile   MoveTo: location];
	//
	//	with the font type in hand, return the proper values...
	//
	switch (fontType)
	{
		case 0x9000 :
		case 0xB000 :
			result = YES;
			break;
		case 0x9001:
		case 0xB001:
			[self  PutCString: "This font has a `height table\', which  Convert FONT can not convert.  You can probably convert the font safely, but the converted heights may be wrong." Into: SECOND_RESULT];
			result = NO;
			break;
		case 0x9002:
		case 0xB002:
			[self  PutCString: "This font has a `width table\', Convert FONT can not convert.  You can probably convert the font safely, but the converted widths may be wrong." Into: SECOND_RESULT];
			result = NO;
			break;
		case 0x9003:
		case 0xB003:
			[self  PutCString: "This font has both a `width\' and a `height\' table, which Convert FONT can not convert.  You can probably convert the font safely, but the character dimensions may be wrong." Into: SECOND_RESULT];
			result = NO;
			break;
		default:
			buffer = NewCString(127);
			//	93.01.24	djb	Compiler doesn't like the %2x and fontType.  Not sure why.
			//				I tried a 0x2324 as a param, and it didn't like that either.
			sprintf(buffer, "This may not be a convertable font.  Proceed with caution.  If you are sure this is a good font, and it fails to convert, give the author this: (%2X)", (unsigned int) fontType);
			[self  PutCString: buffer Into: SECOND_RESULT];
			result = NO;
			break;
	}

	return result;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Method:		Copy:BitsAtOffset:From:Into:
//	Parameters:	The number of bits in the source data to be copied
//				The number of bits, offset from the start of source, where source data starts
//				The source byte string to copy from
//				The destination byte string to copy into
//	Returns: 	The destination pointer (identical to the one passed)
//	Stores:		error code
//				1 The destination pointer (as a Pointer)
//				2 The count of the number of bytes stored in the destination
//	Description:
//		This routine can be used to extract arbitrary bit patterns out of a source string.
//		It was created to serve two different purposes: to allow one to get a bitmap from
//		a PICT image so it was left justified in its storage space, rather than offset some
//		number of bits in.  The other use was to extract the characters of a Mac font,
//		one scanline at a time, from the single bitmap tht makes up a Mac font.
//		Ultimately, the work is simple: take a source string, and an offset into it where
//		the data resides (and the length of the source data).  Copy the relevant bits from
//		the source to the dest.  Note that this aligns the left of the source data to the
//		beginning of a byte boundrary in dest.  Also note that it fills up an integral number
//		of bytes in dest, filling the last out with 0's if needed.
//	Bugs:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (ByteString) Copy: (PositiveInteger) sourceSize
	BitsAtOffset: (PositiveInteger) offset
	From: (ByteString) source
	Into: (ByteString) dest
{
	PositiveInteger	firstByte, lastByte;	// First and last bytes in source string to be copied
	PositiveInteger	index, destIndex;		// indices into source and dest strings
	PositiveInteger	offsetInByte;			// Number of bits into a byte a dest byte starts
	Byte			byte1, byte2;			// Temporary bytes to hold info as copied
	
	Byte	mask;
	PositiveInteger	bitpos, bitsMoved, finalBits;
	
	[self	ResetResults];
	
	if (sourceSize == 0)
	{
		[self   StoreErrorCode: ERR_BADSOURCESIZE
			AndText: "You requested for 0 bytes.  This has been fulfilled, weird as it is."];
		dest[0] = 0;
		[self   StorePointer: (Pointer) dest];
		[self   PutPositiveInteger: 0 Into: SECOND_RESULT];
	}
	else
	{
		//
		//	Computer our start and end position in source string, in bytes, and compute what
		//	bit offset in the first byte we should start working at
		//
		firstByte = offset / 8;
		lastByte = ((offset+sourceSize-1) / 8);
		offsetInByte = offset % 8;	// Zero origin...
		//
		//	Bear in mind that it's most likely that the destination byte will straddle two bytes
		//	in the source string.  So.  Get two bytes at a time from the source, and bitshift
		//	so they each contain only the bits that are relevant to the destination byte (get its
		//	upper and lower parts), then fuse the two parts together into a single destination
		//	byte.  Increment our destination index, and store the upper of the two bytes, for
		//	it will be the lower one the next time around. 
		//	Following this, deal with any remaining bits that might belong to the final
		//	dest byte, and pad them with zero.
		//
		destIndex = 0;
		//
		//	Two major cases: our data resides in only a single byte, or it spans
		//	two or more bytes:
		//
		if (firstByte == lastByte)
		{
			//
			//	First, shift the data in the byte down so it is aligned with the start
			//	of the byte.
			//	Then Build a mask to clear out any extraneous bits that were above the
			//	source data.  We're too lazy to actully determine whether there is any
			//	junk (there would be if the offset to the data + the length < 8 bits), and
			//	so, build a mask of sourceSize length, and use it.
			//
			byte1 = source[firstByte] << offsetInByte;
			mask = 0x00;
			for (bitpos = 0; bitpos < sourceSize; bitpos ++)
			{
				mask = mask >> 1;
				mask |= 0x80;
			}
			dest[destIndex] = byte1 &  mask;
			destIndex++;
		}
		else
		{
			//
			//	Start off by pulling off contiguous groups of 8 bits from
			//	the source, and storing them as bytes in the destination.
			//
			for (index = firstByte; index < lastByte; index++)
			{
				byte1 = source[index] << offsetInByte;
				byte2 = source[index+1] >> ( 8 - offsetInByte);
				
				dest[destIndex] = byte1 | byte2;
				destIndex++;
			}
			//
			//	There are 3 possible states at this point:
			//	- We happen to have copied exactly the number of source bits to the dest.
			//	- We have copied too many bits to the dest (i.e. our final byte2 group had
			//		too many source bits in it)
			//	- We have not copied enough bits (i.e. there were bits in source[lastByte] that
			//		were not moved with those in byte2).
			//	Process each of these accordingly.
			//
			//	Calculate:
			//		Bits copied to dest in byte2:
			//		Bits source bits actually in source[lastbyte]
			//
			bitsMoved = offsetInByte;
			finalBits = (offset+sourceSize) - (lastByte*8);
			//
			//	There are a few bits which we have not yet moved.
			//
			if (finalBits > bitsMoved)
			{
				byte1 = source[index] << bitsMoved;
				mask = 0x00;
				for (bitpos = 0; bitpos < (finalBits - bitsMoved); bitpos ++)
				{
					mask = mask >> 1;
					mask |= 0x80;
				}
				dest[destIndex] = byte1 & mask;
				destIndex++;
			}
			//
			//	Check if we moved more bits than we should have
			//
			else  if (finalBits < bitsMoved)
			{
				mask = 0x00;
				for (bitpos = 0; bitpos < finalBits+( 8 - offsetInByte); bitpos ++)
				{
					mask = mask >> 1;
					mask |= 0x80;
				}
				dest[destIndex-1] = dest[destIndex-1] & mask;
			}
		}
	
		[self   StoreErrorCode: ERR_OK AndText: "No errors (big surprise)"];
		[self   StorePointer: (Pointer) dest];
		[self   PutPositiveInteger: destIndex Into: SECOND_RESULT];
	}

	return dest;
}



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Method:		BuildAFMFileFrom:Into:
//	Parameters:	A Mac font record that we should build an afm file based on
//				a text file instance that has already been created and opened to put
//					the AFM file information into
//	Returns: 	self
//	Stores:		?????
//	Description:
//	Bugs:
//		For the capheight, xheight, ascender and descender values, we use the
//		simple absolute height and depth of the font box to fill these in.  If we were
//		a bit more adventurous, we could extract the bitmap information for the
//		relevant H, x d and p characters, by examining when we cease getting
//		blank lines back from the bit extractor.
//		Feeling really adventurous, we could provide real bounding boxes for all
//		characters, as justdescribed.  I think this ia version 2 feature.
//	History:
//		93.01.24	djb	Oddly, nDescent is sometimes the negative of the ascent!!  descent
//					always seems good, so replacing the one with the other.
//		93.04.03	djb	Modified so that when converting to a NeXTSTEP encoding, it will convert to
//						the proper characters above 128.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- BuildAFMFileFrom: (FontRecPtr) macFont Into: afmFile
{
	CString		fontName;
	Integer 	thechar,
				index,
				numChars;
	OWEntry	*OffsetWidthTable;
	CString		buffer 			= NewCString(1024);
 	Real			conversionFactor	=  (1.0/macFont->fRectHeight) * 1000;
	CString		theName;		// Used to point to a constant string to be written ou.
	Boolean		characterUsed[255];
	Character		macCharacterFor[255];
	Character	NeXTCharacter;
	
	[self	ResetResults];

	for (index = 0; index < 256; index++)
	{
		characterUsed[index] = NO;
		macCharacterFor[index] = NullCharacter;
	}

	fontName = [afmFile	GetBasename];
	
	OffsetWidthTable = (OWEntry*)  (&(macFont->owTLoc) + macFont->owTLoc);

	[afmFile   WriteTextLine: "StartFontMetrics 1.0"];
	[afmFile   WriteTextLine: "Version 1.0"];
	[afmFile   WriteTextUsing: buffer
			WithFormat: "Comment (Converted from Macintosh bitmap font using %s)\n",
			VERSIONSTRING];
	[afmFile   WriteTextUsing: buffer WithFormat: "FontName %s\n", fontName];
	[afmFile   WriteTextUsing: buffer WithFormat: "FullName %s\n", StoredName];
	[afmFile   WriteTextUsing: buffer WithFormat: "FamilyName %s\n", StoredName];
	[afmFile   WriteTextLine: "Weight Roman"];
	[afmFile   WriteTextLine: "ItalicAngle 0"];
	if  ((macFont->fontType & fixedFont) == fixedFont)
		[afmFile   WriteTextLine: "IsFixedPitch true"];  
	else
		[afmFile   WriteTextLine: "IsFixedPitch false"];  
	[afmFile   WriteTextUsing: buffer  WithFormat: "FontBBox 0 %.3f %.3f %.3f\n",
				(-1*macFont->descent) * conversionFactor,
				macFont->fRectWidth * conversionFactor,
				macFont->ascent * conversionFactor];
	//
	//	Added code for NS Encoding.
	//
	if (UseNSEncoding == YES)
		[afmFile   WriteTextLine: "EncodingScheme AdobeStandardEncoding"];
	else
		[afmFile   WriteTextLine: "EncodingScheme FontSpecific"];

	[afmFile   WriteTextLine: "UnderlinePosition -180"];  // A rash assumption
	[afmFile   WriteTextLine: "UnderlineThickness 10"];  // Ditto
	//
	//	Note that we could actually be computing the following for real, relatively easily.. 
	//
	[afmFile   WriteTextLine: "CapHeight 1000"];
	[afmFile   WriteTextLine: "XHeight 1000"];
	[afmFile   WriteTextLine: "Ascender 1000"];
	[afmFile   WriteTextUsing: buffer  WithFormat: "Descender %.3f\n",
				(macFont->descent * -1) * conversionFactor];
	//
	//	Count the number of characters that actually exist inthe font (except null char)
	//
	numChars = 0;
	for (thechar = macFont->firstChar; thechar <= macFont->lastChar;  thechar++)
	{
		index = thechar -  macFont->firstChar;
		if ( ( OffsetWidthTable[index].offset != -1) && ( OffsetWidthTable[index].width != -1))
			numChars += 1;
	}
	//
	//	Now, start writing out the character metrics
	//	NOTE:  This loop produces one of two results.  If we are using a Mac endocing, it writes out
	//	the metrics to the file.  If we are doing the NeXTSTEP encoding, then we just record which
	//	characters are used, and later write out the metrics.  This is done because if mac character N
	//	was used, then we want to write out the encoding for the NeXT character M.  That is, the Mac bullet
	//	might be at M, but it would be at M on the NeXT.  Since it is possible that M < N this would mean
	//	that we'd have to either write out the metrics in an unordered fashion, or not write out the values
	//	at all.  The solution is to record an array of which characters were used, and then write
	//	out metrics based on these later.
	//	Note that we also do not write out the StartCharMetrics line if we are doing NeXTstep encoding.
	//	This is because the number of characters may be smaller (some of the mac chars available will
	//	map to nothing in the nextstep endocing, and thus effectively vanish.  Sigh.
	//
	if (UseNSEncoding == NO)
		[afmFile   WriteTextUsing: buffer  WithFormat: "StartCharMetrics %d\n", numChars];
	else
		numChars = 0;
		
	for (thechar = macFont->firstChar; thechar <= macFont->lastChar;  thechar++)
	{
		index = thechar -  macFont->firstChar;
		if ( ( OffsetWidthTable[index].offset != -1) && ( OffsetWidthTable[index].width != -1))
		{
			//
			//	93.03.14	Added NS Encoding support.
			//	93.04.03	Modified because was producing improper names above 128, it seems.
			//
			if (UseNSEncoding == YES)
			{
				NeXTCharacter = MacToNeXTLookup[thechar];
				if (NeXTCharacter != NullCharacter)
				{
					//
					//	The following should really be using a struct.  yuck.
					//
					characterUsed[NeXTCharacter] = YES;
					macCharacterFor[NeXTCharacter] = thechar;
					numChars++;
				}
			}
			else
			{
				theName = EncodingVector[thechar];
			
				[afmFile   WriteTextUsing: buffer 
					WithFormat: "C %d ; WX %.3f ; N %s ; B %.3f %.3f %.3f %.3f ;\n",
						thechar,  OffsetWidthTable[index].width* conversionFactor,
						theName,
						(macFont->kernMax + OffsetWidthTable[index].offset)
							* conversionFactor,
						(macFont->descent * -1) * conversionFactor,
						(OffsetWidthTable[index].width* conversionFactor),
						macFont->ascent * conversionFactor];
			}
		}
	}
	//
	//	93.04.03	djb	Now, if we used the NS encoding, we should write out the values now that
	//					we know which characters were used.
	//
	if (UseNSEncoding == YES)
	{
		[afmFile   WriteTextUsing: buffer  WithFormat: "StartCharMetrics %d\n", numChars];
		for (thechar = 0; thechar < 256; thechar++)
		{
			if ( characterUsed[thechar] == YES)
			{
				index = macCharacterFor[thechar] -  macFont->firstChar;
				[afmFile   WriteTextUsing: buffer 
					WithFormat: "C %d ; WX %.3f ; N %s ; B %.3f %.3f %.3f %.3f ;\n",
						thechar,  OffsetWidthTable[index].width* conversionFactor,
						NSEncodingVector[thechar],
						(macFont->kernMax + OffsetWidthTable[index].offset)
							* conversionFactor,
						(macFont->descent * -1) * conversionFactor,
						(OffsetWidthTable[index].width* conversionFactor),
						macFont->ascent * conversionFactor];
			}
		}
	}

	[afmFile   WriteTextLine: "EndCharMetrics"];
	[afmFile   WriteTextLine: "EndFontMetrics"];
	FreeCString(buffer);
	return self;
}



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Method:		ConvertMacFONT:ToType3Font:
//	Parameters:	The file to read a Mac front from
//				The file to write a Type 3 font to.
//	Returns: 	a 16 bit Mac INTEGER (signed!)
//	Stores:		?????
//	Description:
//		A note about the character coordinates is in order here.  the main font imaging
//		routine (the postscript proc: BuldGlyph) had requent references to the height
//		of the font.  don't be misled!  Notice that all of them, by the time they are
//		executed are basically turned into relative measures (numbers from 0 to 1
//		usually).  It has taken me a while to grasp what was going on here.  I suppose
//		if I'd gone with adobe's recommendation of using a 1000 by 1000 coordinate
//		system , it might have been easier.  But I didn't want to completely obscure
//		the numbers that the mac form had.  Using such a coord system woulda given
//		lotsa xxx.yyyy numbers, and it would not have been as clear.  Anyway.
//		You needn't agree. It's just what I chose to do then.  Not sure I'd do it again.
//	Bugs:
//		We rely on the fact that the destination file name happens to be the name that
//		we want to have for the font...
//	History:
//		93.01.24	djb	Oddly, nDescent is sometimes the negative of the ascent!!  descent
//					always seems good, so replacing the one with the other.
//		93.08.01	djb	Replaced code to read in the font record with a call to the GetFontRec...
//					method, so all endianness of i/o is hidden from the app.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ConvertMacFONT: SourceFile ToType3Font: DestFile AndAFM: afmFile
{
	FontRecPtr	fontPtr;
	PositiveInteger	fontLength;
	CString		tempString = NewCString(1024);
	Integer 	thechar, index;
	INTEGER	*LocationTable;
	OWEntry	*OffsetWidthTable;
	ByteString	FontImage, RasterLine, destLine;
	INTEGER	FontHeight, RowWords;
	PositiveInteger	startBit, endBit, line;
	PositiveInteger	imageWidth;
	CString			buffer = NewCString(1024); 
	time_t			currentTime = time(0);
	CString			fontName;
	CString			timeString;
 	Real				conversionFactor;

	fontName = [DestFile	GetBasename];
	//
	//	Read in the font to use
	//
	fontLength = [SourceFile  FileSize];
	fontPtr = [self   GetFontRecordWithLength: fontLength  From: SourceFile];
	conversionFactor =  (1.0/fontPtr->fRectHeight) * 1000;
	//
	//	Build the AFM file
	//
	[self BuildAFMFileFrom: fontPtr Into: afmFile];
	//
	//	Build the ps font file
	//
	FontHeight = fontPtr->fRectHeight;
	//
	//	Write PS header comments
	//
	[DestFile   WriteComment: "!PS-Adobe-3.0"];
	[DestFile   WriteDSCCommentUsing: buffer WithFormat: "FontName: %s",  fontName];
	[DestFile   WriteDSCComment: "ConvertedFrom: (Macintosh bitmap font)"];
	timeString = ctime(&currentTime);
	timeString[24] = NullCharacter;	// Kill the final newline
	[DestFile   WriteDSCCommentUsing: buffer WithFormat: "CreationDate: (%s)",
				timeString];
	[DestFile   WriteDSCCommentUsing: buffer
				WithFormat: "Creator: (%s)", VERSIONSTRING];
	[DestFile   WriteDSCComment: "EndComments"];
	[DestFile   ForceNewLine];
	//
	//	Write some mini reference comments.
	//
	[DestFile	  WriteComment:
				"\tSome handy references (in orig. mac-bitmap coord system)"];
	[DestFile	  WriteCommentUsing: buffer
				WithFormat: "\tTotal Font Height is: %d", FontHeight];
	[DestFile	  WriteCommentUsing: buffer
				WithFormat: "\tFont Ascent is: %d", fontPtr->ascent];
	[DestFile	  WriteCommentUsing: buffer
				WithFormat: "\tFont Decent is: %d", fontPtr->descent];
	[DestFile	  WriteComment:
			"\tNote: that the numbers in the char definitions are:"];
	[DestFile	  WriteComment:
		"\t\twidth of character in bits/pixels"];
	[DestFile	  WriteComment:
		"\t\toffset to start drawing from the char origin"];
	[DestFile   ForceNewLine];
	[DestFile   WritePSLineUsing: buffer WithFormat: "/%s 8 dict begin", fontName];
	[DestFile   ForceNewLine];
	//
	//	Define the font type and font matrix
	//
	[DestFile   WritePSLine: "/FontType 3 def"];
	[DestFile   WritePSLine: "/FontMatrix [0.001 0 0 0.001 0 0] def"];
	[DestFile   WritePSLineUsing: buffer  WithFormat: "/FontBBox [0 %.3f %.3f %.3f] def",
				(fontPtr->descent * -1) * conversionFactor,
				fontPtr->fRectWidth * conversionFactor,
				fontPtr->ascent * conversionFactor];
	//
	//	Write the encoding array.
	//
	[DestFile   WriteText: "/Encoding ["];
	for (index = 0; index < 256; index++)
	{
		//
		//	93.03.14	Added code to support both NSEncoding and NS encoding vectors
		//
		if (UseNSEncoding == NO)
			[DestFile   WriteTextUsing: buffer WithFormat:" /%s",
						EncodingVector[index]];
		else
			[DestFile   WriteTextUsing: buffer WithFormat:" /%s",
						NSEncodingVector[index]];
	}
	[DestFile   WriteTextLine: "] def"];
	//
	//	Write the BuildGlyph procedure.   (I agree.  ICKY)
	//
	[DestFile   WritePSLine: "/BuildGlyph {"];
	[DestFile   WritePSLine: "	exch /CharProcs get exch"];
	[DestFile   WritePSLine: "	2 copy known not {pop /.notdef} if"];
	[DestFile   WritePSLine: "	get exec"];
	[DestFile   WritePSLine: "	/charimage exch def"];
	[DestFile   WriteTextUsing: buffer WithFormat: "\t/charoffset exch %.3f mul  def\n",
		conversionFactor];
	[DestFile   WriteTextUsing: buffer WithFormat: "\t/charwidth exch %.3f mul  def\n",
		conversionFactor];	
	[DestFile   WritePSLine: "	/bitwidth exch def"];
	[DestFile   WriteTextUsing: buffer WithFormat: "\tcharoffset 0  translate\n"];	[DestFile   WriteTextUsing: buffer WithFormat: "\tcharwidth 0\n\t0 %.3f %.3f  %.3f\n",
				(fontPtr->descent * -1) * conversionFactor,
				fontPtr->fRectWidth * conversionFactor,
				fontPtr->ascent * conversionFactor];
	[DestFile   WriteTextUsing: buffer
		WithFormat: "\tsetcachedevice\n\tbitwidth %d true\n", FontHeight];
	[DestFile   WriteTextUsing: buffer WithFormat: "\t[%.3f 0 0 -%.3f 0 %d]\n",
				FontHeight / 1000.0, FontHeight / 1000.0, fontPtr->ascent];
	[DestFile   WritePSLine: "\tcharimage"];
	[DestFile   WritePSLine: "\t imagemask"];
	[DestFile   WritePSLine: "} bind def"];
	[DestFile   WritePSLine: "/BuildChar {"];
	[DestFile   WritePSLine: "1 index /Encoding get exch get"];
	[DestFile   WritePSLine: "1 index /BuildGlyph get exec"];
	[DestFile   WritePSLine: "} bind def"];
	//
	//	Begin definition of the individual character procedures.
	//			(+1+1 is for 'fencepost' and undefined character)
	//
	[DestFile   WritePSLineUsing: buffer WithFormat: "/CharProcs %d  dict def",
				fontPtr->lastChar-fontPtr->firstChar+1+1];
	[DestFile   WritePSLine: "CharProcs begin"];

	RowWords = fontPtr->rowWords;
	FontImage = &(fontPtr->ImageAndTables);
	LocationTable = (INTEGER*) ((FontHeight*RowWords*2) + FontImage);
	OffsetWidthTable = (OWEntry*)  (&(fontPtr->owTLoc) + fontPtr->owTLoc);
	destLine = NewByteString(RowWords*2);

	for (thechar = fontPtr->firstChar; thechar <= (fontPtr->lastChar+1);  thechar++)
	{
		//
		//	give the manager a crude idea of how far done we are (note we don't give
		//	%'s for the afm part, and this isn't accurate since we usually don't have
		//	all256 chars)
		//
		if ( [myManager   respondsTo:@selector(SetPercentageDone:)] ) 
			[myManager   SetPercentageDone: thechar / 2.56];

		index = thechar -  fontPtr->firstChar;
		//
		//	If there is data for this character (offset and width aren't -1), then extract it.
		//
		if ( ( OffsetWidthTable[index].offset != -1) && ( OffsetWidthTable[index].width != -1))
		{
			//
			//	Get the name for the character, and write it out.
			//
			if (thechar == fontPtr->lastChar+1)
				[DestFile   WritePSLineUsing: buffer WithFormat: "/%s {", ".notdef "];
			else
			{
				//
				//	93.03.14	We do NOT want to write out NS encoding names here, since
				//			no matter how you set up your references, the data that we
				//			are extracting is comming out in a Mac encoding order
				//
				[DestFile   WritePSLineUsing: buffer
					WithFormat: "/%s {", EncodingVector[thechar]];
			}
			//
			//	Prepare to extract the bit image by locating the first and
			//	last bit of the lines of pixels
			//
			startBit = LocationTable[index];
			endBit = LocationTable[index+1];
			imageWidth = endBit-startBit;
			//
			//	
			//
			[DestFile   WritePSLineUsing: (CString) buffer WithFormat:"\t%d", imageWidth];
			[DestFile   WritePSLineUsing: buffer WithFormat: "\t%d",
						OffsetWidthTable[index].width];
			[DestFile   WritePSLineUsing: buffer WithFormat: "\t%d",
						fontPtr->kernMax + OffsetWidthTable[index].offset];
			if (imageWidth <= 0)
			{
				[DestFile   WritePSLine: "{<>}"];
			}
			else
			{
				[DestFile   WritePSLine: "{<"];
				//
				//	Extract the bit image for each character
				//	93.01.05	djb	Added check on imageWidth so we would not write out
				//	empty lines.
				//
				for (line = 0; line < FontHeight; line ++)
				{
					RasterLine = &(FontImage[line*RowWords*2]);
					[self   Copy: imageWidth BitsAtOffset: startBit
						From: RasterLine Into: destLine];
					[DestFile	   Write: [self GetPositiveIntegerFrom: SECOND_RESULT] 
						BytesOfHexDataFrom: destLine];
				}
				[DestFile   WritePSLine: ">}"];
			}
			[DestFile   WritePSLine: "} bind def"];
		}
	}
	[DestFile   WritePSLine: "end"];
	[DestFile   ForceNewLine];
	[DestFile   WritePSLine: "currentdict"];
	[DestFile   WritePSLine: "end"];
	[DestFile   WritePSLine: "definefont pop"];

	FreeByteString(destLine);
	FreeByteString((ByteString) fontPtr);
	FreeCString(tempString);
	FreeCString(buffer);
	//
	//	93.01.10	djb	Remove the stored name if there is one, so we don't re-use it next
	//				time.
	//
	if (StoredName != NullCString)
	{
		FreeCString(StoredName);
		StoredName = NullCString;
	}
	return self;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Method:		SetFullNameTo:
//	Parameters:	A string that will be used as the font's name
//	Returns: 	self
//	Stores:		none
//	Description:
//		This is added to the font converter on 93.01.10... that is, just as I'm doing my
//		final pre-beta testing.  I found that one could say: convert this font:
//				myfont(it's way cool).font
//		and this would dutifully create a font with the name myfont(it's way cool)
//		but this name makes PS get ill due to special characters.  Yet, one wants this
//		name to appear in the font menu.  So, this name is passed to this method which
//		stores it for storage in the afm file in the right places, while the rest of the
//		converter uses a name like  myfontit'swaycool.  In any case, this just makes a
//		copy of the string.  It's up to the conversion routine to deallocate it when it's done
//		so it doesn't get confused.
//	Bugs:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-SetFullNameTo: (ConstCString) filename
{
	if (StoredName != NullCString)
		FreeCString(StoredName);
	StoredName = NewCString(strlen(filename));
	strcpy(StoredName, filename);
	return self;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	Method:		GetFontRecordFrom:
//	Parameters:	the file to read a Mac font record structure from
//	Returns: 	a pointer to a font record (caller must dispose of the memory)
//	Stores:		none
//	Description:
//		This routine reads in a big-endian Macintosh font record from.  Since this may
//		be running on little endian (or other? =) machines, this routine then builds a
//		new structure for the endianness that is currently in use.
//		This is redundant work for Black hardware, but what the heck.  
//	History:
//		93.08.01	djb	Created, thus insulating the rest of the code from endian concerns
//					in the source files.
//		93.08.15	djb	Argh!  I need to be casting the results!!!
//		93.11.05	djb	Added code to do the endian flip of the location table.
//	Bugs:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (FontRecPtr) GetFontRecordWithLength: (PositiveInteger) fontLength From: SourceFile
{
	FontRecPtr	sourceFontRec;
	FontRecPtr	destFontRec;
	Integer		index;
	INTEGER	*LocationTable;
	INTEGER	*DestLocationTable;
	INTEGER	FontBitmapSize;

	sourceFontRec = (FontRecPtr) NewByteString(fontLength);
	destFontRec = (FontRecPtr) NewByteString(fontLength);
	
	[SourceFile   Read: fontLength BytesInto: (ByteString) sourceFontRec];
	//
	//	Copy the source font record to the destination record.  This moves the font bitmaps
	//	and other stuff which we have no plans to copy.
	//
	memcpy(destFontRec, sourceFontRec, fontLength);
	//
	//	Now, swap all the INTEGERS (2 byte integers) from big endian to whwatever
	//	the local endianness is.
	//
	destFontRec->fontType = (INTEGER) NXSwapBigShortToHost(sourceFontRec->fontType);
	destFontRec->firstChar = (INTEGER) NXSwapBigShortToHost(sourceFontRec->firstChar);
	destFontRec->lastChar = (INTEGER) NXSwapBigShortToHost(sourceFontRec->lastChar);
	destFontRec->widMax = (INTEGER) NXSwapBigShortToHost(sourceFontRec->widMax);
	destFontRec->kernMax = (INTEGER) NXSwapBigShortToHost(sourceFontRec->kernMax);
	destFontRec->nDescent = (INTEGER) NXSwapBigShortToHost(sourceFontRec->nDescent);
	destFontRec->fRectWidth = (INTEGER) NXSwapBigShortToHost(sourceFontRec->fRectWidth);
	destFontRec->fRectHeight = (INTEGER) NXSwapBigShortToHost(sourceFontRec->fRectHeight);
	destFontRec->owTLoc = (INTEGER) NXSwapBigShortToHost(sourceFontRec->owTLoc);
	destFontRec->ascent = (INTEGER) NXSwapBigShortToHost(sourceFontRec->ascent);
	destFontRec->descent = (INTEGER) NXSwapBigShortToHost(sourceFontRec->descent);
	destFontRec->leading = (INTEGER) NXSwapBigShortToHost(sourceFontRec->leading);
	destFontRec->rowWords = (INTEGER) NXSwapBigShortToHost(sourceFontRec->rowWords);
	//
	//	Flip the endianness, if needed, of the location table.  The +3 in the for loop is because
	//	+1 to compensate for the last-first subtraction to get the number of chars, +1 for the unknown
	//	character at the end of the font, and +1 for the final location, since one needs a trailing
	//	location to mark where the last character ends.
	//
	FontBitmapSize = ((destFontRec->fRectHeight * destFontRec->rowWords) * 2);
	LocationTable = (INTEGER*) (FontBitmapSize + (&(sourceFontRec->ImageAndTables)));
	DestLocationTable = (INTEGER*) (FontBitmapSize + (&(destFontRec->ImageAndTables)));
	for (index = 0; index <= ((destFontRec->lastChar - destFontRec->firstChar)+3);  index++)
		DestLocationTable[index] = (INTEGER) NXSwapBigShortToHost(LocationTable[index]);
	//
	//	dispose of the source one, and return the destination.
	//
	FreeByteString((ByteString)sourceFontRec);
	return destFontRec;
}






@end;

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.