DIRECTORY Atom USING [GetPName], Basics USING [bytesPerWord, LongNumber], FS USING [Error, StreamOpen, StreamOptions], ImagerFont USING [Font, Width], IO USING [Close, Error, SetIndex, STREAM, UnsafeGetBlock], MessageWindow USING [Append, Blink], NodeStyle USING [FontFace, GetFontFamily, GetFontFace, GetFontSize, GetReal, Style], NodeStyleFont USING [FontFromStyleParams], Rope USING [Cat, Concat, ROPE]; NodeStyleSpacesImpl: CEDAR PROGRAM IMPORTS Atom, FS, ImagerFont, IO, MessageWindow, NodeStyle, NodeStyleFont, Rope EXPORTS NodeStyle ~ BEGIN ROPE: TYPE ~ Rope.ROPE; GetScreenSpaceWidth: PUBLIC PROC[style: NodeStyle.Style] RETURNS[REAL] ~ { font: ImagerFont.Font _ style.font; IF font = NIL THEN font _ NodeStyleFont.FontFromStyleParams[prefix: style.name[fontPrefix], family: style.name[fontFamily], face: style.fontFace, size: NodeStyle.GetReal[style, fontSize], alphabets: style.fontAlphabets]; RETURN[ImagerFont.Width[font, [set: 0, code: 40B]].x]; }; GetPrintSpaceWidth: PUBLIC PROC[style: NodeStyle.Style] RETURNS[width: REAL] ~ { family: ROPE ~ Atom.GetPName[NodeStyle.GetFontFamily[style]]; face: NodeStyle.FontFace ~ NodeStyle.GetFontFace[style]; size: REAL ~ NodeStyle.GetFontSize[style]; fontName: ROPE ~ family.Concat[SELECT face FROM Regular => "", Bold => "B", Italic => "I", BoldItalic => "BI", ENDCASE => ERROR]; tfmName: ROPE ~ Rope.Cat["///Fonts/FontMetrics/", fontName, ".tfm"]; stream: IO.STREAM _ NIL; oops: BOOL _ FALSE; binaryStreamOptions: FS.StreamOptions ~ [tiogaRead: FALSE, commitAndReopenTransOnFlush: TRUE, truncatePagesOnClose: TRUE, finishTransOnClose: TRUE, closeFSOpenFileOnClose: TRUE]; Protest: PROC [why: ROPE] = { MessageWindow.Append[why, TRUE]; MessageWindow.Append[" (using 1/2 font size for space size)", FALSE]; MessageWindow.Blink[]; }; width _ size/2; -- default in case of disaster; stream _ FS.StreamOpen[fileName: tfmName, accessOptions: $read, streamOptions: binaryStreamOptions ! FS.Error => { Protest[error.explanation]; CONTINUE }]; IF stream#NIL THEN TRUSTED { dir: Directory; dirAddr: LONG POINTER _ @dir; param: Param; paramAddr: LONG POINTER _ @param; [] _ stream.UnsafeGetBlock[ [base: dirAddr, startIndex: 0, count: SIZE[Directory]*Basics.bytesPerWord] ! IO.Error => {oops _ TRUE; CONTINUE} ]; oops _ oops OR NOT ValidDirectory[dir]; IF NOT oops THEN stream.SetIndex[ParamStart[dir]*SIZE[Word]*Basics.bytesPerWord ! IO.Error => {oops _ TRUE; CONTINUE} ]; IF NOT oops THEN [] _ stream.UnsafeGetBlock[ [base: paramAddr, startIndex: 0, count: SIZE[Param]*Basics.bytesPerWord] ! IO.Error => {oops _ TRUE; CONTINUE} ]; IF oops THEN Protest[Rope.Concat[tfmName, " is invalid"]] ELSE { unscaledSpaceWidth: REAL _ Long[param[spaceWidth]]/realTwoToTheTwentieth; width _ unscaledSpaceWidth*size; }; stream.Close[! IO.Error => CONTINUE]; }; }; twoToTheTenth: INT ~ 2*2*2*2*2 * 2*2*2*2*2; twoToTheTwentieth: INT ~ twoToTheTenth*twoToTheTenth; realTwoToTheTwentieth: REAL ~ twoToTheTwentieth; Word: TYPE ~ MACHINE DEPENDENT RECORD [hiHalf, lowHalf: CARDINAL]; Fixed: TYPE ~ MACHINE DEPENDENT RECORD [ValueTimesTwoToTheTwentieth: Word]; FixedArray: TYPE ~ MACHINE DEPENDENT RECORD [ entry(0): PACKED SEQUENCE COMPUTED CARDINAL OF Fixed]; Long: PROC [w: Word] RETURNS [INT] ~ INLINE { t: Basics.LongNumber _ [num[lowbits: w.lowHalf, highbits: w.hiHalf]]; RETURN[t.li] }; Directory: TYPE ~ MACHINE DEPENDENT RECORD [ lf: CARDINAL, -- length of entire file in Words lh: CARDINAL, -- length of header data bc: CARDINAL, -- first character code in font ec: CARDINAL, -- last character code in font nw: CARDINAL, -- number of Words in width table nh: CARDINAL, -- number of Words in height table nd: CARDINAL, -- number of Words in depth table ni: CARDINAL, -- number of Words in italic correction table nl: CARDINAL, -- number of Words of lig/kern program nk: CARDINAL, -- number of Words in kern table ne: CARDINAL, -- number of Words in extensible character table np: CARDINAL -- number of font parameters ]; ValidDirectory: PROC [h: Directory] RETURNS [BOOLEAN] ~ { OPEN h; RETURN [lh<=24 -- Allow headers to grow a bit -- AND ec>=bc AND ec<256 AND nw <= 256 AND nh <= 16 AND nd <= 16 AND ni <= 64 AND nl <= 256 AND nk <= 256 AND ne <= 256 AND np <= 24 AND lf = 6 + lh + (ec-bc+1) + nw + nh + nd + ni + nl + nk + ne + np] }; ParamStart: PROC [h: Directory] RETURNS [CARDINAL] ~ INLINE { OPEN h; RETURN [6 + lh + (ec-bc+1) + nw + nh + nd + ni + nl + nk + ne] }; Param: TYPE ~ PACKED ARRAY ParamIndex OF Fixed; ParamIndex: TYPE ~ MACHINE DEPENDENT {-- see MetaFont manual, pages 98-100 slant(0), -- index for amount of italic slant (do not scale) spaceWidth(1), spaceStretch(2), spaceShrink(3), xHeight(4), quad(5), x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,mathSyParamLen }; END. NodeStyleSpacesImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Michael Plass, May 16, 1984 5:31:11 pm PDT Rick Beach, March 23, 1985 5:20:39 pm PST Russ Atkinson (RRA) June 20, 1985 2:10:21 am PDT Doug Wyatt, September 2, 1986 1:16:35 pm PDT Space width attributes (exported to NodeStyle) Copied from TFM defs note a Word is 32 bits long, and in BigEndian order. Κ'˜codešœ™Kšœ Οmœ7™BK™*J™)K™0K™,—K˜šΟk ˜ Kšœžœ ˜Kšœžœ˜(Kšžœžœ$˜,Kšœ žœ˜Kšžœžœžœ˜:Kšœžœ˜$Kšœ žœE˜TKšœžœ˜*Kšœžœžœ˜—headšœžœž˜"Kšžœžœžœ/˜OKšžœ ˜Kšœž˜K˜Kšžœžœžœ˜—™.š Οnœžœžœžœžœ˜JKšœ#˜#KšžœžœžœΚ˜άKšžœ0˜6Kšœ˜K˜—š Ÿœžœžœžœžœ˜PKšœžœ1˜=Kšœ8˜8Kšœžœ ˜*Kš œ žœžœžœ@žœžœ˜Kšœ žœ7˜DKšœžœžœžœ˜Kšœžœžœ˜Kš œžœžœžœžœžœžœ˜²šŸœžœžœ˜Kšœžœ˜ Kšœ>žœ˜EKšœ˜K˜—KšœΟc˜/šœ žœW˜bšœžœ ˜Kšœ˜Kšž˜Kšœ˜——šžœžœžœžœ˜Kšœ˜Kšœ žœžœ˜Kšœ ˜ Kšœ žœžœ ˜!šœBžœ ˜fKšœžœžœžœ˜%Kšœ˜—Kšœ žœžœ˜'šžœžœžœ!žœ˜OKšœžœžœžœ˜%Kšœ˜—šžœžœžœEžœ˜uKšœžœžœžœ˜%Kšœ˜—šžœ˜Kšžœ-˜1šžœ˜Kšœžœ1˜IKšœ ˜ K˜——Kšœžœ žœ˜%Kšœ˜—Kšœ˜K™—Kšœžœ˜+Kšœžœ˜5Kšœžœ˜0—™š œžœžœž œžœžœ˜BKšœ4™4—Kš œžœžœž œžœ%˜Kš œ žœžœž œžœ˜-Kš œ žœžœžœžœžœ˜6K˜—š Ÿœžœ žœžœžœ˜-KšœE˜EKšžœ˜ Kšœ˜K˜—š œ žœžœž œžœ˜,Kšœžœ !˜/Kšœžœ ˜&Kšœžœ ˜-Kšœžœ ˜,Kšœžœ !˜/Kšœžœ "˜0Kšœžœ !˜/Kšœžœ -˜;Kšœžœ &˜4Kšœžœ  ˜.Kšœžœ 0˜>Kšœžœ ˜*˜K˜——šŸœžœžœžœ˜9Kšžœ˜šžœ  !œž˜4Kšœžœž˜Kšœ ž˜ Kšœ ž˜ Kšœ ž˜ Kšœ ž˜ Kšœ ž˜ Kšœ ž˜ Kšœ ž˜ Kšœ ž˜ K˜@—Kšœ˜K˜—š Ÿ œžœžœžœžœ˜=Kšžœ˜Kšžœ8˜>Kšœ˜K˜—š œžœžœžœ žœ˜/K˜—šœ žœžœž œ $˜JKšœ  2˜