<> <> <> <> <> <<>> DIRECTORY Atom USING [GetPName], Convert USING [AppendInt], Imager USING [Error], ImagerFont USING [Find, Font, Scale], NodeStyle USING [FontAlphabets, FontFace], NodeStyleFont USING [], Real USING [Round], RefText USING [AppendRope, AppendTextRope, ObtainScratch, ReleaseScratch], Rope USING [Equal, Find, FromRefText, Match, ROPE, Size], VFonts USING [DefaultFont]; NodeStyleFontImpl: CEDAR PROGRAM IMPORTS Atom, Convert, Real, Rope, RefText, Imager, ImagerFont, VFonts EXPORTS NodeStyleFont ~ BEGIN ROPE: TYPE ~ Rope.ROPE; FontAlphabets: TYPE ~ NodeStyle.FontAlphabets; FontFace: TYPE ~ NodeStyle.FontFace; Font: TYPE ~ ImagerFont.Font; PrefixKind: TYPE ~ RECORD [ pattern: ROPE, sizeInName: BOOL, faceEncoding: FaceEncoding ]; FaceEncoding: TYPE ~ {boldItalic, bir, bi}; prefixKinds: LIST OF PrefixKind _ LIST[ [pattern: "xerox/tiogafonts/", sizeInName: TRUE, faceEncoding: bi], [pattern: "xerox/pressfonts/", sizeInName: FALSE, faceEncoding: bir], [pattern: "xerox/altofonts/", sizeInName: TRUE, faceEncoding: bi], [pattern: "xerox/xc*", sizeInName: FALSE, faceEncoding: boldItalic] ]; AppendFontName: PROC [text: REF TEXT, prefix: ATOM, family: ATOM, face: FontFace, size: REAL, alphabets: FontAlphabets] RETURNS [new: REF TEXT, sizeInName: BOOL] ~ { fam: ROPE ~ Atom.GetPName[family]; pre: ROPE _ IF prefix#NIL THEN Atom.GetPName[prefix] ELSE NIL; faceEncoding: FaceEncoding _ boldItalic; IF Rope.Find[fam, "/"] >= 0 THEN { text _ RefText.AppendRope[text, fam]; RETURN [text, FALSE]; }; IF pre = NIL OR Rope.Size[pre] = 0 THEN pre _ "xerox/tiogafonts/"; sizeInName _ FALSE; FOR p: LIST OF PrefixKind _ prefixKinds, p.rest UNTIL p=NIL DO IF Rope.Match[p.first.pattern, pre, FALSE] THEN { sizeInName _ p.first.sizeInName; faceEncoding _ p.first.faceEncoding; }; ENDLOOP; text _ RefText.AppendRope[text, pre]; text _ RefText.AppendRope[text, fam]; IF sizeInName THEN { text _ Convert.AppendInt[text, Real.Round[size]]; }; SELECT faceEncoding FROM boldItalic => { IF face=Bold OR face=BoldItalic THEN text _ RefText.AppendTextRope[text, "-bold"]; IF face=Italic OR face=BoldItalic THEN text _ RefText.AppendTextRope[text, "-italic"]; }; bir => { text _ RefText.AppendTextRope[text, SELECT face FROM Bold => "-BRR", Italic => "-MIR", BoldItalic => "-BIR", ENDCASE => "-MRR"]; }; bi => { IF face=Bold OR face=BoldItalic THEN text _ RefText.AppendTextRope[text, "B"]; IF face=Italic OR face=BoldItalic THEN text _ RefText.AppendTextRope[text, "I"]; }; ENDCASE => ERROR; new _ text; }; FontNameFromStyleParams: PUBLIC PROC [prefix: ATOM, family: ATOM, face: FontFace, size: REAL, alphabets: FontAlphabets] RETURNS [name: ROPE, scale: REAL] ~ { scratch: REF TEXT ~ RefText.ObtainScratch[100]; text: REF TEXT _ scratch; sizeInName: BOOL _ FALSE; [text, sizeInName] _ AppendFontName[text, prefix, family, face, size, alphabets]; name _ Rope.FromRefText[text]; IF sizeInName THEN scale _ 1.0 ELSE scale _ size; RefText.ReleaseScratch[scratch]; }; nTrys: NAT ~ 4; tryDelta: ARRAY [0..nTrys) OF REAL _ [0, -0.999, 0.999, -1.998]; families: LIST OF LIST OF ATOM _ LIST[ LIST[$Tioga, $Laurel, $TimesRoman], LIST[$TimesRoman, $Classic], LIST[$Helvetica, $Modern, $TimesRoman], LIST[$Modern, $Helvetica], LIST[$Classic, $TimesRoman], LIST[$Gacha, $Helvetica] ]; SubstituteFamilies: PROC [family: ATOM] RETURNS [LIST OF ATOM] ~ { fam: ROPE ~ Atom.GetPName[family]; FOR f: LIST OF LIST OF ATOM _ families, f.rest UNTIL f=NIL DO k: ATOM _ f.first.first; IF family = k OR Rope.Equal[fam, Atom.GetPName[k]] THEN RETURN [f.first]; ENDLOOP; RETURN [NIL]; }; Replacement: PROC [prefix: ATOM, family: ATOM, face: FontFace, size: REAL, alphabets: FontAlphabets] RETURNS [font: ImagerFont.Font] _ NIL; <> <<>> horribleHackForTioga10: BOOL _ TRUE; FontFromStyleParams: PUBLIC PROC [prefix: ATOM, family: ATOM, face: FontFace, size: REAL, alphabets: FontAlphabets] RETURNS [font: ImagerFont.Font _ NIL] ~ { IF Replacement # NIL THEN { font _ Replacement[prefix, family, face, size, alphabets]; }; IF font = NIL THEN { scratch: REF TEXT ~ RefText.ObtainScratch[100]; text: REF TEXT _ scratch; sizeInName: BOOL _ FALSE; families: LIST OF ATOM _ NIL; trialFamily: ATOM _ family; IF horribleHackForTioga10 AND (family=$tioga OR family=$Tioga) AND (size NOT IN [9.5..10.5]) THEN { trialFamily _ family _ $TimesRoman; }; WHILE font = NIL AND trialFamily # NIL DO FOR try: NAT IN [0..nTrys) WHILE font=NIL DO trialSize: REAL _ size + tryDelta[try]; text.length _ 0; [text, sizeInName] _ AppendFontName[text, prefix, trialFamily, face, trialSize, alphabets]; TRUSTED { font _ ImagerFont.Find[LOOPHOLE[text] ! Imager.Error => CONTINUE]; }; IF NOT sizeInName THEN EXIT; ENDLOOP; IF font = NIL THEN { IF families = NIL THEN families _ SubstituteFamilies[family]; IF families # NIL THEN { families _ families.rest; }; trialFamily _ IF families=NIL THEN NIL ELSE families.first; }; ENDLOOP; IF font = NIL THEN { font _ VFonts.DefaultFont[font]; sizeInName _ TRUE; }; IF NOT sizeInName THEN { font _ ImagerFont.Scale[font, size]; }; RefText.ReleaseScratch[scratch]; }; }; END. <<>> <> <> <> <<>>