1. Bundled Files

Collected files are stored in Dropbox/SwissMicros_Design/Fonts/Calc_Src directory

Here is overview of the contents:

Calc_Src/dmcp_font_info.html      <-- This doc
Calc_Src/dmcp_font_info.txt       <-- Source for this doc (just for curiosity)
Calc_Src/fonts/hp42s/free42-font-table.png <-- free42a font table
Calc_Src/fonts/hp42s/free42a.bdf  <-- BDF source for free42 font
Calc_Src/fonts/li/BitstreamVeraSansMono-Roman.ttf   <-- Intermediate TTF
Calc_Src/fonts/li/BitstreamVeraSansMono-Oblique.ttf <-- Intermediate TTF
Calc_Src/fonts/li/BitstreamVeraSansMono-Bold.ttf    <-- Intermediate TTF
Calc_Src/fonts/li/BitstreamVeraSansMono-Roman.sfd   <-- Source for base font
Calc_Src/fonts/li/BitstreamVeraSansMono-Oblique.sfd <-- Source for base italic font
Calc_Src/fonts/li/BitstreamVeraSansMono-Bold.sfd    <-- Source for base bold font
Calc_Src/fonts/li/*.bdf           <-- Generated BDF files for base fonts
Calc_Src/dm/font/gen_free42       <-- Script for C file generation for free42 font
Calc_Src/dm/font/bdf2c.py         <-- BDF to C conversion utility
Calc_Src/dm/font/gen_fonts_vera   <-- Script for base font rasterization and conversion
Calc_Src/dm/font/*.c              <-- Generated C files for all DMCP fonts

C files are included in the bundle as they contain useful information in comments, like character codes (final font positions), various dimensions and mainly glyph representation.

2. DMCP Font sets

The system supports 6 font sizes, but bold and italic are used (at least for now) only in four sizes in the help browser, therefore first and last position in font table for bold and italic are mapped to normal font to save some space.

This gives three font sets: normal, bold and italic. I will reference those as a base font, base bold font and base italic font.

There is also fourth set representing scaled 5x7 free42 font. The base of the scaled fonts is just 5x7 font variant and scaling is performed on demand during drawing.

Following shows the font definitions. Four font sets can be seen at the end with FONT_SEQUENCE defines.

Don’t mind the actual names, those are just historical relics.

Font definitions
// Font shortcuts
#define f10x20     (&lib_mono_10x16)
#define f11x22     (&lib_mono_11x18)
#define f12x24     (&lib_mono_12x20)
#define f14x28     (&lib_mono_14x24)
#define f16x32     (&lib_mono_16x27)
#define f18x40     (&lib_mono_18x30)

// Bold
#define f10x20b    (&lib_mo_b_10x16)
#define f11x22b    (&lib_mo_b_11x18)
#define f12x24b    (&lib_mo_b_12x20)
#define f14x28b    (&lib_mo_b_14x24)
#define f16x32b    (&lib_mo_b_16x27)
#define f18x40b    (&lib_mo_b_18x30)

// Italic
#define f10x20i    (&lib_mo_i_10x16)
#define f11x22i    (&lib_mo_i_11x18)
#define f12x24i    (&lib_mo_i_12x20)
#define f14x28i    (&lib_mo_i_14x24)
#define f16x32i    (&lib_mo_i_16x27)
#define f18x40i    (&lib_mo_i_18x30)

// Free42
#define f5x7     (&free42a)
#define f42_2x2  (&free42_2x2)
#define f42_2x3  (&free42_2x3)
#define f42_3x3  (&free42_3x3)
#define f42_3x4  (&free42_3x4)
#define f42_6x8  (&free42_6x8)


// Define bold/italic for fonts 1-4, map to normal font for 0,5
#define FONT_SEQUENCE     {f10x20,  f11x22,  f12x24,  f14x28,  f16x32,  f18x40}
#define FONT_SEQUENCE_B   {f10x20,  f11x22b, f12x24b, f14x28b, f16x32b, f18x40}
#define FONT_SEQUENCE_I   {f10x20,  f11x22i, f12x24i, f14x28i, f16x32i, f18x40}

#define FONT_SEQUENCE_T   {f42_2x2, f42_2x3, f42_2x3, f42_3x3, f42_3x3, f42_3x4}

3. Font Files

3.1. Base Font

The sources of the first three font sets are:

fonts/li/BitstreamVeraSansMono-Bold.sfd
fonts/li/BitstreamVeraSansMono-Oblique.sfd
fonts/li/BitstreamVeraSansMono-Roman.sfd

Those are FontForge files as I’ve edited the original fonts in FontForge.

The .sdf files are loaded into FontForge and TTF files are exported:

fonts/li/BitstreamVeraSansMono-Bold.ttf
fonts/li/BitstreamVeraSansMono-Oblique.ttf
fonts/li/BitstreamVeraSansMono-Roman.ttf

From those files are generated bdf files using otf2bdf converter.

And further converted from bdf to .c sources using our bdf2c.py utility.

All that is automatically done in gen_fonts_vera script.

3.2. Free42 font

I’ve generated the .bdf font from font table.

The source file is

fonts/hp42s/free42a.bdf

4. Font Parameters

Notes:

  • Filenames correspond to names in Font definitions

  • W,H are font dimensions

  • B is the baseline

List of used DMCP font files
C-source         BDF-file            DIM   W   H   B
lib_mono_10x16.c lib_mono_10x16.bdf 11x21  11, 21, 4 | from "BitstreamVeraSansMono-Roman.ttf"
lib_mono_11x18.c lib_mono_11x18.bdf 12x23  12, 23, 5 | from "BitstreamVeraSansMono-Roman.ttf"
lib_mono_12x20.c lib_mono_12x20.bdf 13x25  13, 25, 5 | from "BitstreamVeraSansMono-Roman.ttf"
lib_mono_14x24.c lib_mono_14x24.bdf 15x28  15, 28, 6 | from "BitstreamVeraSansMono-Roman.ttf"
lib_mono_16x27.c lib_mono_16x27.bdf 16x32  16, 32, 6 | from "BitstreamVeraSansMono-Roman.ttf"
lib_mono_18x30.c lib_mono_18x30.bdf 18x35  18, 35, 7 | from "BitstreamVeraSansMono-Roman.ttf"
lib_mo_b_10x16.c lib_mo_b_10x16.bdf 11x21  11, 21, 4 | from "BitstreamVeraSansMono-Bold.ttf"
lib_mo_b_11x18.c lib_mo_b_11x18.bdf 12x23  12, 23, 5 | from "BitstreamVeraSansMono-Bold.ttf"
lib_mo_b_12x20.c lib_mo_b_12x20.bdf 14x25  14, 25, 5 | from "BitstreamVeraSansMono-Bold.ttf"
lib_mo_b_14x24.c lib_mo_b_14x24.bdf 15x28  15, 28, 6 | from "BitstreamVeraSansMono-Bold.ttf"
lib_mo_b_16x27.c lib_mo_b_16x27.bdf 16x32  16, 32, 6 | from "BitstreamVeraSansMono-Bold.ttf"
lib_mo_b_18x30.c lib_mo_b_18x30.bdf 18x35  18, 35, 7 | from "BitstreamVeraSansMono-Bold.ttf"
lib_mo_i_10x16.c lib_mo_i_10x16.bdf 13x21  13, 21, 4 | from "BitstreamVeraSansMono-Oblique.ttf"
lib_mo_i_11x18.c lib_mo_i_11x18.bdf 13x23  13, 23, 5 | from "BitstreamVeraSansMono-Oblique.ttf"
lib_mo_i_12x20.c lib_mo_i_12x20.bdf 15x25  15, 25, 5 | from "BitstreamVeraSansMono-Oblique.ttf"
lib_mo_i_14x24.c lib_mo_i_14x24.bdf 18x28  18, 28, 6 | from "BitstreamVeraSansMono-Oblique.ttf"
lib_mo_i_16x27.c lib_mo_i_16x27.bdf 20x32  20, 32, 6 | from "BitstreamVeraSansMono-Oblique.ttf"
lib_mo_i_18x30.c lib_mo_i_18x30.bdf 23x35  23, 35, 7 | from "BitstreamVeraSansMono-Oblique.ttf"
    free42_5x7.c        free42a.bdf  5x8    5,  8, 1 | BDF generated by me

5. System Fonts

There are two system fonts (see Font definitions for naming).

f10x20

Is used as system small font. Used wherever smaller text is written (e.g. in About screens)

f12x24

Is used as normal system font. It is used in menus, header line and system dialogs.

6. Calculator Fonts

Calculator fonts usage (which the calc uses to display numbers and program) can vary based on current view configuration.

6.1. DM42

Both register and program font can use either segmented free42 font or use various sizes of the base font.

6.2. DM41X

Register font

Special segmented hp41font requires separate build process from the base segment image to font. There is no intermediate bdf font in this process as the C code is directly generated from the image of segments and character-segment table.

Request the build files if needed.

Program font

Uses hp41font in single line mode and various sizes of the basic font in multiline modes.

There are internal tables for mapping from base font to 41X encoding (e.g. for multiline program mode).

Note that handling of font encoding on 41X was particularly big mess as the calculator ROM itself uses three different character codes in various places.

7. Required Characters

The bdf2c.py utility expects the fonts in Unicode. Then collects required characters and transforms to appropriate font table for the font data structures. Missing characters are reported during conversion.

Note that bdf2c.py isn’t universal BDF file handler. It is possible that some modification to it will be needed when used to handle BDFs generated by different programs.
DMCP font table
  0: U+0020 ' ' |  33: U+0041 'A' |  66: U+0062 'b' |  99: U+222B '∫'
  1: U+0021 '!' |  34: U+0042 'B' |  67: U+0063 'c' | 100: U+2592 '▒'
  2: U+0022 '"' |  35: U+0043 'C' |  68: U+0064 'd' | 101: U+03A3 'Σ'
  3: U+0023 '#' |  36: U+0044 'D' |  69: U+0065 'e' | 102: U+25B6 '▶'
  4: U+0024 '$' |  37: U+0045 'E' |  70: U+0066 'f' | 103: U+03C0 'π'
  5: U+0025 '%' |  38: U+0046 'F' |  71: U+0067 'g' | 104: U+00BF '¿'
  6: U+0026 '&' |  39: U+0047 'G' |  72: U+0068 'h' | 105: U+2264 '≤'
  7: U+0027 ''' |  40: U+0048 'H' |  73: U+0069 'i' | 106: U+240A '␊'
  8: U+0028 '(' |  41: U+0049 'I' |  74: U+006A 'j' | 107: U+2265 '≥'
  9: U+0029 ')' |  42: U+004A 'J' |  75: U+006B 'k' | 108: U+2260 '≠'
 10: U+002A '*' |  43: U+004B 'K' |  76: U+006C 'l' | 109: U+21B5 '↵'
 11: U+002B '+' |  44: U+004C 'L' |  77: U+006D 'm' | 110: U+2193 '↓'
 12: U+002C ',' |  45: U+004D 'M' |  78: U+006E 'n' | 111: U+2192 '→'
 13: U+002D '-' |  46: U+004E 'N' |  79: U+006F 'o' | 112: U+2190 '←'
 14: U+002E '.' |  47: U+004F 'O' |  80: U+0070 'p' | 113: U+03BC 'μ'
 15: U+002F '/' |  48: U+0050 'P' |  81: U+0071 'q' | 114: U+00A3 '£'
 16: U+0030 '0' |  49: U+0051 'Q' |  82: U+0072 'r' | 115: U+00B0 '°'
 17: U+0031 '1' |  50: U+0052 'R' |  83: U+0073 's' | 116: U+00C5 'Å'
 18: U+0032 '2' |  51: U+0053 'S' |  84: U+0074 't' | 117: U+00D1 'Ñ'
 19: U+0033 '3' |  52: U+0054 'T' |  85: U+0075 'u' | 118: U+00C4 'Ä'
 20: U+0034 '4' |  53: U+0055 'U' |  86: U+0076 'v' | 119: U+2221 '∡'
 21: U+0035 '5' |  54: U+0056 'V' |  87: U+0077 'w' | 120: U+1D07 'ᴇ'
 22: U+0036 '6' |  55: U+0057 'W' |  88: U+0078 'x' | 121: U+00C6 'Æ'
 23: U+0037 '7' |  56: U+0058 'X' |  89: U+0079 'y' | 122: U+2026 '…'
 24: U+0038 '8' |  57: U+0059 'Y' |  90: U+007A 'z' | 123: U+241B '␛'
 25: U+0039 '9' |  58: U+005A 'Z' |  91: U+007B '{' | 124: U+00D6 'Ö'
 26: U+003A ':' |  59: U+005B '[' |  92: U+007C '|' | 125: U+00DC 'Ü'
 27: U+003B ';' |  60: U+005C '\' |  93: U+007D '}' | 126: U+2592 '▒'
 28: U+003C '<' |  61: U+005D ']' |  94: U+007E '~' | 127: U+25A0 '■'
 29: U+003D '=' |  62: U+2191 '↑' |  95: U+251C '├' | 128: U+25BC '▼'
 30: U+003E '>' |  63: U+005F '_' |  96: U+00F7 '÷' | 129: U+25B2 '▲'
 31: U+003F '?' |  64: U+0060 '`' |  97: U+00D7 '×' |
 32: U+0040 '@' |  65: U+0061 'a' |  98: U+221A '√' |

This particular set of characters can look strange, but is based on the character set used by HP42.

The free42a.bdf uses calculator encoding which can be seen in free42-font-table.png.

The 41 segment fonts use directly segment tables for characters to generate final glyphs. Request the build files if needed.

8. Font Display State

Display State is a data structure used by DMCP system for any text to LCD drawing.

It is important to keep in mind that the final font appearance is influenced by several parameters in "Display State".

ya

Lines to fill above the font, i.e. this adds space above the font

yb

Lines to fill below the font, i.e. this adds space below the font

xoffs

X offset for the first char on a line

xspc

Additional space between chars (could be positive or negative)

post_offs

If configured it allows per character changes to above value

As the current fonts are automatically generated from the OpenType fonts. These parameters are used to fine tune the final appearance. It is up to decision whether any of these will be used or needed with new fonts, but important is to keep in mind that defaults for those values should be updated in the system (they are hardcoded in DMCP data structures).
Also parts of the code where these parameters are fine tuned for particular situation have to be identified, fixed and checked in tests.

Font display state
typedef struct {
  line_font_t const * f; // Current font
  int16_t x, y;        // Current x,y position
  int16_t ln_offs;     // Line offset (when displaying by line numbers)
  int16_t y_top_grd;   // Don't overwrite anything above this line
  int8_t  ya;          // Lines to fill above the font
  int8_t  yb;          // Lines to fill below the font
  int8_t  xspc;        // Space between chars
  int8_t  xoffs;       // X offset for first char on line
  uint8_t fixed;       // Draw in fixed width
  uint8_t inv;         // Draw inverted
  uint8_t bgfill;      // Fill background while drawing
  uint8_t lnfill;      // Fill whole lines before writing line
  uint8_t newln;       // New line after writing line
  const uint8_t *post_offs; // X-advance character width minus this value (if not-null)
} disp_stat_t;