// PLMaker.bcpl // edited by Ramshaw December 23, 1980 1:57 PM remove f-kerning // for italic fonts, since italic correction takes care of it // edited by Ramshaw December 14, 1980 5:04 PM new PL and TFM format, // more data about fonts. Added PLMakerData module // edited by Ramshaw July 11, 1980 11:58 AM ignore chars above #177, // plus new families // edited by Guibas October 18, 1979 8:54 AM new OS plus more families // edited by Wyatt September 4, 1979 1:59 PM (NEW PL FORMAT) // edited by Wyatt May 3, 1979 3:02 PM (changed SPACE computation) // edited by Wyatt April 29, 1979 5:43 PM (added TIMESROMANSC,HELVETICASC) // edited by Wyatt February 19, 1979 3:18 PM // edited by Guibas February 18, 1979 1:13 PM to add trident code // modified 2/12/79 to create .PL files for an entire character dictionary // load with: Bldr PLMaker PLMaker1 PLMakerData gp tfs* loadram triconmc // (tfs* from tfs.dm) // read a prepress character (.ac) file, and produce a property list (.PL) // file suitable for consumption by a sail program which produces // "TFP" files for TEX get "altodefs.d"; // from [maxc] get "streams.d"; // from [maxc] get "ix.dfs"; // from [ivy] get "plmaker.d"; // from [ivy] manifest [ cr=$*n quadchar=#17 // em space in newer PARC fonts ] external [ // from GP SetupReadParam; ReadParam; // from OS GetFixed; FixedLeft; InitializeZone; Allocate; Free; OpenFile; ReadBlock; WriteBlock; Gets; Puts; Endofs; Resets; Closes; Ws; Wo; Wns; Wss; SetFilePos; FilePos; DoubleAdd; MoveBlock; SetBlock; Usc; Min; Max; fpComCm; dsp; SetEndCode; lvUserFinishProc; lvSwatContextProc; // Trident disk stuff LoadRam; // from LoadRam DiskRamImage; // from TriConMc TFSSwatContextProc; TFSClose; TFSInit; TFSSilentBoot; // from TFS* TFSzone; TFSdisk; // from PLMaker1 Str; Chr; Cr; Dec; UDec; Oct; DNum; ONum; XNum; Char; RNumOver10; Begin; End; SetPos; GetPos; IncPos; DoubleSub; MulDiv; WordsForString; CopyString; StringMatch; AppendChar; AppendNum; AppendStr; DefaultExtension; StripExtension; //from PLMakerData InitTables // outgoing statics outstream; lev; z; flags; tflags; names; tnames; nt; cwvec; // outgoing proc (to PlMakerData) MakeStringCopy ]; static [ z // free storage zone logstream // stream for display and log file infilename outfilename instream1=0 // (word) stream on the input file instream2=0 // another (word) stream on the input file outstream=0 // (byte) stream on the output file bc; ec; // beginning and ending chars nc; // number of characters fam; face; siz; rot; // family code, face code, size in micas, rotation sl; wt; ex; // slope, weight, expansion (e.g., $I, $M, $R) resx; resy; // resolutions (10*number of bits per inch) cwvec // pointer to CharWidth array from input file dirvec // pointer to directory array from input file cwLen // length of cwvec dirLen // length of dirvec dirfp // file position of directory lev=0 // indentation level fixedPitch // true if font has fixed pitch fLigs // true if font has "f" ligatures dLigs // true if font has en-dash and em-dash mQuad // true if font has em-quad s40 // true if #40 is a word space CScode // codingscheme code number pts // size of font in PARC points from the dictionary file texStyle=true // true if PL file is being produced for TEX. names // pointer to array of names from dictionary flags // pointer to array of flags associated with names tnames // pointer to array of family names to be considered tflags // pointer to array of flags associated with tnames nt // number of entries in tnames savedUFP; savedSCP; TFSzone; TFSdisk = 0 // for the Trident ]; structure S: // BCPL string [ length byte body^0,255 byte ]; let main() be [ OpenLog("PLMaker.log"); Log("PLMaker of December 18, 1980:*n"); InitStorage(); ReadComCm(); Log("Reading file: "); Log(infilename); Log(".*n*n"); OpenInputFile(); InitTables(); ScanDictionary(); CloseFiles(); ]; and InitStorage() be [ let res = LoadRam(DiskRamImage,true); let AltoVersion=(table [ #61014; #1401 ] )() let eng=AltoVersion<>IX.Type eq IXTypeEnd break; // end of index ReadBlock(instream1, ix+1, ix>>IX.Length-1); // read rest of index entry switchon ix>>IX.Type into [ case IXTypeName: EnterName(lv ix>>IXN.Name, ix>>IXN.Code); endcase; case IXTypeChars: case IXTypeOrbitChars: case IXTypeMultiChars: ProcessChars(ix); default: endcase; // just ignore it ]; ] repeat ]; and EnterName(name, code) be [ names!code=MakeStringCopy(name); // look up the name in tnames for i=0 to nt-1 do [ if StringMatch(name,tnames!i) do [ flags!code=tflags!i; (flags!code)<>IX.Type into [ case IXTypeChars: case IXTypeOrbitChars: fam=ix>>IX.fam; face=ix>>IX.face; siz=ix>>IX.siz; bc=ix>>IX.bc; ec=ix>>IX.ec; rot=ix>>IX.rotation; resx=ix>>IX.resolutionx; resy=ix>>IX.resolutiony; psa=lv ix>>IX.sa; endcase; case IXTypeMultiChars: fam=ix>>IXM.fam; face=ix>>IXM.face; siz=ix>>IXM.siz; bc=ix>>IXM.bc; ec=ix>>IXM.ec; rot=ix>>IXM.rotation; resx=ix>>IXM.resolutionx; resy=ix>>IXM.resolutiony; psa=lv ix>>IXM.segs^1.sa; // most recent widths are in 1st seg endcase; default: Log("[??? IX.Type not chars]*n"); return; ]; pts=MulDiv(siz,72,2540); // point size if PARCface(face) then DecodeFace(face, lv wt, lv sl, lv ex); let name=vec 30; // space for the name CopyString(name, names!fam); // first, the family name if (flags!fam)<>CharWidth.WX; let zero=vec 1; zero!0,zero!1=0,0; test fixedPitch ifnot [ let half=vec 1; // half _ 1/2 wx half!1=(wx!1)rshift 1 + (wx!0)lshift 15; half!0=(wx!0)rshift 1; space!0,space!1=wx!0,wx!1; // space _ wx DoubleAdd(space, half); // space _ space + 1/2 wx (space = 3/2 wx) str!0,str!1=wx!0,wx!1; // str _ wx shr!0,shr!1=half!0,half!1; // shr _ 1/2 wx xtrspace!0,xtrspace!1=half!0,half!1; // xtrspace _ 1/2 wx ] ifso [ space!0,space!1=wx!0,wx!1; // space _ wx xtrspace!0,xtrspace!1=wx!0,wx!1; // xtrspace _ wx str!0,str!1=0,0; // str _ 0 shr!0,shr!1=0,0; // shr _ 0 ]; Begin(); Str("SPACE"); XNum(space); End(); Begin(); Str("STRETCH"); XNum(str); End(); Begin(); Str("SHRINK"); XNum(shr); End(); ] if InFont($x) do [ let cw=Cwp($x); let xh=cw>>CharWidth.H+cw>>CharWidth.YB; Begin(); Str("XHEIGHT"); DNum(xh); End(); ] Begin(); Str("QUAD"); test mQuad ifso XNum(lv Cwp(quadchar)>>CharWidth.WX) ifnot RNumOver10(MulDiv(reso,siz,2540)); //remember reso=10*resolution End(); if s40 do [ Begin(); Str("EXTRASPACE"); XNum(xtrspace); End() ]; End(); // of TEXINFO if fLigs % dLigs do MakeLigtable(); for c=bc to ec do if InFont(c) do [ Begin(); Str("CHARACTER"); Char(c); Cr(); OutCharInfo(c); End(); ]; ] and Label(c) be [ Begin(); Str("LABEL"); Char(c); End(); ] and Lig(c1,c2) be [ Begin(); Str("LIG"); Char(c1); Char(c2); End(); ] and Kern(c,d) be [ Begin(); Str("KRN"); Char(c); DNum(d); End(); ] and Stop() be [ Begin(); Str("STOP"); End(); ] and MakeLigtable() be [ Begin(); Str("LIGTABLE"); Cr(); if fLigs do [ Label($f); let cw=Cwp($f) let wx=lv cw>>CharWidth.WX let wid=wx!0; let corr=cw>>CharWidth.W+cw>>CharWidth.XL-wid if (corr gr 0)&(sl eq $R) then [ if InFont($') then Kern($',corr) if InFont($)) then Kern($),corr) if InFont($]) then Kern($],corr) if InFont($!) then Kern($!,corr) if InFont($?) then Kern($?,corr) ] Lig($f,#6); Lig($i,#24); Lig($l,#25); Stop(); // ff, fi, fl Label(#6); cw=Cwp(#6) wx=lv cw>>CharWidth.WX wid=wx!0; corr=cw>>CharWidth.W+cw>>CharWidth.XL-wid if (corr gr 0)&(sl eq $R) then [ if InFont($') then Kern($',corr) if InFont($)) then Kern($),corr) if InFont($]) then Kern($],corr) if InFont($!) then Kern($!,corr) if InFont($?) then Kern($?,corr) ] Lig($i,#21); Lig($l,#22); Stop(); // ffi, ffl ] if dLigs do [ Label($-); Lig($-,#26); Stop(); // -- = Label(#26); Lig($-,#23); Stop(); // - = ] End(); // of LIGTABLE ] and Cwp(c)=cwvec+(c-bc)*CharWidthsize; // pointer to CharWidth structure for c and InFont(c) = bc le c & c le ec & Cwp(c)>>CharWidth.H ne HNonExCode; and OutCharInfo(c) be [ let cw=Cwp(c); let wx=lv cw>>CharWidth.WX; Begin(); Str("CHARWD"); XNum(wx); End(); let ht=cw>>CharWidth.H+cw>>CharWidth.YB; Begin(); Str("CHARHT"); DNum(Max(ht,0)); End(); let dp=-cw>>CharWidth.YB; Begin(); Str("CHARDP"); DNum(Max(dp,0)); End(); let wid=wx!0; // truncate, to round italic correction up let corr=cw>>CharWidth.W+cw>>CharWidth.XL-wid; if corr gr 0 do [ Begin(); Str("CHARIC"); DNum(corr); End() ]; ]; // from fontwidths.bcpl and DecodeFace(face,w,s,e) be [ @s=(table [ $R; $I ])!(face&1) face=face rshift 1 @w=(table [ $M; $B; $L ])!(face rem 3) face=face/3 @e=(table [ $R; $C; $E ])!(face rem 3) ] and PARCface(face) = valof [ if face ls 0 then resultis false if face ge 18 then resultis false resultis true ] and CodeToString(code) =valof [ switchon code into [ case CSxeroxtext: resultis "XEROX TEXT" case CSalphabetic: resultis "ALPHABETIC" case CSpi: resultis "PI" case CSgraphic: resultis "GRAPHIC" case CSxeroxgreek: resultis "XEROX GREEK" case CSxeroxcyrillic: resultis "XEROX CYRILLIC" case CSsail: resultis "SUAI" case CSsanitizedsail: resultis "SANITIZED SUAI" ] ] and // allocate space for a new string and copy s into it MakeStringCopy(s) = valof [ let nw=WordsForString(s); // number of words required let ss=Allocate(z, nw); MoveBlock(ss, s, nw); resultis ss; ]; and Punt(string) be [ Log("*nPunt: "); Log(string); Log("*n"); CloseFiles(); abort; ];