DIRECTORY Atom, Char, Convert, Imager, ImagerColor, ImagerFont, NodeStyle, NodeStyleFont, Real, RefText, Rope, SimpleFeedback; NodeStyle2Impl: CEDAR MONITOR IMPORTS Atom, Char, Convert, Imager, ImagerColor, ImagerFont, NodeStyle, Real, RefText, Rope, SimpleFeedback EXPORTS NodeStyle, NodeStyleFont ~ BEGIN OPEN NodeStyle; ROPE: TYPE ~ Rope.ROPE; Font: TYPE ~ ImagerFont.Font; PrefixKind: TYPE ~ RECORD [ pattern: ROPE, sizeInName: BOOL, preScaled: BOOL, -- Having pre-scaled fonts was probably a mistake, but we are sort of stuck, for now. faceEncoding: FaceEncoding ]; FaceEncoding: TYPE ~ {boldItalic, bir, bi}; prefixKinds: LIST OF PrefixKind ¬ LIST[ [pattern: "xerox/tiogafonts/", sizeInName: TRUE, preScaled: TRUE, faceEncoding: bi], [pattern: "xerox/pressfonts/", sizeInName: FALSE, preScaled: FALSE, faceEncoding: bir], [pattern: "xerox/altofonts/", sizeInName: TRUE, preScaled: TRUE, faceEncoding: bi], [pattern: "xerox/xc*/tioga-", sizeInName: TRUE, preScaled: FALSE, faceEncoding: boldItalic], [pattern: "xerox/xc*/", sizeInName: FALSE, preScaled: FALSE, faceEncoding: boldItalic] ]; boldItalicSuffix: ARRAY FontFace OF ROPE ~ [ Regular: "", Bold: "-bold", Italic: "-italic", BoldItalic: "-bold-italic" ]; birSuffix: ARRAY FontFace OF ROPE ~ [ Regular: "-MRR", Bold: "-BRR", Italic: "-MIR", BoldItalic: "-BIR" ]; biSuffix: ARRAY FontFace OF ROPE ~ [ Regular: "", Bold: "B", Italic: "I", BoldItalic: "BI" ]; faceIndex: ARRAY FontFace OF [0..4) ~ [ Regular: 0, Bold: 1, Italic: 2, BoldItalic: 3 ]; AppendFontName: PROC [text: REF TEXT, prefix: ATOM, family: ATOM, face: FontFace, size: REAL, alphabets: FontAlphabets] RETURNS [new: REF TEXT, sizeInName: BOOL ¬ FALSE, preScaled: BOOL ¬ FALSE] ~ { fam: ROPE ~ Atom.GetPName[family]; IF Rope.Find[fam, "/"] >= 0 THEN RETURN[RefText.AppendRope[text, fam]] ELSE { prePName: ROPE ~ IF prefix#NIL THEN Atom.GetPName[prefix] ELSE NIL; pre: ROPE ~ IF Rope.Size[prePName]>0 THEN prePName ELSE "xerox/tiogafonts/"; famSize: INT ~ Rope.Size[fam]; pos: ARRAY [0..4] OF INT ¬ ALL[famSize]; text ¬ RefText.AppendRope[text, pre]; FOR i: [0..4] IN [0..4] DO pos1: INT ~ IF i=0 THEN 0 ELSE pos[i-1]+1; s2: ROPE ~ SELECT i FROM 0 => "(", 4 => ")", ENDCASE => "|"; IF NOT (pos[i] ¬ Rope.Index[s1: fam, pos1: pos1, s2: s2]) { text ¬ RefText.AppendRope[text, boldItalicSuffix[face]]; IF sizeInName THEN { text ¬ RefText.AppendChar[text, '-]; text ¬ Convert.AppendInt[text, Real.Round[size]]; }; }; bir => { IF sizeInName THEN ERROR; text ¬ RefText.AppendRope[text, birSuffix[face]]; }; bi => { IF sizeInName THEN text ¬ Convert.AppendInt[text, Real.Round[size]]; text ¬ RefText.AppendRope[text, biSuffix[face]]; }; 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, preScaled: BOOL ¬ FALSE; [text, sizeInName, preScaled] ¬ AppendFontName[text, prefix, family, face, size, alphabets]; name ¬ Rope.FromRefText[text]; IF preScaled THEN scale ¬ 1.0 ELSE scale ¬ size; RefText.ReleaseScratch[scratch]; }; nTrys: NAT ~ 5; tryDelta: ARRAY [0..nTrys) OF REAL ¬ [0, -0.999, 0.999, -1.998, 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, $Modern], 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], FALSE] THEN RETURN [f.first]; ENDLOOP; RETURN [NIL]; }; FontReplacementProc: PROC [prefix: ATOM, family: ATOM, face: FontFace, size: REAL, alphabets: FontAlphabets] RETURNS [font: Font] ¬ NIL; horribleHackForTioga10: BOOL ¬ TRUE; defaultPrintFont: Font ¬ NIL; candidates: LIST OF ROPE ¬ LIST[ "xerox/xc1-2-2/modern", "xerox/pressfonts/helvetica-mrr" ]; GetDefaultFont: PROC RETURNS [Font] ~ { FOR each: LIST OF ROPE ¬ candidates, each.rest WHILE defaultPrintFont = NIL DO defaultPrintFont ¬ ImagerFont.Find[each.first, substituteQuietly ! Imager.Error => CONTINUE]; ENDLOOP; RETURN [defaultPrintFont] }; GetFont: PUBLIC PROC [style: Style] RETURNS [Font] ~ { RETURN FontFromStyleParams[ prefix: NodeStyle.GetName[style, fontPrefix], family: NodeStyle.GetName[style, fontFamily], face: NodeStyle.GetFontFace[style], size: NodeStyle.GetReal[style, fontSize], alphabets: NodeStyle.GetFontAlphabets[style] ]; }; GetSpaceWidth: PUBLIC PROC [style: NodeStyle.Ref] RETURNS [REAL] ~ { font: Font ~ GetFont[style]; RETURN[ImagerFont.Escapement[font, Char.Widen[' ]].x]; }; FontFromStyleParams: PUBLIC PROC [prefix: ATOM, family: ATOM, face: FontFace, size: REAL, alphabets: FontAlphabets] RETURNS [font: Font ¬ NIL] ~ { didSubstitution: BOOL ¬ FALSE; font ¬ CheckStyleFontCache[prefix, family, face, size, alphabets]; IF font = NIL THEN { IF FontReplacementProc # NIL THEN { font ¬ FontReplacementProc[prefix, family, face, size, alphabets]; }; IF font = NIL THEN { scratch: REF TEXT ~ RefText.ObtainScratch[100]; text: REF TEXT ¬ scratch; sizeInName, preScaled: BOOL ¬ FALSE; trialFace: FontFace ¬ face; WHILE font = NIL DO families: LIST OF ATOM ¬ NIL; trialFamily: ATOM ¬ family; firstFamily: ATOM ¬ family; IF horribleHackForTioga10 AND (firstFamily=$tioga OR firstFamily=$Tioga) AND (size NOT IN [9.5..10.5]) THEN { trialFamily ¬ firstFamily ¬ $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, preScaled] ¬ AppendFontName[text, prefix, trialFamily, trialFace, trialSize, alphabets]; font ¬ ImagerFont.Find[Rope.FromRefText[text], noSubstitute ! Imager.Error => CONTINUE]; IF font = NIL THEN didSubstitution ¬ TRUE; IF NOT sizeInName THEN EXIT; ENDLOOP; IF font = NIL THEN { IF families = NIL THEN families ¬ SubstituteFamilies[firstFamily]; IF families # NIL THEN { families ¬ families.rest; }; trialFamily ¬ IF families=NIL THEN NIL ELSE families.first; }; ENDLOOP; IF trialFace = Regular THEN EXIT; trialFace ¬ IF trialFace = BoldItalic THEN Bold ELSE IF trialFace = Bold AND face = BoldItalic THEN Italic ELSE Regular; ENDLOOP; IF font = NIL THEN { <> { font ¬ GetDefaultFont[]; preScaled ¬ FALSE }; }; IF NOT preScaled THEN { font ¬ ImagerFont.Scale[font, size] }; RefText.ReleaseScratch[scratch]; }; EnterStyleFontCache[[prefix, family, face, size, alphabets, font]]; }; IF didSubstitution THEN { text: REF TEXT ¬ RefText.ObtainScratch[100]; text ¬ RefText.AppendRope[text, "Substituting font "]; text ¬ RefText.AppendRope[text, ImagerFont.Name[font]]; text ¬ RefText.AppendRope[text, " for "]; text ¬ AppendFontName[text, prefix, family, face, size, alphabets].new; SimpleFeedback.Append[$Tioga, oneLiner, $Warning, Rope.FromRefText[text] ]; RefText.ReleaseScratch[text]; }; }; styleFontCacheSize: NAT ¬ 25; styleFontCache: LIST OF StyleFontCacheRec ¬ NIL; styleFontCacheHits: INT ¬ 0; styleFontCacheMisses: INT ¬ 0; StyleFontCacheRec: TYPE ~ RECORD [prefix: ATOM, family: ATOM, face: FontFace, size: REAL, alphabets: FontAlphabets, font: Font]; FlushStyleFontCache: ENTRY PROC ~ { styleFontCache ¬ NIL }; CheckStyleFontCache: ENTRY PROC [prefix: ATOM, family: ATOM, face: FontFace, size: REAL, alphabets: FontAlphabets] RETURNS [Font] ~ { prev: LIST OF StyleFontCacheRec ¬ NIL; FOR c: LIST OF StyleFontCacheRec ¬ styleFontCache, c.rest UNTIL c = NIL DO IF c.first.prefix = prefix AND c.first.family = family AND c.first.face = face AND c.first.size = size AND c.first.alphabets = alphabets THEN { IF prev # NIL THEN { prev.rest ¬ c.rest; c.rest ¬ styleFontCache; styleFontCache ¬ c; }; styleFontCacheHits ¬ styleFontCacheHits + 1; RETURN [c.first.font]; }; prev ¬ c; ENDLOOP; styleFontCacheMisses ¬ styleFontCacheMisses + 1; RETURN [NIL] }; EnterStyleFontCache: ENTRY PROC [styleFontCacheRec: StyleFontCacheRec] ~ { new: LIST OF StyleFontCacheRec ¬ NIL; prev: LIST OF StyleFontCacheRec ¬ NIL; i: NAT ¬ 2; FOR p: LIST OF StyleFontCacheRec ¬ styleFontCache, p.rest DO IF p = NIL THEN {new ¬ LIST[styleFontCacheRec]; EXIT}; IF i >= styleFontCacheSize AND p.rest#NIL THEN { new ¬ p.rest; p.rest ¬ NIL; new.rest ¬ NIL; new.first ¬ styleFontCacheRec; EXIT; }; i ¬ i + 1; ENDLOOP; new.rest ¬ styleFontCache; styleFontCache ¬ new; }; GetNamedColor: PROC [style: NodeStyle.Style, name: NodeStyle.NameParam] RETURNS [ImagerColor.Color] ~ { a: ATOM ~ NodeStyle.GetName[style, name]; RETURN [IF a=NIL OR a=$nil THEN NIL ELSE ImagerColor.Find[Atom.GetPName[a]]]; }; GetHSBColor: PROC [style: Style, h, s, b: NodeStyle.RealParam] RETURNS [ImagerColor.Color] ~ { brightness: REAL ~ NodeStyle.GetReal[style, b]; IF brightness = 0.0 THEN RETURN[Imager.black] ELSE { saturation: REAL ~ NodeStyle.GetReal[style, s]; IF saturation = 0.0 THEN RETURN[Imager.MakeGray[1.0-brightness]] ELSE { hue: REAL ~ NodeStyle.GetReal[style, h]; RETURN[ImagerColor.ColorFromHSV[H: hue, S: saturation, V: brightness]]; }; }; }; ColorParams: TYPE ~ RECORD [name: NodeStyle.NameParam, h, s, b: NodeStyle.RealParam]; paramsFromColorParam: ARRAY ColorParam OF ColorParams ~ [ text: [name: textNamedColor, h: textHue, s: textSaturation, b: textBrightness], underline: [name: underlineNamedColor, h: underlineHue, s: underlineSaturation, b: underlineBrightness], strikeout: [name: strikeoutNamedColor, h: strikeoutHue, s: strikeoutSaturation, b: strikeoutBrightness], outlineBox: [name: outlineBoxNamedColor, h: outlineBoxHue, s: outlineBoxSaturation, b: outlineBoxBrightness], background: [name: backgroundNamedColor, h: backgroundHue, s: backgroundSaturation, b: backgroundBrightness], area: [name: areaNamedColor, h: areaHue, s: areaSaturation, b: areaBrightness], outline: [name: outlineNamedColor, h: outlineHue, s: outlineSaturation, b: outlineBrightness] ]; GetColor: PUBLIC PROC [style: NodeStyle.Style, param: NodeStyle.ColorParam] RETURNS [color: ImagerColor.Color] ~ { p: ColorParams ~ paramsFromColorParam[param]; color ¬ GetNamedColor[style, p.name]; IF color = NIL THEN color ¬ GetHSBColor[style, p.h, p.s, p.b]; }; END.  NodeStyle2Impl.mesa Copyright Σ 1991, 1992, 1993 by Xerox Corporation. All rights reserved. Michael Plass, September 24, 1991 1:06 pm PDT Doug Wyatt, March 7, 1993 11:07 pm PST Font info Plug with debugger for experimentation purposes. Address fault if none of the default candidates were found This loop tries different faces. This loop tries different families. This loop tries different sizes of screen fonts. Last chance! Style Font Cache Move to front NB: The following code forces a styleFontCache size of >= 2 Color info Κ›•NewlineDelimiter ™codešœ™Kšœ Οeœ=™HK™-K™&K™—šΟk ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—KšΟnœžœž˜Kšžœe˜lKšžœ˜ šœžœžœ ˜K™Kšžœžœžœ˜Kšœžœ˜—head™ šœ žœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœΟcU˜fK˜Kšœ˜K˜—šœžœ˜+K˜—šœ žœžœžœ˜'Kšœ+žœ žœ˜TKšœ+žœ žœ˜WKšœ*žœ žœ˜SKšœ*žœ žœ˜\Kšœ$žœ žœ˜VKšœ˜K˜—šœžœ žœžœ˜,K˜IK˜K˜—šœ žœ žœžœ˜%K˜AK˜K˜—šœ žœ žœžœ˜$K˜5K˜K˜—šœ žœ žœ ˜'K˜-K˜K˜—šŸœžœžœžœ žœ žœžœžœžœžœžœžœ žœžœ˜ΗKšœžœ˜"Kšžœžœžœ˜Fšžœ˜Kš œ žœžœžœžœžœžœ˜CKš œžœžœžœ žœ˜LKšœ žœ˜Kš œžœžœžœžœ ˜(Kšœ%˜%šžœ žœž˜Kš œžœžœžœžœ ˜*Kš œžœžœžœžœ˜šžœ"žœžœ˜1Kšœ ˜ Kšœ˜Kšœ$˜$Kšœ˜—Kšžœ˜—Kšœ%˜%šžœž˜šœ˜K˜8šžœ žœ˜Kšœ$˜$Kšœ1˜1Kšœ˜—Kšœ˜—šœ˜Kšžœ žœžœ˜K˜1Kšœ˜—šœ˜Kšžœ žœ2˜DK˜0Kšœ˜—Kšžœžœ˜—K˜—Kšœ ˜ K˜—Kšœ˜K˜—šŸœžœžœ žœ žœžœžœžœ žœ˜Kšœ žœžœ˜/Kšœžœžœ ˜Kšœžœžœ˜$Kšœ\˜\Kšœ˜Kšžœ žœ žœ˜0Kšœ ˜ Kšœ˜K˜—Kšœžœ˜Kšœ žœ žœžœ%˜Gš œ žœžœžœžœžœžœ˜&Kšžœ˜#Kšžœ˜Kšžœ#˜'Kšžœ˜Kšžœ!˜%Kšžœ˜K˜K˜—šŸœžœ žœžœžœžœžœ˜BKšœžœ˜"šžœžœžœžœžœžœžœžœž˜=Kšœžœ˜Kš žœ žœ#žœžœžœ ˜PKšžœ˜—Kšžœžœ˜ K˜K˜—šŸœžœ žœ žœžœžœžœ˜ˆK™0K™—šœžœžœ˜$K˜—Kšœžœ˜š œ žœžœžœžœ˜ K˜K˜ Kšœ˜K™—šŸœžœžœ ˜'š žœžœžœžœžœžœž˜NKšœ:™:KšœSžœ˜]Kšžœ˜—Kšžœ˜Kšœ˜K˜—šŸœžœžœžœ ˜6šžœ˜Kšœ-˜-Kšœ-˜-Kšœ#˜#Kšœ)˜)Kšœ,˜,Kšœ˜—K˜K˜—š Ÿ œžœžœžœžœ˜DKšœ˜Kšžœ0˜6Kšœ˜K˜—šŸœžœžœ žœ žœžœžœžœ˜’Kšœžœžœ˜KšœB˜Bšžœžœžœ˜šžœžœžœ˜#KšœB˜BKšœ˜—šžœžœžœ˜Kšœ žœžœ˜/Kšœžœžœ ˜Kšœžœžœ˜$Kšœ˜šžœžœž˜K™ Kš œ žœžœžœžœ˜Kšœ žœ ˜Kšœ žœ ˜šžœžœžœžœžœžœžœ˜mKšœ(˜(Kšœ˜—š žœžœžœžœž˜)K™#š žœžœžœ žœžœž˜.K™0Kšœ žœ˜'Kšœ˜Kšœk˜kKšœNžœ˜XKšžœžœžœžœ˜*Kšžœžœ žœžœ˜Kšžœ˜—šžœžœžœ˜Kšžœ žœžœ,˜Bšžœ žœžœ˜Kšœ˜Kšœ˜—Kš œžœ žœžœžœžœ˜;Kšœ˜—Kšžœ˜—Kšžœžœžœ˜!Kšœ žœžœžœžœžœžœžœ ˜xKšžœ˜—šžœžœžœ˜K™ šΠkyΟy ‘’%˜8Kš‘’0‘’Πcy˜WKš‘’(‘’‘˜5—Kšœ'žœ˜/Kšœ˜—Kšžœžœ žœ)˜>Kšœ ˜ Kšœ˜—KšœC˜CKšœ˜—šžœžœ˜Kšœžœžœ˜,Kšœ6˜6Kšœ7˜7Kšœ)˜)KšœG˜GKšœK˜KKšœ˜Kšœ˜—Kšœ˜——šœ™Kšœžœ˜Kšœžœžœžœ˜0Kšœžœ˜šœžœ˜K˜—š œžœžœ žœ žœžœ(˜€K˜—šŸœžœžœžœ˜;K˜—šŸœžœžœ žœ žœžœžœ ˜…Kšœžœžœžœ˜&š žœžœžœ,žœžœž˜JKšžœ˜Kšžœ˜Kšžœ˜Kšžœ˜Kšžœ˜!šžœ˜šžœžœžœ˜K™ Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ,˜,Kšžœ˜Kšœ˜—Kšœ ˜ Kšžœ˜—Kšœ0˜0Kšžœžœ˜ Kšœ˜K˜—šŸœžœžœ+˜JKšœžœžœžœ˜%Kšœžœžœžœ˜&Kšœžœ˜ K™;šžœžœžœ,ž˜K˜K˜——K™Kšžœ˜J˜—…—+Š