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.