-- Copyright (C) 1981  by Xerox Corporation. All rights reserved. 
-- File: WindowFonts.mesa  edit by
-- Karlton,  2-Jul-81 13:08:51 

DIRECTORY
  WindowFont USING [ErrorCode, Handle];

WindowFonts: PROGRAM EXPORTS WindowFont =
  BEGIN

  Handle: TYPE = WindowFont.Handle;

  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];

  defaultFont: PUBLIC Handle ← NIL;
  Error: PUBLIC ERROR [code: WindowFont.ErrorCode] = CODE;

  SetDefault: PUBLIC PROCEDURE [font: Handle] = {defaultFont ← font};

  CharIsDefined: PUBLIC PROCEDURE [char: CHARACTER, font: Handle ← defaultFont]
    RETURNS [BOOLEAN] = {
    IF font = NIL THEN font ← defaultFont; RETURN[font.width[char] # 0]};

  CharWidth: PUBLIC PROCEDURE [char: CHARACTER, font: Handle ← defaultFont]
    RETURNS [width: NATURAL] = {
    IF font = NIL THEN font ← defaultFont;
    width ← font.width[char];
    IF width = 0 THEN width ← font.width[font.max + 1]};

  FontHeight: PUBLIC PROCEDURE [font: Handle ← defaultFont] RETURNS [NATURAL] = {
    RETURN[IF font = NIL THEN defaultFont.height ELSE font.height]};

  SetFontAddresses: PROCEDURE [font: WindowFont.Handle] = {
    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]};

  Initialize: PUBLIC PROCEDURE [font: Handle] = {
    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;
    IF strike.header.min ~IN [0..377B] THEN ERROR Error[illegalFormat];
    font.min ← LOOPHOLE[strike.header.min];
    IF strike.header.max ~IN [strike.header.min..377B) THEN
      ERROR Error[illegalFormat];
    font.max ← LOOPHOLE[strike.header.max];
    font.height ← strike.body.ascent + strike.body.descent;
    font.raster ← strike.body.raster;
    font.maxWidth ← strike.header.maxwidth;
    SetFontAddresses[font];
    FOR c IN [0C..font.min) DO font.width[c] ← 0 ENDLOOP;
    FOR c IN [font.min..font.max + 1] DO
      font.width[c] ← font.xInSegment[c + 1] - font.xInSegment[c] ENDLOOP;
    FOR c IN (font.max + 1..377C] DO font.width[c] ← 0 ENDLOOP};


  END.