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(¤tTime);
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.