(* Copyright (C) 1992, Digital Equipment Corporation                         *)
(* All rights reserved.                                                      *)
(* See the file COPYRIGHT for a full description.                            *)
(*                                                                           *)
(* by Steve Glassman, Mark Manasse and Greg Nelson           *)
(* Last modified on Fri Apr 30 13:47:12 PDT 1993 by mjordan  *)
(*      modified on Fri Apr  2 10:25:51 PST 1993 by steveg   *)
(*      modified on Fri Jan 29 12:21:33 PST 1993 by msm      *)
(*      modified on Mon Feb 24 13:58:03 PST 1992 by muller   *)
(*      modified on Sat Dec 21 16:36:41 PST 1991 by gnelson  *)
<*PRAGMA LL*>

(* A "ScrnFont.T" is a handle on a typeface that is valid for some
   particular screentype, called the <I>owner</I> of the handle.  All 
   handles have names, which are highly conventionalized strings
   encoding the size, style, and other properties of the typeface. *)
   
INTERFACE ScrnFont;

IMPORT ScrnPixmap, Rect, TrestleComm, Font, Fingerprint;

EXCEPTION Failure;

(* <H3> Obtaining handles from the oracle </H3> *)

TYPE
  Oracle = Private OBJECT
    METHODS
      <* LL.sup <= VBT.mu *>
      list(pat: TEXT; maxResults := 1): 
        REF ARRAY OF TEXT RAISES {TrestleComm.Failure};
      match(
        family: TEXT;
        pointSize: INTEGER := 120;
        slant: Slant := Slant.Roman;
        maxResults: CARDINAL := 1;
        weightName: TEXT := AnyMatch;
        version: TEXT := "";
        foundry: TEXT := AnyMatch;
        width: TEXT := AnyMatch;
        pixelsize: INTEGER := AnyValue;
        hres, vres: INTEGER := ScreenTypeResolution;
        spacing: Spacing := Spacing.Any;
        averageWidth: INTEGER := AnyValue;
        charsetRegistry: TEXT := "ISO8859";
        charsetEncoding: TEXT := "1")
      : REF ARRAY OF TEXT RAISES {TrestleComm.Failure};
      lookup(name: TEXT): T 
        RAISES {Failure, TrestleComm.Failure};
      builtIn(f: Font.Predefined): T;
    END;
    Private <: ROOT;

(* For a screentype "st", the field "st.font" is an "Oracle" that
   produces font handles owned by "st".

   The method call

| st.font.list(pat, maxResults)

   returns the names of all fonts owned by "st" that match the pattern
   "pat".  The list of results may be truncated to length "maxResults".
   A "*" matches any number of characters and a "?" matches a single
   character.

   The arguments to the "match" method specify various font attributes,
   as explained below.  The method call 
   
| st.font.match(...)

   returns the names of all font handles owned by "st" that match the
   specifications.  The list of results may be truncated to the length
   "maxResults".  If no fonts match the specifications, the result will
   be either "NIL" or an empty array.  Passing "AnyMatch" for a text
   attribute, or "AnyValue" for an integer attribute, allows any value
   for that attribute.  For text attributes, partial text matches are
   also possible: a "*" matches any number of characters and "?" matches
   a single character.

   The method call 
   
| st.font.lookup(name)

   returns the font handle owned by "st" with the given name.  Generally
   "name" should be one of the names returned by the "list" or
   "match" method.

   The method call 
   
| st.font.builtIn(f)

   returns the screen-dependent font valid for "st" that corresponds
   to the predefined screen-independent font "Font.T{f}".
   
   The locking level for all methods is "LL.sup &lt;= VBT.mu". *)

(* <H3> Font attributes </H3> *)

(* The arguments to a font oracle list method specify font attributes
   whose full specifications are the ``X Logical Font Description
   Conventions Version 1.3'', an MIT X Consortium Standard which can
   be found in Part IV of <I>X Window System</I> by Scheifler and Gettys
   <A REL=BIB.ENTRY HREF="../html/references.html#XSpec"> [XSpec] </A>.  Here they are described in brief.

   The argument "family" specifies the family of the typeface.  To find
   out what fonts your X server has, run the "xlsfonts" program.  Most
   servers support the families "Courier", "Helvetica", and "Times", 
   among others.

   The argument "pointsize" is ten times the font's size in 
   points; e.g., 120 for a standard 12-point font.

   The argument "slant" is an element of the following enumeration 
   type: *)

TYPE
  Slant = {Roman, Italic, Oblique, ReverseItalic, 
    ReverseOblique, Other, Any};

(* whose elements have the following interpretations:

<UL><LI>
"Roman": Upright letters in a roman style.
<LI>
"Italic": Clockwise slanted letters in an italic style.
<LI>
"Oblique": Clockwise slanted letters in a roman style.
<LI>
"ReverseItalic":  Counter clockwise slanted letters in an italic style.
<LI>
"ReverseOblique": Counter clockwise slanted letters in a roman style.
<LI>
"Other": None of the above
<LI>
"Any": Any of the above (including "Other").  
</UL>


The argument "weightName" is the foundry's name for the font's weight;
e.g.,  "Bold", "DemiBold", or "Medium". 
       
The argument "version" specifies the version of the <I>X Logical
Font Description Conventions</I> that describes the format of a font's
name.  If the argument is omitted, Version 1.3 is assumed.  (Version
1.3 is the only version as these words are written.)
   
The argument "foundry" specifies the X registered name for the font's
foundry, e.g., "Adobe", "B&H", "Bitstream", "DEC".

The argument "width" specifies the foundry's name for the font's width; e.g., "Normal" or "Condensed".
       
The argument "pixelsize" specifies the size of the font in pixels.
The size in points depends on the vertical resolution of the device:
A pixelsize of 20 could represent a 20-point font at 75 pixels per
inch or a 10-point font at 150 pixels per inch.

The arguments "hres" and "vres" specify the horizontal and vertical
screen resolution for which the font is designed, in pixels per inch.

The argument "spacing" is an element of the following enumeration:
*)

TYPE Spacing = 
  {Proportional, Monospaced, CharCell, Any};

(* whose elements have the following meaning:

<UL><LI>"Proportional": Character widths vary.
<LI>"Monospaced": Character widths are constant.
<LI>"CharCell": Font is self-clearing, as defined in
the "VBT" interface.
<LI>"Any": Any of the above.
</UL>
The argument "averageWidth" specifies the un-weighted
arithmetic mean of the widths of all glyphs in the font, measured in
tenths of a pixel.

The arguments "charsetRegistry" and "charsetEncoding" are the X names of the 
font's character set and encoding scheme;  e.g., "ISO8859" and "1" for
ISO Latin-1 fonts.  See Appendix G of <A REL=BIB.ENTRY HREF="../html/references.html#XSpec"> [XSpec] </A>. *)

CONST
  AnyMatch = "*";
  AnyValue = -1;
  ScreenTypeResolution = -2;

(* Passing "AnyMatch" as an argument to the "list" method matches any
   text value for the corresponding attribute, and "AnyValue" matches
   any integer value.  Passing "ScreenTypeResolution" for "hres" or
   "vres" matches fonts whose horizontal and vertical resolutions agree
   with the screentype that owns the font.  *)

(* <H3> Registering fonts </H3> *)
  
(* Some screentypes allow the client to register fonts.  The client registers
   the font's strike (bits) and metrics (description) with the "StrikeOracle".
   The name of the font is implied by the attributes in the metrics, so
   the "list" and "lookup" methods will find client-registered fonts.  *)

TYPE
  StrikeOracle = Oracle OBJECT
    METHODS
      <* LL.sup <= VBT.mu *>
      load(strike: Strike; metrics: Metrics): T 
        RAISES {Failure, TrestleComm.Failure};
    END;

(* The method call "st.font.load(strike, metrics)" creates a font
   owned by "st" with the given strike and metrics and returns a handle
   to it.
   
   The "metrics" argument must define all of the initial fields of the
   font metrics record: "family", "pointSize", ..., "isAscii", and
   "defaultChar".  The values "minBounds" and "maxBounds" must be provided
   if "charMetrics" is "NIL"; otherwise if "printWidth" is "AnyValue", the
   "load" method will compute them from "charMetrics".  If any of
   the remaining fields have the value "AnyValue", the "load" method
   will compute them. *)
         
(* <H3> The handle object </H3>  *)

TYPE 
  T <: Public; 
  Public = OBJECT (*CONST*)
    id: INTEGER;
    metrics: Metrics
  END;

TYPE StrikeFont = T OBJECT
  METHODS <* LL.sup <= VBT.mu *>
    strike(): Strike RAISES {TrestleComm.Failure}
  END; 

TYPE Strike = OBJECT
  METHODS <* LL.sup <= VBT.mu *>
    glyph(ch: INTEGER): ScrnPixmap.T;
  END;

(* If "f" is a "ScrnFont.T", then "f.id" is an identifier whose
   interpretation depends on the screentype that owns "f" and
   "f.metrics" are the metrics for "f".  If in addition "f" is a
   "StrikeFont", then "f.strike()" returns "f"'s strike.  The screentype
   of the strike's pixmaps will be the screentype that owns "f".

   If "str" is a "Strike", then "str.glyph(ch)" is the pixmap for
   the character "ch".  This will be empty except for characters in
   the range "[m.firstChar..m.lastChar]", where "m" is the metrics (see
   below) for the font of which "str" is the strike.  *)
   
PROCEDURE BoundingBox(txt: TEXT; fnt: T): Rect.T;
<* LL arbitrary *>
(* Return the smallest rectangle that contains the bounding boxes
   of the characters of "txt" if "txt" were painted in the font "fnt" with
   "txt"'s reference point at the origin. *)

PROCEDURE BoundingBoxSub(
  READONLY txt: ARRAY OF CHAR; 
  fnt: T): Rect.T;
<* LL arbitrary *>
(* Like "BoundingBox" but takes an array instead of a "TEXT". *)

PROCEDURE BoundingBoxSubValid(
  READONLY txt: ARRAY OF CHAR; 
  fnt: T; VAR (*OUT*) valid: BOOLEAN): Rect.T;
<* LL arbitrary *>
(* Like "BoundingBoxSub" but indicates if all characters in "txt"
   are valid.  "valid" may be set to "FALSE" even if all characters
   are valid, if the text wasn't checked. *)

PROCEDURE TextWidth(txt: TEXT; fnt: T): INTEGER;
<* LL arbitrary *>
(* Return the sum of the printing widths of the characters in "txt"
   in the font "fnt". *)

(* <H3> The raw representation </H3> *)

TYPE
  CharMetric = RECORD
    printWidth: INTEGER;
    boundingBox: Rect.T;
  END;
  CharMetrics = REF ARRAY OF CharMetric;
  
(* The "printWidth" of a character is the displacement to the next
   character's reference point.

   The "boundingBox" of a character is the smallest rectangle with sides
   parallel to the axes that contains the glyph of the character placed
   with its reference point at (0,0).  *)

TYPE
  Metrics = OBJECT (*CONST*)
    family: TEXT; 
    pointSize: INTEGER;
    slant: Slant;
    weightName: TEXT; 
    version: TEXT; 
    foundry: TEXT;
    width: TEXT;
    pixelsize: INTEGER;
    hres, vres: INTEGER;
    spacing: Spacing;
    averageWidth: INTEGER;
    charsetRegistry: TEXT;
    charsetEncoding: TEXT;
    firstChar, lastChar: INTEGER;
    charMetrics: CharMetrics;
    selfClearing: BOOLEAN;
    rightKerning, leftKerning: BOOLEAN;
    isAscii: BOOLEAN;
    defaultChar: INTEGER;
    minBounds, maxBounds: CharMetric;
    ascent, descent := 0;
    fprint := Fingerprint.Zero;
  METHODS <* LL arbitrary *>
    intProp(name: TEXT; ch: INTEGER := -1): INTEGER
      RAISES {Failure};
    textProp(name: TEXT; ch: INTEGER := -1): TEXT
      RAISES {Failure};
  END;

(* The fields from "family" to "charSetEncoding" in the "Metrics" object
   specify the attributes that were defined for the "lookup" method.
   A value of "*" or "Any" in one of these fields means that the
   corresponding attribute is unknown.
   
   The integers "firstChar" and "lastChar" are the indices of the 
   first and last characters defined in the font. 
   
   The array "charMetrics" specifies the metrics of the
   individual characters.  The metrics for character "ch" 
   are in "charMetrics[ch-firstChar]".  If all characters have 
   the same "printWidth" and "boundingBox", then these values
   are stored in "minBounds" and "maxBounds" and the "charMetrics" 
   field is "NIL". 
       
   The flag "selfClearing" indicates whether the font is self-clearing,
   as defined in the "VBT" interface, and the two kerning flags indicate
   the present of right and left kerning in the font.
       
   The flag "isAscii" indicates that character codes 32-126 (base 10)
   have their normal ASCII meanings.
       
   The integer "defaultChar" is the code for the recommended character
   to display in the place of a character that isn't defined for the
   font.
    
   The rectangles "minBounds.boundingBox" and "maxBounds.boundingBox"
   contain the meet and join, respectively, of the bounding boxes of
   all characters in the font when they are positioned with their
   reference points at (0, 0). The values "minBounds.printWidth" and
   "maxBounds.printWidth" are the minimum and maximum printing widths
   for all characters in the font.

   The method call "m.intProp(nm)" returns the integer value of the
   font attribute named "nm", or raises "Failure" if this attribute is
   not defined for "m".  The method call "m.intProp(nm, ORD(ch))"
   returns the integer value of the font attribute named "nm" for the
   character "ch", or raises "Failure" if this attribute is not defined
   for "(m, ch)".  The "textProp" method is similar.

   The set of attributes returned by the metrics methods depend on the
   font.  Fonts that are owned by X screentypes support the attributes
   defined in Part IV of <I>X Window System</I> (<I>op. cit.</I>); we
   recommend that other fonts support them too.  (To read an X font
   attribute whose type is an X atom, use the "textProp" method, which
   returns the name of the atom.)

   The fprint field, if non-zero, holds a fingerprint for the metrics,
   which can be used to quickly determine if two Metrics are the same.

   The ascent and descent fields contain the recommended spacing in pixels
   above and below the baseline; the sum is the recommended base-line skip.
*)

END ScrnFont.
