// FontPass1.bcpl // modified by Ramshaw, January 19, 1982 4:18 PM // - added FontPickyMatch switch; if true, means to Swat if any // font request can't be "perfectly" matched. // - also adjusted font match algorithm so that off-by-one-mica // bugs can't make splines take over from rasters // modified by Ramshaw, January 18, 1981 5:26 PM // - adjusted font match algorithm so that chars will only take // precedence over splines if they are very nearly a perfect match. // modified by Ramshaw, January 9, 1981 10:23 PM // - changed code so that icc index zero is now only used for dummies, // (whatever they are!). Indices for real characters are allocated // starting at 1, and a dummy raster pointer is output for index 0. // modified by Butterfield, October 13, 1980 11:18 AM // - ResolutionB, ResolutionS, 1X instead of 10X - 10/13/80 // errors 600 // //Routines for preparing the two fonts for the 3100 PRESS printer. // //FontsPass(wp,ws,wg,numrecs) // is called to prepare fonts. // wp = window on PRESS file, positioned to read Font Part. // ws = window on scratch file, positioned at beginning. // wg = window on GOD file (Grand Old Dictionary) // numrecs = # records in press font part. //NB -- resolutions need to be set by someone!!!! get "PressParams.df" get "PressInternals.df" get "Ix.dfs" get "FontPass.df" // outgoing procedures external [ FontsPass ] // outgoing statics external [ ws //Window on scratch file wfdir //Window on GOD SetTable ICCtot ] static [ ws wfdir SetTable ICCtot ] // incoming procedures external [ //PRESS PressError FSGetX FSPut GetTime //PRESSML MulDiv DoubleAdd; DoubleSub; DoubleCop //From FONTPASS2.c PrintFonts ConvertFontParts ConvertFonts LoopFonts LoopFontParts DPADi SetPosRelative ReadIX ReleaseFontCore //OS MoveBlock; SetBlock; Zero //WINDOW WindowInit WindowClose WindowSetPosition WindowGetPosition WindowReadBlock WindowWriteBlock WindowRead WindowWrite WindowCopy //METER MeterBlock MeterTime //CURSOR CursorChar CursorDigit CursorToggle ] // incoming statics external [ ResolutionS ResolutionB portrait //True if printerMode=3; else printerMode=8 Report FontPickyMatch //True => Swat on any non-perfect font match ] // internal statics static [ wp ] // File-wide structure and manifest declarations. structure STR[ length byte char^1,255 byte ] // Procedures let FontsPass(wwp,wws,wg,numrecs) be [ compileif ReportSw then [ GetTime(lv Report>>REP.FontTime) ] let FPStats=vec size FPStat/16 compileif MeterSw then [ FPStats>>FPStat.TimeIn=MeterTime() ] CursorChar($F) //Fonts pass wp=wwp; ws=wws; wfdir=wg //Save windows in statics. WindowWriteBlock(ws,0,6) //Save spot for 3 numbers... let st1=vec 65 SetTable=st1 //Main font-set table. Zero(st1,65) // 0-64 (!!!!!!) ReadPressFontPart(numrecs) ReadCharacterDictionary(wfdir) ICCtot=AssignICCs() ConvertFontParts(wp) ConvertFonts() AssembleWidths() WriteDirectories() ReleaseFontCore() compileif MeterSw then [ FPStats>>FPStat.TimeOut=MeterTime() FPStats>>FPStat.ICCtotal=ICCtot MeterBlock(METERFontPass,FPStats,size FPStat/16) ] compileif ReportSw then [ GetTime(lv Report>>REP.FontTime) ] ] and //Read the PRESS font part and build an internal description of all // font part requests (FPREQ) or "font part characters" (CREQ). ReadPressFontPart(numrecs) be [ let FontPartPos=vec 1 //Current font part position. WindowGetPosition(wp,FontPartPos) let AllowedLength=vec 1 //Maximum font part length. AllowedLength!0=0; AllowedLength!1=numrecs*256 let BreakFont=false //Flag when appending break font. [ //Loop reading font parts.. CursorToggle(0) let f=vec (size PRESSFE/16) //Spot to read font entry. WindowSetPosition(wp,FontPartPos) let len=WindowRead(wp) let dlen=vec 1 dlen!0=0; dlen!1=len DoubleAdd(FontPartPos,dlen) //Update next place to look DoubleSub(AllowedLength,dlen) if AllowedLength!0 ls 0 then [ //We have overrun our bounds. PressError(600) //The simplest error there is.. len=0 //Get out... ] test len eq 0 then [ //Last entry -- get break font BreakFont=true f=table [ //This is a dummy font... 64*256+0; 0*256+127; 9*256+$B; //Family name $R*256+$E; $A*256+$K; $F*256+$O; $N*256+$T; 0;0;0;0;0; 0*256+0; //Face=MRR 10;0 //10 Point, no rotation. ] ] or [ //Read; assume most common thing WindowReadBlock(wp,f,size PRESSFE/16) ] compileif ReportSw then [ Report>>REP.FontsUsed=Report>>REP.FontsUsed+1 ] let a=f>>PRESSFE.famly //Get first word of family. if (a rshift 8) gr 19 then [ //Illegal length PressError(601) //Dump out an error message. loop //and go on. ] let Set=f>>PRESSFE.set if (Set gr 63) & (BreakFont eq 0) then [ //Illegal font set. PressError(602) //Give him a message. loop ] //And go after next font entry. let Font=f>>PRESSFE.font if Font gr 15 then [ //Illegal font number. PressError(603) loop ] let g=nil test a eq 0 then [ //FontPartCharacter g=FSGetX(size CREQ/16) Zero(g,(size CREQ/16)) g>>CREQ.type=FontPartCharacter let fp=vec 1 DoubleCop(fp,FontPartPos) DoubleSub(fp,dlen) DoubleAdd(fp,table [ 0;3 ]) DoubleCop(lv g>>CREQ.pos,fp) g>>CREQ.len=len-3 f>>PRESSFE.n=f>>PRESSFE.m ] or [ //Standard. g=FSGetX(size FPREQ/16) //Block to remember request. Zero(g,(size FPREQ/16)) //Zero it! g>>FPREQ.type=Standard MoveBlock(lv g>>FPREQ.rfamly, lv f>>PRESSFE.famly, size FPREQ.rfamly/16) g>>FPREQ.rfacesource=f>>PRESSFE.facesource let s=f>>PRESSFE.siz g>>FPREQ.rsiz=((s ls 0)? -s,MulDiv(s,635,18)) g>>FPREQ.rrotation=f>>PRESSFE.rotation+(portrait? 90*60,0) ] g>>FPREQ.rmn=f>>PRESSFE.mn //Now put this REQ on the correct list for this set,font let r=SetTable!Set if r eq 0 then [ r=FSGetX(size SET/16) Zero(r,(size SET/16)) SetTable!Set=r ] let f=r>>SET.font^Font if f eq 0 then [ f=FSGetX(size FONT/16) Zero(f,(size FONT/16)) f>>FONT.bc=255 f>>FONT.font=Font f>>FONT.set=Set r>>SET.font^Font=f ] // f -> "font" header for this font set. let m=g>>FPREQ.rm let n=g>>FPREQ.rn let p=lv f>>FONT.segments //Header for pieces of fonts. [ if @p eq 0 then break //Look for correct position let t=@p if n ls t>>FPREQ.rm then break //good place for it. test n le t>>FPREQ.rn ifso [ //We are inserting one that overlaps //t. Two cases: (1) ours extends to left //of t, and t is pared down, or (2) ours //lies entirely in t, and t is split. if m gr t>>FPREQ.rm then [ let nt=FSGetX(size FPREQ/16) MoveBlock(nt,t,(size FPREQ/16)) nt>>FPREQ.rn=m-1 @nt=@p @p=nt p=nt ] t>>FPREQ.rm=n+1 if t>>FPREQ.rm gr t>>FPREQ.rn then [ //Delete t entirely! @p=@t FSPut(t) ] break //Ready to put it in. ] ifnot [ //We end beyond t. But we may //have to pare it down. test m le t>>FPREQ.rm then [ //Delete t entirely @p=@t FSPut(t) ] or test m le t>>FPREQ.rn then [ t>>FPREQ.rn=m-1 p=t //Move right ] or p=t ] ] repeat @g=@p; @p=g //Link it in. ] repeatuntil BreakFont //Read Font part ] and //Read the directory file and find the best match with each font // part request. ReadCharacterDictionary(wfdir) be [ //Now read the directory from the mighty file, and piece it all together. let pFont=vec 3 let sn=0 let ix=vec IXLMax [ CursorToggle(1) ReadIX(wfdir,ix) //Read an entry. sn=sn+1 switchon ix>>IX.Type into [ case IXTypeEnd: break //Done. case IXTypeName: [ //Distribute the name. @pFont=0 //Initialize looper while LoopFontParts(pFont) do [ //See if name matches. let p=pFont!0 if p>>FPREQ.type ne FontPartCharacter & ComStr(lv p>>FPREQ.rfamly,lv ix>>IXN.Name) then [ p>>FPREQ.named=true p>>FPREQ.rfam=ix>>IXN.Code ] ] ] endcase case IXTypeMultiChars: //reformat to look like OrbitChars [ ix>>IX.Type=IXTypeOrbitChars let rx=ix>>IXM.resolutionx let ry=ix>>IXM.resolutiony MoveBlock(lv ix>>IX.sa,lv ix>>IXM.segs^1.sa,4) //move sa,len ix>>IX.resolutionx=rx ix>>IX.resolutiony=ry ] //endcase intentionally omitted case IXTypeChars: //error message some day??? case IXTypeOrbitChars: case IXTypeSplines: [ //See if we are a good match. @pFont=0 //Initialize looper while LoopFontParts(pFont) do [ let p=pFont!0 if p>>FPREQ.type ne FontPartCharacter then [ let score=MatchEntries(ix,p) //Compute similarity if score gr p>>FPREQ.score then [ p>>FPREQ.score=score p>>FPREQ.type=ix>>IX.Type //Copy current best match! MoveBlock(lv p>>FPREQ.famface,lv ix>>IX.famface, (size IX-offset IX.famface)/16) p>>FPREQ.sn=sn ] ] ] ] endcase default: PressError(604) ] ] repeat //ReadIX until IXTypeEnd if FontPickyMatch then [ @pFont=0 //initialize looper while LoopFontParts(pFont) do [ let p=pFont!0 if p>>FPREQ.type ne FontPartCharacter & pFont!2 le 63 & //don't worry about the BreakFont p>>FPREQ.score ls 118 //a spline match counts 118 then PressError(605, lv p>>FPREQ.rfamly, p>>FPREQ.rface, p>>FPREQ.rsiz, p>>FPREQ.rrotation-(portrait ? 90*60,0)) ] ] ] and //Compute a match score between an ix entry read from a dictionary file // and a font piece request. Maximum score, a perfect match of rasters, // is 120. A perfect match by splines is 118, so that rasters will take // precedence even if someone is off by a mica or two. //WARNING: The constant 118 appears near the end of the prededing // procedure! // Rotation=64; Size=32; Family=16; Face=8 MatchEntries(ix,p) = valof [ let score=nil test (ix>>IX.Type eq IXTypeChars)%(ix>>IX.Type eq IXTypeOrbitChars) then [ let fontSiz= MulDiv(ix>>IX.resolutionx, ix>>IX.siz, 10*ResolutionS) let reqSiz = p>>FPREQ.rsiz; let dif=(fontSiz-reqSiz) //number of micas of difference if dif ls 0 then dif=-dif //max allowable error is about 10% more or less than request //spline size match is 16, so total diff allowed is 20% dif=MulDiv(dif, 150, reqSiz) if dif gr 32 then dif=32 score=32-dif if ix>>IX.rotation eq p>>FPREQ.rrotation then score=score+64 ] or [ //Lyle Ramshaw: Splines should be used instead of // chars unless the chars are an excellent match. score=94 //Rotation OK, size match=30=32-2 ] if ix>>IX.face eq p>>FPREQ.rface then score=score+8 if p>>FPREQ.named ne 0 & p>>FPREQ.rfam eq ix>>IX.fam then score=score+16 resultis score ] and //Assign ICC addresses. //First, update bc,ec for each font. If there is only one FPREQ for a // font, and if it is of type IXTypeChars, mark the FONT as verbatim // (i.e. can just point at things for this font). // Then, assign ICC's and put in verbatim fonts the corresponding // disk address, or mark it as "same as some other font". AssignICCs() =valof [ let pFont=vec 3 @pFont=0 while LoopFontParts(pFont) do [ let f=pFont!1 let p=pFont!0 let source=p>>FPREQ.rsource let bc=source let ec=source+p>>FPREQ.rn-p>>FPREQ.rm //bc,ec in address space of available font. if p>>FPREQ.type ne FontPartCharacter then [ if bc ls p>>FPREQ.bc then bc=p>>FPREQ.bc if ec gr p>>FPREQ.ec then ec=p>>FPREQ.ec if f>>FONT.segments eq p & p>>FPREQ.next eq 0 then f>>FONT.sharable=true ] let off=p>>FPREQ.rm-source p>>FPREQ.rsource=bc //New starting spot. bc=off+bc ec=off+ec //bc,ec in address space of request if bc ls f>>FONT.bc then f>>FONT.bc=bc if ec gr f>>FONT.ec then f>>FONT.ec=ec p>>FPREQ.rm=bc p>>FPREQ.rn=ec ] let numfonts=0 let ICC=1 //start indices for real chars at one! @pFont=0 while LoopFonts(pFont) do [ let f=pFont!1 //Font pointer let found=false if f>>FONT.sharable then [ //See if there is another equal. let ppFont=vec 3 @ppFont=0 while LoopFonts(ppFont) do [ let pf=ppFont!1 if pf eq f then break //None found yet if pf>>FONT.sharable then [ let ppf=pf>>FONT.segments //this request let pp=f>>FONT.segments //later one. if ppf>>FPREQ.sn eq pp>>FPREQ.sn & ppf>>FPREQ.rsiz eq pp>>FPREQ.rsiz & ppf>>FPREQ.rrotation eq pp>>FPREQ.rrotation then [ f>>FONT.WTPos.File=FPOSDNE f>>FONT.AuxSet=pf>>FONT.set f>>FONT.AuxFont=pf>>FONT.font f>>FONT.indirect=true found=true break ] ] ] ] unless found then [ //Assign ICC's f>>FONT.ICCPos.File=FPOSDNE f>>FONT.ICCBase=ICC ICC=ICC+f>>FONT.ec-f>>FONT.bc+1 ] ] resultis ICC ] and //Assemble widths on a font-by-font basis if needed. AssembleWidths() be [ let pFont=vec 3 @pFont=0 while LoopFonts(pFont) do [ CursorToggle(0) let f=pFont!1 let p=pFont!0 let fp=vec 1; let file=nil if f>>FONT.indirect eq 0 then [ test f>>FONT.sharable then [ DoubleCop(fp,lv p>>FPREQ.sa) let rc=p>>FPREQ.rsource-p>>FPREQ.bc DPADi(fp,rc*CharWidthsize) DoubleCop(lv f>>FONT.WTPos,fp) file=(p>>FPREQ.type eq Converted)? FPOSScratch,FPOSGod ] or [ let nc=f>>FONT.ec-f>>FONT.bc+1 let CWT=FSGetX(nc*CharWidthsize) SetBlock(CWT,HNonExCode,nc*CharWidthsize) WindowGetPosition(ws,lv f>>FONT.WTPos) while p do [ let t=p>>FPREQ.type test t ne FontPartCharacter then [ file=((t eq IXTypeChars)%(t eq IXTypeOrbitChars))? wfdir,ws DoubleCop(fp,lv p>>FPREQ.sa) let rc=p>>FPREQ.rsource-p>>FPREQ.bc let nc=p>>FPREQ.rn-p>>FPREQ.rn+1 DPADi(fp,rc*CharWidthsize) WindowSetPosition(file,fp) let oc=p>>FPREQ.rm-f>>FONT.bc WindowReadBlock(file,CWT+oc*CharWidthsize, nc*CharWidthsize) ] or MoveBlock(CWT+CharWidthsize*(p>>FPREQ.rm-f>>FONT.bc), lv p>>CREQ.widths,CharWidthsize) p=p>>FPREQ.next ] WindowSetPosition(ws,lv f>>FONT.WTPos) WindowWriteBlock(ws,CWT,nc*CharWidthsize) file=FPOSScratch ] f>>FONT.WTPos.File=file ] ] ] and //Write directories!!!!! WriteDirectories() be [ let FSpos=vec 1 let CDpos=vec 1 let pFont=vec 3 //Write FS directory. WindowGetPosition(ws,FSpos) @pFont=0 while LoopFonts(pFont) do [ CursorToggle(1) let f=pFont!1 WindowWriteBlock(ws,lv f>>FONT.fs,size FDES/16) ] //Write CD directory. WindowGetPosition(ws,CDpos) WindowWriteBlock(ws,table [ 0;0 ] ,2) //pointer for dummy index let cp=vec 1 WindowGetPosition(ws,cp) //Account current position. @pFont=0 while LoopFonts(pFont) do [ CursorToggle(1) let f=pFont!1 if f>>FONT.indirect eq 0 then [ let fp=vec 1 let CD=vec 512 SetBlock(CD,-1,512) let p=pFont!0 while p do [ let t=p>>FPREQ.type test t ne FontPartCharacter then [ compileif ReportSw then [ let fr=Report>>REP.FontsRecorded if fr ne nReportFonts then [ let q=(lv Report>>REP.fonts)+(size REPFont/16)*fr fr=fr+1 Report>>REP.FontsRecorded=fr q>>REPFont.fam=p>>FPREQ.rfam q>>REPFont.face=p>>FPREQ.rface q>>REPFont.siz=p>>FPREQ.rsiz q>>REPFont.used=p>>FPREQ.fam ] ] let file=((t eq IXTypeChars)%(t eq IXTypeOrbitChars))? wfdir,ws let off=vec 1 DoubleCop(off,lv p>>FPREQ.sa) let rc=p>>FPREQ.rsource-p>>FPREQ.bc let nc=p>>FPREQ.rn-p>>FPREQ.rm+1 let nac=p>>FPREQ.ec-p>>FPREQ.bc+1 DPADi(off,CharWidthsize*nac) //Off=beg of CD DoubleCop(fp,off) DPADi(fp,rc*2) WindowSetPosition(file,fp) let oc=p>>FPREQ.rm-f>>FONT.bc WindowReadBlock(file,CD+oc*2,nc*2) if ((t eq IXTypeChars)%(t eq IXTypeOrbitChars)) then [ //Re-locate addresses. for i=0 to nc-1 do [ let p=CD+(oc+i)*2 if p!0 ne -1 then [ DoubleAdd(p,off) p>>FPOS.File=FPOSGod ] ] ] ] or [ //FontPartChar DoubleCop(CD+p>>FPREQ.rm*2,lv p>>CREQ.pos) ] p=p>>FPREQ.next ] let nc=f>>FONT.ec-f>>FONT.bc+1 WindowSetPosition(ws,cp) WindowWriteBlock(ws,CD,nc*2) WindowGetPosition(ws,cp) ] ] WindowSetPosition(ws,table [ 0;0 ]) //Return to beginning WindowWriteBlock(ws,cp,2) //Current end of file.... WindowWriteBlock(ws,FSpos,2) // and fill in Font Set adr WindowWriteBlock(ws,CDpos,2) // and CD adr ] and ComStr(a,b) = valof [ let len= a>>STR.length if len ne b>>STR.length then resultis false for i=1 to len do if ((a>>STR.char^i xor b>>STR.char^i)&(not #40)) ne 0 then resultis false resultis true ] (1792)\11668b50B2589b133B