PC Face: Bitmap arrays for rendering CP437 glyphs using IBM PC OEM fonts
GitHub - susam/pcface: Bitmap arrays for rendering CP437 glyphs using IBM PC OEM fonts
PC Face
PC Face is a collection of programmer-friendly resources that allow
drawing CP437 characters on a graphical canvas. This
project provides bitmap arrays for all 256 glyphs from the CP437
character set rendered using various free fonts that reproduce the
original IBM PC OEM fonts.

Additionally, this project includes a few Python functions to generate
these bitmaps and a few JavaScript functions that render these bitmaps
on a graphical canvas.
Perhaps you are making a retro-style game where you want to take full
control of what each pixel should be. Or perhaps you want to render
CP437 glyphs using asterisks to make a text banner. The bitmap arrays
provided in this project might turn out to be useful for such
activities. The available bitmap arrays can be translated to pixels on
screen or symbols for standard output to render CP437 glyphs.
Visit susam.github.io/pcface/ to see a demo.
Contents

Resources
Demos

Quick Demo
Detailed Demo


Bitmap Format
Font Details

Modern DOS Font
Oldschool PC Fonts


Toolkit Usage

CLI
Python API
JavaScript API


License

Original Fonts
Modern DOS Bitmaps
Oldschool PC Font Bitmaps
Source Code


Support
Channels
More

Resources
There are a number of files provided in the out/ directory of
this project. Visit susam.github.io/pcface/out/ to browse these
files. This directory contains several subdirectories for various free
fonts based on the original IBM PC OEM fonts. Each font directory
contains bitmap arrays for the font and a few other files. Links to
modern-dos-8x16 resource files are provided below as examples while
describing these resources. Here is a brief description of each file:

out/modern-dos-8x16/fontlist.js: Bitmap representation of all
256 glyphs from the CP437 character set exposed as a JavaScript
array of bitmap arrays. Each bitmap array represents the bitmap of
a CP437 character.
out/moderndos-8x16/fontmap.js: Bitmap representation of all
CP437 glyphs from the CP437 character set exposed as a JavaScript
object that maps each CP437 character to its bitmap array.
out/moderndos-8x16/glyph.txt: All CP437 glyphs represented
using asterisks.
out/moderndos-8x16/graph.txt: All CP437 glyphs represented
using the at symbol (@) and dots (.). Each row of the glyph is
prefixed with the binary code of the row represented in
hexadecimal. The same binary codes appear as comments in the
JavaScript files mentioned above.
out/moderndos-8x16/preview-8x16.png: A preview of the font
read from the original font file.
out/moderndos-8x16/preview-16x32.png: A larger preview of the
font read from the original font file.

Similar files are available for each such font included in this
project. Visit susam.github.io/pcface/out/ to browse them.
These files are also available via CDN at
https://cdn.jsdelivr.net/npm/pcface/out/.
Demos
Quick Demo
For a quick demo of the various bitmaps available in this project,
visit the demo page at susam.github.io/pcface/. There is a
dropdown menu at the bottom that can be used to select bitmaps for
different fonts.
This demo exercises both a font list from fontlist.js and a font map
from fontmap.js for the selected font. The font list demo is shown
in the first canvas using green foreground colour. The font map demo
is shown in the second canvas using amber colour.
The rendered glyphs look exactly the same in both demos because the
same bitmap arrays are used in both cases. The only difference between
fontlist.js and fontmap.js is how these bitmap arrays are exposed
in a JavaScript const. The former exposes an array of bitmap arrays
whereas the latter exposes an object that maps each CP437 character to
its bitmap array.
Detailed Demo
There is another slightly more detailed demo available at
susam.github.io/pcface/retro.html.
In the demo page, you would notice that each bitmap demo comes in two
variants: one with the suffix font-list and another with the suffix
font-map. The font-list demo loads fontlist.js of the chosen
font and renders the glyphs in green. The font-map demo loads
fontmap.js of the chosen font and renders the glyphs in amber.
While the previous demo shows only 40 characters per line on a fixed
size canvas with a single font size that equals the original font size
scaled up twice, this demo shows 80 characters per line in two
different font sizes: original font size as well as a scaled up font
size that is twice the original font size. Further, in this demo, the
canvas automatically resizes itself to fit the browser window size
whenever the browser is resized.
Bitmap Format
The format of the bitmaps available in this project is quite simple.
Each glyph is represented with a WxH grid of pixels where W is the
width of each glyph and H is the height of each glyph. For example,
each bitmap in moderndos-8x16 represents 16 rows of pixels with 8
columns in each row. These 16 rows are represented as 16 integers in
the bitmap for each glyph. For example, the glyph for the uppercase
letter 'B' rendered using this font is represented as:
  [
    0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66,
    0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00
  ], // [B] (66)
Each integer represents the dots that must be plotted for every row of
the glyph. The integers 0x00 and 0x00 at the beginning means that
the top two rows of the glyph are blank. Then 0xfc (binary
1111100) means that the first 6 pixels of the third row are plotted
with the font's foreground colour and the last two pixels are left
blank. In this manner, 16 rows of pixels must be plotted.
Here is an example Python code that reads these bitmaps and plots the
glyph on standard output using a dot (.) for every 0 bit and the
at symbol (@) for every 1 bit:
bitmap = [
    0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66,
    0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
]
s = ''
for row in bitmap:
    s += f'{row:#04x} ' + f'{row:08b}\n'.translate(str.maketrans('01', '.@'))
print(s)
Here is the output:
0x00 ........
0x00 ........
0xfc @@@@@@..
0x66 .@@..@@.
0x66 .@@..@@.
0x66 .@@..@@.
0x7c .@@@@@..
0x66 .@@..@@.
0x66 .@@..@@.
0x66 .@@..@@.
0x66 .@@..@@.
0xfc @@@@@@..
0x00 ........
0x00 ........
0x00 ........
0x00 ........

If you need more help with writing the code to translate the bitmaps
to pixels, refer to the drawChar(), drawString(), and
drawStrings() functions in src/pcface.js. You can
also load this script in your web page using a CDN URL and use these
functions directly in your page. This is explained in more detail in
section JavaScript API.
It should be possible to refer to these functions and write similar
code in a different programming language for a graphical toolkit of
your choice.
Font Details
Modern DOS Font
This project includes Modern DOS 8x16 font (version
20190101.02) developed by Jayvee Enaguas. This font is available under
the terms of the CC0 1.0 Universal Public Domain Dedication. A
copy of the font is also archived in the
src/font/moderndos/ directory of this project.
This font is based on the IBM VGA 8x16 and Verite
8x16 OEM fonts for IBM PCs. Some glyphs in this font look
exactly like the glyphs of IBM VGA 8x16 while some others look exactly
like the glyphs of Verite 8x16. However, there are also several glyphs
in this font that match neither of the two OEM fonts. Instead they
happen to be adaptations of the glyphs found in one or both of the OEM
fonts.
In my opinion, this font contains the best parts of both OEM fonts. I
like that this font has the slashed zero of Verite. I also like the
more squarish outline of the letters in Verite that has been inherited
into this font. While it inherits a lot of good design from Verite
8x16, it also inherits some nice features from IBM VGA 8x16. For
example, it has the raised stem for the digit 2 and the curved stem
for the digit 7 from IBM VGA 8x16.
Oldschool PC Fonts
This project includes several Oldschool PC fonts (version
2.2) developed by VileR. These fonts are available under the terms of
Creative Commons Attribution-ShareAlike 4.0 International
License. Copies of these fonts are also archived in the
src/font/oldschool/ directory of this project.
These fonts do an excellent job of reproducing the original IBM PC OEM
fonts as faithfully as possible. However, these fonts also differ from
the original OEM fonts in minor ways, especially, to correct minor
errors in the original fonts. See the FAQ at the Oldschool PC
Documentation for more details about these corrections.
Toolkit Usage
While the primary purpose of this project is to distribute bitmap
arrays for CP437 glyphs, this project also makes some of the work that
went into generating and testing these bitmaps as Python and
JavaScript functions. The Python functions are also packaged in the
form of a command-line interface (CLI) tool. The following subsections
provide a brief introduction to the CLI tool as well as the Python and
JavaScript functions.
CLI
The Python command line interface (CLI) tool that this project
provides can be used to generate your own bitmap arrays for CP437
glyphs with a font of your choice. The following steps explain how we
can do this using the Oldschool IBM EGA 9x14 font, a font that is not
included in this project.


First download and extract the font file for Oldschool IBM EGA
9x14:
curl -o oldschool.zip https://int10h.org/oldschool-pc-fonts/download/oldschool_pc_font_pack_v2.2_FULL.zip
unzip -j oldschool.zip "ttf - Px (pixel outline)/Px437_IBM_EGA_9x14.ttf"


Create a virtual Python environment and install PC Face:
python3 -m venv venv
venv/bin/pip3 install pcface


Enter the following command to print the usage details of the tool:



Create bitmap arrays and other output files:
venv/bin/pcface -s 16 Px437_IBM_EGA_9x14.ttf oldschool-ega-9x14/
Note that the output directory name must end with the dimension of
each output glyph expressed in WxH format where W is the width
of each glyph and H is the height of each glyph. The -s option
specifies the font size. It should be set to the font size that
leads to glyphs of the desired dimension. If the -s option is
omitted, a font size of H is used where H is the glyph height
read from the output directory name which may not always produce
the correct glyph dimension.


Now create bitmap arrays for the same font but with the glyph
width and height doubled:
venv/bin/pcface -s 32 Px437_IBM_EGA_9x14.ttf oldschool-ega-18x28/


The output directories would now contain JavaScript files containing
the bitmap arrays as well as a few other files that illustrate the
glyphs. See section Resources for a brief description of
these files.
Python API
The following steps show how to get started with the Python API:


First download and extract the font file for Oldschool IBM EGA
9x14:
curl -o oldschool.zip https://int10h.org/oldschool-pc-fonts/download/oldschool_pc_font_pack_v2.2_FULL.zip
unzip -j oldschool.zip "ttf - Px (pixel outline)/Px437_IBM_EGA_9x14.ttf"


Create a virtual Python environment and install PC Face:
python3 -m venv venv
venv/bin/pip3 install pcface


Now write this Python script and save it in a file, say, ex1.py.
import pcface

bitmap = pcface.make_bitmap('A', 'Px437_IBM_EGA_9x14.ttf', 16, 9, 14)
graph = pcface.make_graph(bitmap, 9, '.@', False)
print(graph)


Enter the following command to execute the script:

The following output should appear:
.........
.........
...@.....
..@@@....
.@@.@@...
@@...@@..
@@...@@..
@@@@@@@..
@@...@@..
@@...@@..
@@...@@..
.........
.........
.........



See src/example/ for more examples of Python scripts
that invoke the Python API of this project.
Also, see Python API Documentation for complete documentation
of all the functions exposed in the Python API.
JavaScript API
Here is a minimal HTML example that shows how PC Face and a font map
can be loaded from a CDN into a web page and used:
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>PC Face Demo</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <style>
      body {background: #111}
      canvas {background: #000; image-rendering: pixelated; margin: auto; display: block}
    </style>
    <script src="https://cdn.jsdelivr.net/npm/pcface/src/pcface.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/pcface/out/moderndos-8x16/fontmap.js"></script>
    <script>
      'use strict'
      window.addEventListener('load', function () {
        const canvas = document.getElementById('canvas')
        const ctx = canvas.getContext('2d')
        ctx.fillStyle = '#3f3'
        pcface.drawString(PC_FACE_MODERNDOS_8X16_FONT_MAP, ctx, 8, "hello, world", 0, 0, 2)
      })
    </script>
  </head>
  <body>
    <canvas id="canvas"></canvas>
  </body>
</html>
Here is another example that loads a font list instead of a font map:
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>PC Face Demo</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <style>
      body {background: #111}
      canvas {background: #000; image-rendering: pixelated; margin: auto; display: block}
    </style>
    <script src="https://cdn.jsdelivr.net/npm/pcface/src/pcface.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/pcface/out/moderndos-8x16/fontlist.js"></script>
    <script>
      'use strict'
      window.addEventListener('load', function () {
        const canvas = document.getElementById('canvas')
        const ctx = canvas.getContext('2d')
        ctx.fillStyle = '#3f3'
        pcface.drawString(PC_FACE_MODERNDOS_8X16_FONT_LIST, ctx, 8,
                          [65, 32, 61, 32, 227, 114, 253], 0, 0, 2)
      })
    </script>
  </head>
  <body>
    <canvas id="canvas"></canvas>
  </body>
</html>
See JavaScript API Documentation for complete documentation
of all the functions exposed in the JavaScript API.
License
Original Fonts
The original fonts archived in this project are available under the
terms of the orignal licenses chosen by the font developers, i.e.,

src/font/moderndos/ is available under the
terms of the CC0 1.0 Universal Public Domain Dedication;
src/font/oldschool/ is available under the
terms of the Creative Commons Attribution-ShareAlike 4.0
International License.

Modern DOS Bitmaps
You may use the content of the following directory under the terms of
either the MIT License or the CC0 1.0 Universal Public Domain
Dedication:

out/out/moderndos-8x16/

Oldschool PC Font Bitmaps
You may use the content of the following directory under the terms of
either the GNU General Public License v3 or the Creative
Commons Attribution-ShareAlike 4.0 International License:

out/oldschool-bios-8x8/
out/oldschool-cga-8x8/
out/oldschool-ega-8x14/
out/oldschool-mda-9x14/
out/oldschool-model30-8x16/
out/oldschool-pgc-8x16/
out/oldschool-verite-8x16/
out/oldschool-vga-8x16/
out/oldschool-vga-9x14/
out/oldschool-vga-9x16/
src/demo.html
src/retro.html

Source Code
All other files in this project, excluding the ones listed in the
three subsections above, are available under the terms of the MIT
License. See LICENSE.md for the complete license text.
Support
To report bugs, suggest improvements, or ask questions,
create issues.
Channels
The author of this project hangs out at the following places online:

Website: susam.net
Twitter: @susam
Mastodon: @susam@mastodon.social
GitHub: @susam
Matrix: #susam:matrix.org
IRC: #susam:libera.chat

You are welcome to subscribe to, follow, or join one or more of the
above channels to receive updates from the author or ask questions
about this project.
More
See Andromeda Invaders where a
small subset of the Modern DOS 8x16 bitmaps available in this project
has been used to render text on a game canvas.
