ImagerPressFontSubstImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Michael Plass, July 11, 1985 1:19:35 pm PDT
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 TEXTNEW[TEXT[40]];
LowerCaseAtom: ENTRY PROC [fontName: ROPE] RETURNS [ATOM] ~ {
action: PROC [c: CHAR] RETURNS [quit: BOOLFALSE] ~ {
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 ROPELIST [
"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] ~ {
returns the length of the prefix (counting the terminating character) if it is known; otherwise returns -1.
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] ~ {
returns the length of the family (not counting the terminating character) if the families match; otherwise returns -1.
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 BOOLALL[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 [BOOLTRUE] ~ {
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: BOOLEANFALSE] ~ {
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: CARDINALCARDINAL.LAST];
RotRec: TYPE ~ RECORD [a, b, c: CARDINALCARDINAL.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.