<> <> <> <<>> DIRECTORY Ascii, Atom, Checksum, ImagerPress, ImagerPressFontSubst, ImagerTransformation, Rope, Real, RefTab, RefText, PrincOps; ImagerPressFontSubstImpl: CEDAR MONITOR IMPORTS Ascii, Atom, Checksum, RefTab, ImagerTransformation, Rope, Real, RefText EXPORTS ImagerPressFontSubst SHARES Rope ~ BEGIN OPEN ImagerPressFontSubst; PrinterType: TYPE ~ ImagerPress.PrinterType; Transformation: TYPE ~ ImagerTransformation.Transformation; FactoredTransformation: TYPE ~ ImagerTransformation.FactoredTransformation; FontAtom: TYPE ~ REF FontAtomRep; FontAtomRep: TYPE ~ RECORD [name: ATOM, m: Transformation]; TransformationRep: TYPE ~ ImagerTransformation.TransformationRep; hashTableSize: NAT ~ 253; HashIndex: TYPE ~ [0..hashTableSize); HashTable: TYPE ~ REF HashTableRep; HashTableRep: TYPE ~ ARRAY HashIndex OF FontAtomList; FontAtomList: TYPE ~ LIST OF FontAtom; hashTable: HashTable ~ NEW[HashTableRep _ ALL[NIL]]; entries: INT _ 0; collisions: INT _ 0; misses: INT _ 0; Munch: PROC[LONG CARDINAL] RETURNS[CARDINAL] ~ TRUSTED MACHINE CODE { PrincOps.zXOR }; Hash: PROC[atom: ATOM, m: Transformation] RETURNS[CARDINAL] ~ TRUSTED INLINE { RETURN[Checksum.ComputeChecksum[cs: Munch[LOOPHOLE[atom]], nWords: SIZE[TransformationRep], p: LOOPHOLE[m]]]; }; MakeFontAtom: PUBLIC ENTRY PROC [name: ATOM, m: Transformation] RETURNS [FontAtom] ~ { ENABLE UNWIND => NULL; hash: CARDINAL ~ Hash[name, m]; hashIndex: HashIndex ~ hash MOD hashTableSize; head: FontAtomList ~ hashTable[hashIndex]; FOR each: FontAtomList _ head, each.rest UNTIL each=NIL DO f: FontAtom ~ each.first; IF f.name=name AND ImagerTransformation.Equal[f.m, m] THEN RETURN[f] ELSE misses _ misses+1; ENDLOOP; { f: FontAtom ~ NEW[FontAtomRep _ [name: name, m: ImagerTransformation.Copy[m]]]; hashTable[hashIndex] _ CONS[f, head]; entries _ entries+1; IF head#NIL THEN collisions _ collisions+1; RETURN[f]; }; }; ROPE: TYPE ~ Rope.ROPE; tables: ARRAY PrinterType OF RefTab.Ref ~ [RefTab.Create[], RefTab.Create[]]; scratch: REF TEXT _ NEW[TEXT[40]]; LowerCaseAtom: ENTRY PROC [fontName: ROPE] RETURNS [ATOM] ~ { action: PROC [c: CHAR] RETURNS [quit: BOOL _ FALSE] ~ { scratch _ RefText.AppendChar[scratch, c]; }; scratch.length _ 0; [] _ Rope.Map[base: fontName, action: action]; RETURN [Atom.MakeAtomFromRefText[scratch]] }; FindSubstitute: PUBLIC PROC [fontName: ROPE, m: Transformation, printerType: PrinterType] RETURNS [PressFontDescription] ~ { fontAtom: FontAtom ~ MakeFontAtom[LowerCaseAtom[fontName], m]; refTab: RefTab.Ref ~ tables[printerType]; pfd: PressFontDescription ~ NARROW[RefTab.Fetch[refTab, fontAtom].val]; IF pfd = NIL THEN RETURN [LookForSomethingClose[fontAtom, refTab]] ELSE RETURN [pfd]; }; knownPrefixes: LIST OF ROPE _ LIST [ "xerox/pressfonts/", "xerox/xc2-2-2/", "xerox/xc1-1-1/", "xerox/xc0-0-0/", "xerox/xc82-0-0/" ]; PrefixSize: PROC [name: ROPE] RETURNS [size: INTEGER] ~ { <> Check: PROC [prefix: ROPE] RETURNS [INTEGER] ~ { s: NAT ~ Rope.Size[prefix]; IF Rope.Run[s1: prefix, pos1: 0, s2: name, pos2: 0, case: FALSE] = s THEN RETURN [s] ELSE RETURN [-1] }; FOR r: LIST OF ROPE _ knownPrefixes, r.rest UNTIL r = NIL DO size _ Check[r.first]; IF size >= 0 THEN RETURN; ENDLOOP; }; MatchFamily: PROC [r1: Rope.Text, s1: NAT, r2: Rope.Text, s2: NAT] RETURNS [INTEGER] ~ { <> len1: NAT ~ r1.length; len2: NAT ~ r2.length; matchLen: INTEGER _ 0; matchLen _ 0; WHILE s1+matchLen < len1 AND s2+matchLen < len2 DO c1: CHAR _ Ascii.Lower[r1[s1+matchLen]]; c2: CHAR _ Ascii.Lower[r2[s2+matchLen]]; IF c1 = '- THEN c1 _ '/; IF c2 = '- THEN c2 _ '/; IF c1#c2 THEN RETURN [-1]; IF c1='/ THEN RETURN [matchLen]; matchLen _ matchLen + 1; ENDLOOP; IF len1-s1 = len2-s2 THEN RETURN [matchLen] ELSE RETURN [-1]; }; Face: PROC [name: Rope.Text, start: NAT] RETURNS [face: INTEGER] ~ { italicCode: NAT ~ 1; boldCode: NAT ~ 2; lightCode: NAT ~ 4; condensedCode: NAT ~ 6; expandedCode: NAT ~ 12; seen: ARRAY [1..3] OF BOOL _ ALL[FALSE]; len: NAT ~ name.length; Match: PROC [prefix: ROPE] RETURNS [BOOL] ~ { s: NAT ~ Rope.Size[prefix]; IF Rope.Run[s1: prefix, pos1: 0, s2: name, pos2: start, case: FALSE] = s THEN { start _ start + s; RETURN [TRUE] } ELSE RETURN [FALSE] }; FinishOldStyle: PROC RETURNS [BOOL _ TRUE] ~ { SELECT TRUE FROM Match["i"] => {face _ face + italicCode}; Match["r"] => NULL; ENDCASE => RETURN [FALSE]; SELECT TRUE FROM Match["r"] => NULL; Match["c"] => {face _ face + condensedCode}; Match["e"] => {face _ face + expandedCode}; ENDCASE => RETURN [FALSE]; RETURN [start=len]; }; face _ 0; WHILE start < len DO SELECT TRUE FROM Match["-"] => NULL; Match["/"] => NULL; NOT seen[1] AND Match["bold"] => {seen[1] _ TRUE; face _ face + boldCode}; NOT seen[1] AND Match["light"] => {seen[1] _ TRUE; face _ face + lightCode}; NOT seen[2] AND Match["italic"] => {seen[2] _ TRUE; face _ face + italicCode}; NOT seen[3] AND Match["condensed"] => {seen[3] _ TRUE; face _ face + condensedCode}; NOT seen[3] AND Match["expanded"] => {seen[1] _ TRUE; face _ face + expandedCode}; seen = ALL[FALSE] AND Match["m"] => {IF NOT FinishOldStyle[] THEN RETURN [-1]}; seen = ALL[FALSE] AND Match["b"] => {face _ face + boldCode; IF NOT FinishOldStyle[] THEN RETURN [-1]}; seen = ALL[FALSE] AND Match["l"] => {face _ face + lightCode; IF NOT FinishOldStyle[] THEN RETURN [-1]}; ENDCASE => RETURN [-1]; ENDLOOP; }; IsAlias: PROC [name: ATOM, rootName: ATOM] RETURNS [BOOL] ~ { IF name # rootName THEN { nameRope: Rope.Text ~ Atom.GetPName[name]; rootRope: Rope.Text ~ Atom.GetPName[rootName]; prefixSize: INTEGER ~ PrefixSize[nameRope]; rootPrefixSize: INTEGER ~ PrefixSize[rootRope]; familySize: INTEGER; face: INTEGER; IF prefixSize < 0 THEN RETURN [FALSE]; familySize _ MatchFamily[nameRope, prefixSize, rootRope, rootPrefixSize]; IF familySize < 0 THEN RETURN [FALSE]; face _ Face[nameRope, prefixSize+familySize]; IF face < 0 OR face # Face[rootRope, rootPrefixSize+familySize] THEN RETURN [FALSE]; }; RETURN [TRUE]; }; maxDifSqrForMatch: REAL _ 4*(35.27778*35.27778); zeroTransformation: Transformation ~ ImagerTransformation.Scale[0]; LookForSomethingClose: ENTRY PROC [fontAtom: FontAtom, refTab: RefTab.Ref] RETURNS [PressFontDescription] ~ { closestFontAtom: FontAtom _ NIL; closestPFD: PressFontDescription _ NIL; matchDifferenceSqr: REAL _ Real.LargestNumber; pfd: PressFontDescription _ NARROW[RefTab.Fetch[refTab, fontAtom].val]; Action: PROC [key, val: REF] RETURNS [quit: BOOLEAN _ FALSE] ~ { keyFontAtom: FontAtom ~ NARROW[key]; valPfd: PressFontDescription ~ NARROW[val]; IF valPfd.exact AND IsAlias[fontAtom.name, keyFontAtom.name] THEN { m: ImagerTransformation.TransformationRep ~ fontAtom.m^; n: ImagerTransformation.TransformationRep ~ keyFontAtom.m^; Sqr: PROC [a: REAL] RETURNS [REAL] ~ INLINE {RETURN [a*a]}; difSqr: REAL ~ IF n = zeroTransformation^ THEN 1.0 ELSE Sqr[m.a-n.a]+Sqr[m.b-n.b]+Sqr[m.c-n.c]+Sqr[m.d-n.d]+Sqr[m.e-n.e]+Sqr[m.f-n.f]; IF difSqr < matchDifferenceSqr THEN { closestFontAtom _ keyFontAtom; closestPFD _ valPfd; matchDifferenceSqr _ difSqr; IF difSqr = 0.0 THEN quit _ TRUE; }; }; }; IF pfd # NIL THEN RETURN [pfd]; [] _ RefTab.Pairs[refTab, Action]; IF closestPFD # NIL AND matchDifferenceSqr <= maxDifSqrForMatch THEN { pfd _ NEW[PressFontDescriptionRep _ closestPFD^]; pfd.veryClose _ matchDifferenceSqr <= 1.0; pfd.exact _ FALSE; IF pfd.size = 0 THEN { f: FactoredTransformation ~ ImagerTransformation.Factor[fontAtom.m]; IF f.s.x NOT IN [f.s.y*0.99..f.s.y*1.01] OR f.t # [0.0, 0.0] THEN pfd _ NIL ELSE { theta: REAL _ f.r1 + f.r2; WHILE theta >= 360.0 DO theta _ theta - 360.0 ENDLOOP; WHILE theta < 0.0 DO theta _ theta + 360.0 ENDLOOP; pfd.size _ Real.Round[f.s.x]; pfd.rotation _ Real.Round[theta*60]; }; }; IF pfd # NIL THEN [] _ RefTab.Store[refTab, fontAtom, pfd]; }; RETURN [pfd]; }; Init: PROC [] ~ { SizeRec: TYPE ~ RECORD [a, b, c, d, e: CARDINAL _ CARDINAL.LAST]; RotRec: TYPE ~ RECORD [a, b, c: CARDINAL _ CARDINAL.LAST]; FaceRec: TYPE ~ RECORD [a, b, c, d: MyFace]; MyFace: TYPE ~ {nil, r, b, i, bi} _ nil; micasPerPoint: REAL _ 2540/72.0; Full: PROC[family: ROPE, face: MyFace] RETURNS [ROPE] ~ { RETURN [Rope.Cat["xerox/pressfonts/", family, "-", SELECT face FROM r => "mrr", b => "brr", i => "mir", bi => "bir", ENDCASE => ERROR]] }; Def: PROC [family: ROPE, ff: FaceRec, ss: SizeRec, rr: RotRec] ~ { faces: ARRAY [0..4) OF MyFace ~ [ff.a, ff.b, ff.c, ff.d]; sizes: ARRAY [0..5) OF CARDINAL ~ [ss.a, ss.b, ss.c, ss.d, ss.e]; rotations: ARRAY [0..3) OF CARDINAL ~ [rr.a, rr.b, rr.c]; FOR f: NAT IN [0..4) UNTIL faces[f] = nil DO name: ROPE ~ Full[family, faces[f]]; nameAtom: ATOM ~ Atom.MakeAtom[name]; FOR s: NAT IN [0..5) UNTIL sizes[s] = CARDINAL.LAST DO micas: NAT ~ Real.Round[sizes[s]*micasPerPoint]; FOR r: NAT IN [0..3) UNTIL rotations[r] = CARDINAL.LAST DO pfd: PressFontDescription _ NEW[PressFontDescriptionRep _ [ family: family, face: SELECT faces[f] FROM r => 0, b => 2, i => 1, bi => 3, ENDCASE => ERROR, rotation: rotations[r]*INT[60], -- in minutes of arc size: micas, veryClose: TRUE, exact: TRUE ]]; fontAtom: FontAtom ~ MakeFontAtom[nameAtom, ImagerTransformation.Scale[micas].PreRotate[rotations[r]]]; [] _ RefTab.Store[tables[press], fontAtom, pfd]; [] _ RefTab.Store[tables[spruce], fontAtom, pfd]; ENDLOOP; ENDLOOP; ENDLOOP; }; DefPress: PROC [family: ROPE, ff: FaceRec] ~ { faces: ARRAY [0..4) OF MyFace ~ [ff.a, ff.b, ff.c, ff.d]; FOR f: NAT IN [0..4) UNTIL faces[f] = nil DO name: ROPE ~ Full[family, faces[f]]; nameAtom: ATOM ~ Atom.MakeAtom[name]; pfd: PressFontDescription _ NEW[PressFontDescriptionRep _ [ family: family, face: SELECT faces[f] FROM r => 0, b => 2, i => 1, bi => 3, ENDCASE => ERROR, rotation: 0, -- in minutes of arc size: 0, veryClose: TRUE, exact: TRUE ]]; fontAtom: FontAtom ~ MakeFontAtom[nameAtom, zeroTransformation]; [] _ RefTab.Store[tables[press], fontAtom, pfd]; ENDLOOP; }; Def["arrows", [r], [10], [0, 90, 270]]; Def["classic", [r, b, i], [6, 7, 8, 9, 10], [0, 90, 270]]; Def["classic", [r, b, i], [11, 12, 14, 18], [0, 90, 270]]; Def["classicpione", [r, b, i], [8, 10, 12], [0, 90, 270]]; Def["gacha", [r, b, i, bi], [5, 6, 7, 8, 9], [0]]; Def["gacha", [r, b, i, bi], [10, 12], [0]]; Def["gacha", [r], [5, 6, 8, 10, 12], [90, 270]]; Def["gates", [r], [10, 12, 18, 32], [0]]; Def["gates", [r], [32], [90, 270]]; Def["helvetica", [r, b, i, bi], [6, 7, 8, 9, 10], [0, 90, 270]]; Def["helvetica", [r, b, i, bi], [11, 12, 14, 18], [0, 90, 270]]; Def["helvetica", [r], [3, 4, 5], [0]]; Def["helvetica", [b], [24, 36], [0, 90, 270]]; Def["helveticad", [r], [24, 30, 36], [0, 90]]; Def["helveticad", [r], [24, 36], [270]]; Def["hippo", [r], [6, 8, 10, 12, 14], [0]]; Def["hippo", [r], [18], [0]]; Def["hippo", [r], [8, 10, 12], [90, 270]]; Def["keyhole", [b], [20], [0, 90, 270]]; Def["keyhole", [r], [20], [0]]; Def["laurel", [r], [10], [0]]; Def["logo", [r], [12, 18, 24], [0, 90, 270]]; Def["math", [r], [6, 8, 10, 12, 14], [0]]; Def["math", [r], [18], [0]]; Def["mockingbird", [r], [24], [0]]; Def["oldenglish", [r], [10, 12, 18, 24, 36], [0]]; Def["oldenglish", [r], [48], [0]]; Def["oldenglish", [r], [18], [90, 270]]; Def["timesromand", [r], [24, 30, 36], [0, 90]]; Def["timesromand", [r], [24, 36], [270]]; Def["template", [r], [10, 12, 18, 64], [0]]; Def["template", [r], [64], [90, 270]]; Def["timesroman", [r, b, i, bi], [6, 7, 8, 9, 10], [0, 90, 270]]; Def["timesroman", [r, b, i, bi], [11, 12, 14, 18], [0, 90, 270]]; Def["timesroman", [r], [4], [0, 90, 270]]; Def["timesroman", [b], [24, 30, 36], [0, 90, 270]]; Def["xeroxbook", [r, b], [10, 12], [0, 90, 270]]; DefPress["arrows", [r]]; DefPress["classic", [r, b, i]]; DefPress["classicpione", [r, b, i]]; DefPress["gacha", [r]]; DefPress["gates", [r]]; DefPress["helvetica", [r, b, i, bi]]; DefPress["hippo", [r]]; DefPress["keyhole", [b]]; DefPress["laurel", [r]]; DefPress["logo", [r]]; DefPress["math", [r]]; DefPress["mockingbird", [r]]; DefPress["oldenglish", [r]]; DefPress["template", [r]]; DefPress["timesroman", [r, b, i, bi]]; DefPress["xeroxbook", [r, b]]; }; Init[]; END. <<>>