Skip to content

WGML Font File Blocks

Jiri Malak edited this page Feb 19, 2021 · 4 revisions
Table of Contents

The Attributes

The description of the attribtures in the WGML 4 Reference is modified by the README file produceable from the WGML 3.33 Update with only one note:

The mono_space_width attribute in :FONT has been removed.

All of the other attributes listed in WGML 4 Reference were observed in existing :FONT blocks.

Thus, the Attributes are:

defined_name
member_name
font_out_name1
font_out_name2
line_height
line_space
scale_basis
scale_min
scale_max
char_width

Although the WGML 4 Reference states:

The attributes of the font block must all be specified.

This is not, in fact, correct.

These attributes are required:

  • defined_name
  • member_name
  • char_width

If they are not present, then this error message results:

AT--001: Required attribute not found

At least one of these attributes must appear:

  • line_height
  • scale_basis

If neither appears, then this somewhat-unintelligible error message is presented by gendev 4.1:

SN--078: The line_height attribute must be specified
         if the scale_basis

Both may appear, and either or both may have a zero or a non-zero value, without any objection from gendev 4.1. Apparently, the requirement is that at least one of line_height and scale_basis be present, even if the value matches the default value of "0".

These attributes are optional:

  • font_out_name1
  • font_out_name2
  • line_space
  • scale_min
  • scale_max

The attributes defined_name and member_name are discussed in Common Attributes.

The attributes font_out_name1 and font_out_name2 are character strings, and an empty string is allowed. The remaining attributes are non-negative integers: 0 is allowed, but a negative value produces this error message:

SN--001: Number is too large or contains invalid characters

This error message also results if these upper limits are exceeded:

  • For version 3.33 of gendev, for attributes scale_basis, scale_min, and scale_max, values above $7FFFFFFF.
  • For version 3.33 of gendev, for attributes line_height, line_space, and char_width, values above $CCCF.
  • For version 4.1 of gendev, for all numerical attributes, values above $7FFFFFFF.

If the value of the attribute char_width, in version 3.33, is greater than $FF, then only the lower-order byte will be used in any WidthBlock. There is, then, no point in version 3.33 in specifying a value larger than $FF for this attribute.

Regardless of their order in the source file, the attributes are encoded in the binary file this way:

Attributes {
    uint8_t  font_out_name1_length;
    uint8_t  font_out_name1[font_out_name1_length];
    uint8_t  font_out_name2_length;
    uint8_t  font_out_name2[font_out_name2_length];
    FontData fontdata
};

If the corresponding attribute is not present, or if it is given an empty string as its value, then the empty string in the binary file will be parsed as a NULL pointer.

For version 3.33 files, the FontData structure is:

FontData {
    uint16_t designator = 0x1700;
    uint16_t line_height
    uint16_t line_space
    uint32_t scale_basis
    uint32_t scale_min
    uint32_t scale_max
    uint16_t char_width
};

The default values for the optional attributes are:

  • font_out_name1: 0x00 (ie, a length byte of 0)
  • font_out_name2: 0x00 (ie, a length byte of 0)
  • line_height: 0x0000
  • line_space: 0x0000
  • scale_basis: 0x00000000
  • scale_min: 0x00000000
  • scale_max: 0x00000000

For version 4.1 files, the FontData structure is:

FontData {
    uint16_t designator = 0x1D00;
    uint32_t line_height
    uint32_t line_space
    uint32_t scale_basis
    uint32_t scale_min
    uint32_t scale_max
    uint32_t char_width
};

The default values for the optional attributes are:

  • font_out_name1: 0x00 (ie, a length byte of 0)
  • font_out_name2: 0x00 (ie, a length byte of 0)
  • line_height: 0x00000000
  • line_space: 0x00000000
  • scale_basis: 0x00000000
  • scale_min: 0x00000000
  • scale_max: 0x00000000

The designators can be used to determine which structure is present in the binary file.

The CharacterDescriptionBlock Structure

An IntransBlock will be present whenever a non-empty :INTRANS block is found in the source file.

An OuttransBlock will be present whenever a non-empty :OUTTRANS block is found in the source file.

There are two sizes for the OuttransBlock, which will be used below when appropriate:

  • a 1-byte OuttransBlock is an array of 0x100 uint8_t values;
  • a 2-byte OuttransBlock is an array of 0x100 uint16_t values.

A WidthBlock will be present under these conditions:

  • A non-empty :WIDTH block is present and at least one width value differs from the value of attribute char_width.
  • For version 3.33, the value of char_width is greater than $8000.

This does mean that, for version 3.33, the binary file can have a WidthBlock even if there are no non-empty :WIDTH blocks in the source file.

There are also three sizes for these blocks, which will be used below when appropriate:

  • a 1-byte block is an array of 0x100 uint8_t values;
  • a 2-byte block is an array of 0x100 uint16_t values; and
  • a 4-byte block is an array of 0x100 uint32_t values.

Note that the IntransBlock only comes in one variety: the 1-byte IntransBlock. To avoid implying otherwise, no size will be indicated below for the IntransBlock.

The CharacterDescriptionBlock has eight different forms for eight different situations:

  1. There is neither an IntransBlock, nor an OuttransBlock nor a WidthBlock present.
  2. An IntransBlock is present, but an OuttransBlock is not and a WidthBlock is not.
  3. An OuttransBlock is present, but an IntransBlock is not and a WidthBlock is not.
  4. A WidthBlock is present, but an IntransBlock is not and an OuttransBlock is not.
  5. An IntransBlock and an OuttransBlock are present, but a WidthBlock is not present.
  6. An OuttransBlock and a WidthBlock are present, but an IntransBlock is not present.
  7. An IntransBlock and a WidthBlock are present, but an OuttransBlock is not present.
  8. An IntransBlock, an OuttransBlock, and a WidthBlock are present.

When there is neither an IntransBlock, nor an OuttransBlock nor a WidthBlock present, the struct in the binary file will be:

CharacterDescriptionBlock {
    uint8_t       size_flag     = 0x00;
    uint8_t       width_flag    = 0x01;
    uint8_t       data_count    = 0x00;
    uint8_t       outtrans_flag = 0x00;
    uint8_t       intrans_flag  = 0x00;
};

These fields appear in all CharacterDescriptionBlock forms.

When no WidthBlock is present, the value of the field size_flag is always "0x00".

When a WidthBlock is present, the value of the field size_flag varies:

  • the value "0x01" indicates that a 1-byte WidthBlock is present;
  • in version 3.33, the value "0x00" indicates that a 2-byte WidthBlock is present; and
  • in version 4.1, the value "0x00" indicates that a 4-byte WidthBlock is present.

The value of the field width_flag varies:

  • the value "0x00" indicates that a WidthBlock is present; and
  • the value "0x01" indicates that a WidthBlock is not present.

The value of the field data_count is the number of bytes required to encode the output-translation sequences in the :OUTTRANS block; if there is no OuttransBlock present or if a 1-byte OuttransBlock is present, then the value will be "0x00".

The value of the field outtrans_flag varies:

  • the value "0x00" indicates that an OuttransBlock is not present;
  • the value "0x01" indicates that a 1-byte OuttransBlock is present; and
  • the value "0x02" indicates that a 2-byte OuttransBlock is present.

The value of the field intrans_flag varies:

  • the value "0x00" indicates that an IntransBlock is not present; and
  • the value "0x01" indicates that an IntransBlock is present.

When an IntransBlock is present, but an OuttransBlock is not and a WidthBlock is not, the struct in the binary file will be:

CharacterDescriptionBlock {
    uint8_t       size_flag     = 0x00;
    uint8_t       width_flag    = 0x01;
    uint8_t       data_count    = 0x00;
    uint8_t       outtrans_flag = 0x00;
    uint8_t       intrans_flag  = 0x01;
    IntransBlock  intrans;
};

where IntransBlock is described in The :INTRANS Block.

When an OuttransBlock is present, but an IntransBlock is not and a WidthBlock is not, the struct in the binary file will be:

CharacterDescriptionBlock {
    uint8_t       size_flag     = 0x00;
    uint8_t       width_flag    = 0x01;
    uint8_t       data_count;
    uint8_t       outtrans_flag;
    uint8_t       intrans_flag  = 0x00;
    OuttransBlock outtrans;
};

where OuttransBlock is described in The :OUTTRANS Block.

When a WidthBlock is present, but an IntransBlock is not and an OuttransBlock is not, the struct in the binary file will be:

CharacterDescriptionBlock {
    uint8_t       size_flag;
    uint8_t       width_flag    = 0x00;
    uint8_t       data_count    = 0x00;
    uint8_t       outtrans_flag = 0x00;
    uint8_t       intrans_flag  = 0x00;
    WidthBlock    width;
};

The WidthBlock is described in The :WIDTH Block.

When an IntransBlock and an OuttransBlock are present, but a WidthBlock is not present, the struct in the binary file will be:

CharacterDescriptionBlock {
    uint8_t       size_flag     = 0x00;
    uint8_t       width_flag    = 0x01;
    uint8_t       data_count;
    uint8_t       outtrans_flag;
    uint8_t       intrans_flag  = 0x01;
    IntransBlock  intrans;
    OuttransBlock outtrans;
};

When an OuttransBlock and a WidthBlock are present, but an IntransBlock is not present, the struct in the binary file will be:

CharacterDescriptionBlock {
    uint8_t       size_flag;
    uint8_t       width_flag    = 0x00;
    uint8_t       data_count;
    uint8_t       outtrans_flag;
    uint8_t       intrans_flag  = 0x00;
    OuttransBlock outtrans;
    WidthBlock    width;
};

When an IntransBlock and a WidthBlock are present, but an OuttransBlock is not present, the corresponding struct in the binary file will be:

CharacterDescriptionBlock {
    uint8_t       size_flag;
    uint8_t       width_flag    = 0x00;
    uint8_t       data_count    = 0x00;
    uint8_t       outtrans_flag = 0x00;
    uint8_t       intrans_flag  = 0x01;
    IntransBlock  intrans;
    WidthBlock    width;
};

When an IntransBlock, an OuttransBlock, and a WidthBlock are present, the corresponding struct in the binary file will be:

CharacterDescriptionBlock {
    uint8_t       size_flag;
    uint8_t       width_flag    = 0x00;
    uint8_t       data_count;
    uint8_t       outtrans_flag;
    uint8_t       intrans_flag  = 0x01;
    IntransBlock  intrans;
    OuttransBlock outtrans;
    WidthBlock    width;
};

An IntransBlock contains 0x102 bytes. An OuttransBlock contains either 0x102 bytes (if the value of the field outtrans_flag is 0x01) or 0x202 bytes plus the value of field data_count bytes(if the value of the field outtrans_flag is 0x02). A WidthBlock contains either 0x102 bytes (if the value of the field size_flag is "0x01"), 0x202 (if the value of the field size_flag is "0x00" and the version is 3.33), or 0x402 (if the value of the field size_flag is "0x00" and the version is 4.1). Thus, every form of CharacterDescriptionBlock allows computation of the number of bytes in that CharacterDescriptionBlock.

The :INTRANS Block

This block is described in The :INTRANS Block.

The :OUTTRANS Block

This block is described in The :OUTTRANS Block.

The :WIDTH Block

The description of the :WIDTH block given in WGML 4 Reference is still correct:

:WIDTH.
   font-character character-width
:eWIDTH.

This block does not have attributes. The font-character is a character value, and the character_width must be a non-negative integer; if a character is not listed, the value of the attribute char_width is used.

An empty :WIDTH block (one with no entries) is the same as no :WIDTH block at all: gendev ignores it.

The version 3.33 gendev enforces a limit of "$ff" on the values of the font_character with this message:

SN--001: Number is too large or contains invalid characters

The version 4.1 gendev GP-faults for values of the font_character greater than "$ff".

For both versions, prefixing the character_width value with $ (that is, using a hexadecimal value) produces this error message:

SN--009: Width value must be an integer number

The minimum value allowed for the character_width is "0", which does appear in the binary file if used in the source. The maximum value depends on the version:

  • Version 3.33: 32769 (0x8001); however, values that large are reduced to the least-significant byte (0x01). 32767 (0x7FFF) is the largest value that preserves the value entered.
  • Version 4.1: 2147483647 (0x7FFF) is the maximum accepted. The full value entered is preserved.

Multiple :WIDTH blocks, whether identical or different, are allowed in the source file. They are merged into a single entry in the binary file. If the same character is given a width in more than one block, the width given in the last block will be used:

:WIDTH.
   b 5
:eWIDTH.

:WIDTH.
  b 5
:eWIDTH.

assigns the width "5" to 'b'

:WIDTH.
   b 5
:eWIDTH.

:WIDTH.
  d 5
:eWIDTH.

assigns the width "5" to both 'b' and 'd' but

:WIDTH.
   b 5
:eWIDTH.

:WIDTH.
  b 10
:eWIDTH.

assigns the width "10" to 'b' in the binary file.

The struct used in the binary file does not depend on the version nearly so much as it depends on the values of the attribute char_width and the largest character_width value.

This struct is used in the binary file for either version:

WidthBlock {
    uint8_t  designator = 0x81;
    uint8_t  count = 0x00;
    uint8_t  table[0x100];
};

The field designator has the same value as the corresponding field in the IntransBlock.

The field count has the same value as the corresponding field in the IntransBlock.

The field table is an array consisting of 100 bytes, and so this struct will be referred to as the 1-byte WidthBlock.

The 1-byte WidthBlock is used under these conditions:

  • For version 3.33, it is used when the largest character_width value will fit into one byte or is larger than 32767 (0x7FFF), in which case only the lower-order byte is used; the size of the attribute char_width does not matter.
  • For version 4.1, it is used when each of the value of char_width and the largest character_width value will fit into one byte.

This struct is used in the binary file for version 3.33 only:

WidthBlock {
    uint8_t  designator = 0x82;
    uint8_t  count = 0x00;
    uint16_t table[0x100];
};

The field designator has the same value as the corresponding field in the OuttransBlock.

The value of the field count is always "0x00", presumably because the WidthBlock has no field data as the corresponding struct does in the OuttransBlock.

The table is an array consisting of 100 pairs of bytes, and so this struct will be referred to as the 2-byte WidthBlock.

The 2-byte WidthBlock is used under these conditions:

  • The binary file is version 3.33.
  • At least one value of character_width will not fit into a single byte and the value is no greater than 32767 (0x7FFF).
  • The size of the attribute char_width does not matter.

The attribute char_width, in version 3.33, is a two-byte value, but only the lower-order byte is used as the default value in the table. This applies even when the 2-byte WidthBlock is used: the upper byte of the value of the attribute char_width is replaced with a null (0x00). Thus, in version 3.33, attribute char_width is effectively limited to a maximum value of "$FF".

If no non-empty :WIDTH blocks are found in the source file but the value of attribute char_width is greater than $7fff, then a 1-byte WidthBlock in which each byte contains (the lower-order byte of) the value of char_width will be present in the binary file.

This struct is used in the binary file for version 4.1 only:

WidthBlock {
    uint8_t  designator = 0x84;
    uint8_t  count = 0x01;
    uint32_t table[0x100];
};

The field designator always has the value "0x84".

The value of the field count is always "0x01"; it is so-named by analogy with the other WidthBlock structs.

The table is an array consisting of 100 four-byte values, and so this struct will be referred to as the 4-byte WidthBlock.

The 4-byte WidthBlock is used under these conditions:

  • The binary file is version 4.1.
  • Either the value of the attribute char_width or at least one value of character_width will not fit into a single byte and the value is no greater than 2147483647 (0x7FFFFFFF).

The table is only present when at least one non-empty :WIDTH block is found in the source file. When it is present, entries not listed in any :WIDTH block use the full four-byte value of attribute char_width (which has a maximum value of $7FFFFFFF).

Clone this wiki locally