-- TEditFontImpl.mesa; Last Edited by McGregor, January 29, 1982 10:19 am DIRECTORY Directory USING [Error, Lookup], File USING [Capability, GetSize, PageCount], Inline USING [LowHalf], LongString USING [AppendDecimal, AppendString], NodeStyle USING [Dist], Real USING [RoundC], Runtime USING [CallDebugger], Space USING [Create, Handle, LongPointer, Map, PageCount, virtualMemory], TEditFont, NameSymbolTable USING [FromName, Name]; TEditFontImpl: PROGRAM IMPORTS Directory, File, Inline, LongString, NameSymbolTable, Real, Runtime, TEditFont, Space EXPORTS TEditFont = BEGIN OPEN TEditFont; -- declarations for strike format font files defaultFont: PUBLIC TEditFont.Font _ NIL; Error: PUBLIC ERROR [code: TEditFont.ErrorCode] = CODE; Strike: TYPE = LONG POINTER TO StrikeObject; StrikeObject: TYPE = RECORD [header: StrikeHeader, body: StrikeBody]; StrikeHeader: TYPE = RECORD [ bits: StrikeBits, min: CARDINAL, max: CARDINAL, maxwidth: CARDINAL]; StrikeBits: TYPE = RECORD [ newStyle: BOOLEAN, indexed: BOOLEAN, fixed: BOOLEAN, kerned: BOOLEAN, pad: [0..7777B]]; BoundingBox: TYPE = RECORD [ FontBBox, FontBBoy, FontBBdx, FontBBDy: INTEGER]; StrikeBody: TYPE = RECORD [ length: CARDINAL, ascent: CARDINAL, descent: CARDINAL, xoffset: CARDINAL, raster: CARDINAL, bitmap: ARRAY [0..0) OF WORD]; -- Procedures StringWidth: PUBLIC PROCEDURE [string: STRING, font: TEditFont.Font _ defaultFont] RETURNS [width: [0..LAST[INTEGER]]] = BEGIN i: CARDINAL; width _ 0; FOR i IN [0..string.length) DO width _ width + TEditFont.CharWidth[string[i], font] ENDLOOP; END; Initialize: PROCEDURE [font: TEditFont.Font] = BEGIN strike: Strike = font.address; c: CHARACTER; bits: StrikeBits = strike.header.bits; IF ~bits.newStyle THEN ERROR Error[illegalFormat]; IF bits.indexed THEN ERROR Error[illegalFormat]; font.kerned _ bits.kerned; font.min _ LOOPHOLE[strike.header.min]; font.max _ LOOPHOLE[strike.header.max]; IF font.min ~IN [0C..177C] THEN ERROR Error[illegalFormat]; IF font.max ~IN [0C..177C] THEN ERROR Error[illegalFormat]; font.height _ strike.body.ascent + strike.body.descent; font.raster _ strike.body.raster; font.maxWidth _ strike.header.maxwidth; SetFontAddresses[font]; font.width[40C] _ 0; FOR c IN [font.min..MIN[font.max, 176C]] DO font.width[c] _ XInSegment[c+1, font] - XInSegment[c, font] ENDLOOP; FOR c IN [0C..font.min) DO font.width[c] _ font.width[40C] ENDLOOP; FOR c IN (MIN[font.max, 176C]..177C] DO font.width[c] _ font.width[40C] ENDLOOP; font.width[15C] _ font.width[40C]; -- CR width hack END; SetFontAddresses: PROCEDURE [font: Font] = INLINE BEGIN strike: Strike = font.address; font.bitmap _ @strike.body.bitmap + (IF font.kerned THEN SIZE[BoundingBox] ELSE 0); font.xInSegment _ LOOPHOLE[font.bitmap, LONG POINTER ] + font.raster*font.height - LOOPHOLE[font.min, INTEGER]; END; fontChain: Font _ NIL; EstablishFont: PUBLIC PROCEDURE [family: NameSymbolTable.Name, size: NodeStyle.Dist] RETURNS [Font] = BEGIN myString: REF TEXT; myFontHandle: Font; FOR myFontHandle _ fontChain, myFontHandle.next UNTIL myFontHandle=NIL DO IF family=myFontHandle.family AND size=myFontHandle.size THEN RETURN [myFontHandle]; ENDLOOP; myString _ NEW[TEXT[40]]; NameSymbolTable.FromName[family, myString]; IF size#0.0 THEN LongString.AppendDecimal[LOOPHOLE[myString], Real.RoundC[size]]; LongString.AppendString [LOOPHOLE[myString], ".strike"]; myFontHandle _ LoadFont[LOOPHOLE[myString]]; myFontHandle.family _ family; myFontHandle.size _ size; RETURN [myFontHandle]; END; LoadFont: PROCEDURE [name: LONG STRING] RETURNS [myFontHandle: Font] = BEGIN ENABLE Directory.Error => GOTO Punt; file: File.Capability _ Directory.Lookup[fileName: name]; pages: File.PageCount _ File.GetSize[file]; size: Space.PageCount _ IF pages<20 THEN Inline.LowHalf[pages] ELSE ERROR; space: Space.Handle _ Space.Create[size: size, parent: Space.virtualMemory]; Space.Map[space: space, window: [file: file, base: 1]]; -- first page is 1! myFontHandle _ NEW[FontObject]; myFontHandle.address _ Space.LongPointer[space]; Initialize [myFontHandle]; myFontHandle.next _ fontChain; fontChain _ myFontHandle; EXITS Punt => RETURN[defaultFont] END; SetDefaultFont: PROCEDURE [font: TEditFont.Font] = INLINE {defaultFont _ font}; SetDefaultFont [LoadFont["TiogaDefault.strike"L] ]; IF defaultFont=NIL THEN -- not on the disk DO Runtime.CallDebugger["Tioga needs 'TiogaDefault.strike' to start up!"L] ENDLOOP; END.