fontlibc.h

#include <fontlibc.h>

The fontlibc library provides routines for displaying custom fonts and glyphs, and can be used to extend the limited font capabilities of graphx.

The fontlibc library was designed under a “mechanism not policy” sort of philosophy. Rather than attempting to provide as many fancy features as a programmer could want, fontlibc tries to provide fast, basic routines that can be used to build the additional functionality you want. For example, word-wrap is not directly provided, but can be implemented using fontlib_SetAlternateStopCode and fontlib_GetStringWidth. fontlibc hopes to provide enough performance to be usable in games, while providing powerful enough basic features for fancy GUIs and document editors.

Creating Fonts

Fonts for use with fontlibc can be made with any program that can produce Windows 3.x .FNT resource files. Alternatively, the convfont utility also supports creating fonts using a simple ASCII art format.

GUI Editor Software

Fony is probably the most-used FNT editor available. It can open both .FNT and .FON files.

mkwinfont provides some Python code for converting a text-based format to and .FON files; it should be trivial for someone with basic Python skills to change to code to skip the .FON packaging stage and directly produce a .FNT resource file. Useful if for some reason you think graphics are best done without the aid of any kind of graphics editor.

VSoft’s FontEdit is mostly just the original FontEdit included with the Windows SDK for Windows 3.x, but compiled for 32-bit Windows. A notable addition, however, is the ability to import TrueType fonts, though I haven’t tested it. It cannot, however, open .FON files; the FNT resource(s) embedded in a .FON file must be extracted before FontEdit can open the font(s).

MFE is DrDnar’s own bitmap font editor. It can export .FNT files. It has the useful feature of allowing fully custom mapping from Unicode to your font’s 8-bit code page, which makes creating mock-ups with the preview function easier.

Manually Creating a Font

You can also create a font manually with your favorite text editor. Characters in most monospaced fonts are about twice as tall as they are wide, so a double width mode is supported. If set to true, two characters from the input file are read for each pixel, halving the width.

The first line of text in the file must be convfont. After that, specify metadata about the font by separating a tag from its value with a colon. A height tag is required at a minimum here. For monospaced fonts, use the fixed width tag to set the width. The metadata block is terminated with a Font data tag.

convfont
Double width: true
Height: 8
Fixed width: 6
x-height: 2
Baseline: 7
: You can make a comment by starting a line with a colon.
Font data:

After the metadata comes the information for each glyph. For variable width fonts, you should specify a width for each glyph. Making the image is simple: anything that isn’t a space is a set pixel.

Code point: 'A'
: Instead of using a character literal, you could put a number like 65 or 0x41; or use an escape sequence like '\101'.
: There is no need to specify a width because this is a fixed-width font.
Data:
  ******
**      **
**      **
**********
**      **
**      **
**      **

: Since B comes after A, there is no need to specify that this is B.
Data:
########
##      ##
##      ##
########
##      ##
##      ##
########

: Note that comments are not accepted inside bitmaps; they would just be treated as bitmap data.

For more details, consult the convfont readme.

Using Fonts in Your Project

Once your .FNT file has been created, use the convfont utility included with the SDK to convert the .FNT resource file into a format usable in your project.

There are two main ways of including a font in your project:

  • directly in your program binary; or,

  • in separate font pack appvar.

Embedding a Font Directly in Your Program

Embedding a font directly in your program ensures the font will always be available, but it prevents it from being used by any other program, and bloats your program. However, it is also the easiest way to access a custom font.

Place your .FNT font files in your source code directory. Then, create a myfonts.h source code file:

/* Declare globally-accessible pointers to the font data. */
extern const fontlib_font_t *my_font_1;
extern const fontlib_font_t *my_font_2;
. . .

Then create a myfonts.c file:

/* This contains the raw data for the font. */
static const uint8_t my_font_1_data[] = {
    #include "myfont1.inc"
};
/* However, C89 does not allow us to typecast a byte array into a
fontlib_font_t pointer directly, so we have to use a second statement to do it,
though helpfully we can at least do it in the global scope. */
const fontlib_font_t *my_font_1 = (fontlib_font_t *)my_font_1_data;

static const uint8_t my_font_2_data[] = {
    #include "myfont2.inc"
};
const fontlib_font_t *my_font_2 = (fontlib_font_t *)my_font_2_data;

Now you should be wondering where the myfont1.inc file comes from. This file will get generated by your makefile, which will need to be modified to append the following:

# This is a roundabout way to tell make that myfonts.c depends on the .inc files.
# It does it by saying the compiled object code depends on the .inc files.
$(OBJDIR)/myfonts.src: $(SRCDIR)/myfont1.inc $(SRCDIR)/myfont2.inc

# Convert a .fnt file into a .inc file
$(SRCDIR)/myfont1.inc: $(SRCDIR)/myfont1.fnt
    convfont -o carray -f $(SRCDIR)/myfont1.fnt $(SRCDIR)/myfont1.inc

$(SRCDIR)/myfont2.inc: $(SRCDIR)/myfont2.fnt
    convfont -o carray -f $(SRCDIR)/myfont2.fnt $(SRCDIR)/myfont2.inc

Finally, somewhere else in your program, you can use fontlib_SetFont:

void main() {
    . . .
    fontlib_SetFont(my_font_1, 0);
    . . .
}

Packaging a Font Pack

Font packs are an alternative to directly embedding a font in your program binary. They allow multiple related fonts to be packaged together, and FontLibC can select a font from the font pack given a requested size and style. The fonts in a font pack can be used by other programs, reducing the size of your program and saving valuable space on-calculator. They can also be archived, freeing up limited RAM.

A font pack should contain related fonts, namely different sizes and styles of a typeface. It is legal for a font pack to contain only one font. Metadata fields in a font pack, such as the description, should be short.

Font packs are easiest to make as a separate project. Create a new folder, place your .fnt files in it, and then create a makefile with the following contents:

# Put each of your .fnt files on this next line.
# Look at the documentation for convfont for more information on font properties
temp.bin: font1.fnt font2.fnt font3.fnt
    convfont -o fontpack -N "Font Name" -P "ASCII" -V "Some version or date" -A "Your Name" \
    -D "A SHORT description of your font" \
    -f font1.fnt -a 1 -b 1 -w bold -s sans-serif -s upright -s proportional \
    -f font2.fnt -a 2 -b 2 -w normal -s serif -s italic \
    -f font3.fnt -a 0 -b 3 -w light -s monospaced \
    temp.bin

# Don't forget to change font_pack_file_name on both these lines.
# Set PACKNAME to the on-calculator appvar name you want
font_pack_file_name.8xv: temp.bin
    convhex -a -v -n PACKNAME temp.bin font_pack_file_name.8xv

all: font_pack_file_name.8xv

Using Font Packs

While using an embedded font is easy—just call fontlib_SetFont directly on the pointer to the font data—, using a font pack is a bit more involved.

WARNING: FontLibC caches a pointer to the font’s data when you use SetFont. If you do something that causes the font’s data to move, that pointer becomes invalid and FontLibC will start displaying garbage! For example, if a font appvar is in RAM, any operation that creates or resizes a file may invalidate the cached pointer. Simply calling SetFont again will not suffice to fix this; you must also lookup the font’s location again. This also applies if a font pack is archived, and you do something that causes a garbage collection cycle.

(The above warning does not apply to fonts embedded into your program, as data embedded in your program cannot get moved.)

Opening a Font Pack the Simple Way

If you require a specific font pack with a specific appvar name, then opening a font is straight-forward:

#include <graphx.h>
#include <fontlibc.h>

void main(void) {
    fontlib_font_t *my_font;
    . . .
    /* Get the first font present in the font pack */
    my_font = fontlib_GetFontByIndex("MYFONT", 0);
    /* This check is important! If fetching the font fails, trying to use the font will go . . . poorly. */
    if (!my_font) {
        gfx_PrintStringXY("MYFONT appvar not found or invalid", 0, 0);
        return;
    }
    /* Use font for whatever */
    fontlib_SetFont(my_font, 0);
    . . .
}

Caching a Font Pack’s Address

However, accessing fonts this way triggers a slow VAT lookup for the appvar every time you call a GetFont routine. You can avoid this overhead—provided you keep in mind the above warning about moving data around—by using the FileIOC library to get a direct pointer to the appvar’s data.

uint8_t file;
fontlib_font_pack_t *my_font_pack;
fontlib_font_t *my_font;
. . .
/* Open file */
file = ti_open("MYFONT", "r");
/* Throw an error if the file was not found */
if (!my_font_pack) {
    gfx_PrintStringXY("MYFONT appvar not found", 0, 0);
    return;
}
my_font_pack = ti_GetDataPtr(file);
/* Once we have the pointer, we don't need the file handle any more. */
ti_Close(file);
/* Just because the file exists doesn't mean it's actually a font pack */
my_font = fontlib_GetFontByIndexRaw(my_font_pack, 0);
if (!my_font) {
    gfx_PrintStringXY("MYFONT appvar is invalid", 0, 0);
    return;
}

Finding a Font Pack by Typeface Name

In addition to opening a font pack by appvar name, FontLibC also provides the special routine fontlib_GetFontPackName to make it easier to search for a font pack by typeface name:

char *var_name;
char *typeface_name;
fontlib_font_pack_t *my_font_pack;
uint8_t *search_pos = NULL;
while ((var_name = ti_DetectVar(&search_pos, "FONTPACK", TI_APPVAR_TYPE)) != NULL) {
    typeface_name = fontlib_GetFontPackName(var_name);
    /* Font packs can omit the name metadata property, so check for that. */
    if (!typeface_name)
        continue;
    /* Do something interesting with the typeface_name here.
       Note that a direct pointer to the name is returned, which may be archived,
       so you cannot write to the string. */
    if (!strcmp(typeface_name, "My Font")) {
        fontlib_SetFont(fontlib_GetFontByIndex(var_name, 0), 0);
        break;
    }
}

Looking at Other Font Metadata

There are no other routines for processing the other metadata fields in a font pack. However, it is not hard to process the metadata fields yourself:

uint8_t file;
fontlib_font_pack_t *font_pack;
int metadata_offset;
fontlib_metadata_t *font_pack_metadata;
char *font_pack_author;
. . .
/* Assume that file is the already-opened appvar of the font pack. */
font_pack = ti_GetDataPtr(file);
metadata_offset = font_pack->metadata;
if (!metadata_offset)
    return; /* No metadata in the font pack, do something else here */
ti_Seek(metadata_offset, SEEK_SET, file);
font_pack_metadata = ti_GetDataPtr(file);
metadata_offset = font_pack_metadata->font_author;
if (!metadata_offset)
    return; /* No author specified */
ti_Seek(metadata_offset, SEEK_SET, file);
font_pack_author = ti_GetDataPtr(file);
/* Now you have the author name string */

Selecting a Font by Style

The GetFontByStyle routines help you automatically select a font given a set of size and style criteria.

fontlib_font_pack_t *font_pack;
fontlib_font_t *font;
. . .
/* Assume font_pack already points to a valid font pack. */
/* Get a 9 or 10 pixel tall bold, serif font that isn't monospaced and isn't italic. */
font = fontlib_GetFontByStyleRaw(font_pack, 9, 10, FONTLIB_BOLD, FONTLIB_BOLD, FONTLIB_SERIF, FONTLIB_MONOSPACED | FONTLIB_ITALIC);
if (font)
    fontlib_SetFont(font, 0);

API Usage Notes

Text Windowing

To assist in text layout, fontlibc provides for a text window, which automatically confines text to appear in a specific rectangular area of the screen. This feature may be useful for dialogs and scrolling large blocks of text. Use fontlib_SetWindow to set the current window bounds. Use fontlib_SetNewlineOptions to control how fontlib_DrawString behaves when it reaches the right edge of he text window.

Aligning Text

Implementing centered text, right-aligned text, and word wrap requires being able to compute the width of a word or string of text. The routine fontlib_GetStringWidth provides this functionality.

If you call fontlib_SetAlternateStopCode(' '), fontlib_GetStringWidth and fontlib_DrawString will stop drawing on spaces, giving you a chance to check if the next word will fit on screen. You can use fontlib_GetLastCharacterRead() to find out where fontlib_GetStringWidth or fontlib_DrawString stopped, and, after handling the space, then pass that address (plus one) again to fontlib_GetStringWidth or fontlib_DrawString to resume processing at where it left off before.

Text Control Codes

Embedded control codes are a popular way of managing style and formatting information in string. fontlibc only natively recognizes two types of control codes: NULL (0) as a stop code and a user-specified alternate stop code, and a user-specified newline code (defaults to 0x0A—ASCII LF and standard Linux style). However, you can add your own control codes with fontlib_SetFirstPrintableCodePoint. When any code point less than the first printable code point is encountered, fontlibc stops string processing and returns to allow you to handle the control code yourself using fontlib_GetLastCharacterRead.

Transparent Text

Part of providing high-performance is not painting a single pixel more than once. To assist with this goal, fontlibc provides for both transparent and opaque text backgrounds. Use fontlib_SetTransparency(true) if you need to paint text over a background other than a solid color. If you turn transparency off, however, fontlibc will paint both background and foreground pixels for you, eliminating the time needed to erase those pixels before painting over that area.

Line Spacing

Since a block of text may not always be the same size, fontlibc provides fontlib_ClearEOL for erasing the remainder of a line of text without needing to pad it with spaces. This action can also be performed automatically after embedded newlines in text and on normal wrapping with fontlib_SetNewlineOptions.

Additional blank vertical space around text can improve readability in large blocks of text. fontlib_SetLineSpacing allows you to set this behavior. Fonts may specify default additional spacing that is automatically applied when calling fontlib_SetFont. In GUIs and games where the benefits of legibility are outweighed by more aggressive use of vertical space, you can force the default spacing to zero after using fontlib_SetFont with fontlib_SetLineSpacing.

API Documentation

Provides improved font support.

Author

DrDnar

Typedefs

typedef struct fontlib_metadata_t fontlib_metadata_t

Contains references to various metadata strings.

Note

Any or all of these offsets may be NULL.

Note

These should be short null-terminated C strings, but this is not enforced. Check for malformed metadata!

typedef struct fontlib_font_t fontlib_font_t

This is the actual font format.

Directly reading from this struct is the only way to read a font’s cap_height, x_height, and baseline_height metrics.

For example:

unsigned char baseline;
fontlib_font_t *my_font = fontlib_GetFontByStyle("FONTPACK", 12, 12,
    FONTLIB_NORMAL, FONTLIB_NORMAL, FONTLIB_SERIF, 0);
if (!my_font || !fontlib_SetFont(my_font))
    return;
baseline = my_font->baseline_height;

Note

The font’s width table and bitmaps table should appear directly after this struct. The struct does not contain a member for the data because it is probably not useful for C code to parse the width or bitmap data directly.

typedef struct fontlib_font_pack_t fontlib_font_pack_t

This is the format of a font pack appvar.

Parsing this directly is the only way to get metadata other than the typeface name.

FILE font_pack_file;
fontlib_font_pack_t *font_pack;
fontlib_metadata_t *metadata;
char *var_name;
char *font_author;
uint8_t *search_pos = NULL;
// Just randomly select the first font pack found
if ((var_name = ti_Detect(&search_pos, "FONTPACK")) == NULL)
    return;
// Get font pack header
font_pack_file = ti_Open(var_name, "r");
font_pack = ti_GetDataPtr(font_pack_file);
// Is metadata present?
if (!font->metadata)
    return;
if (EOF == ti_Seek(font->metadata, SEEK_SET, font_pack_file))
    return;
// Is metadata semi-valid?
metadata = ti_GetDataPtr(font_pack_file);
if (metadata->length < sizeof(fontlib_metadata_t))
    return;
// Get font's author
if (!metadata->font_author)
    return;
if (EOF == ti_Seek(metadata->font_author, SEEK_SET, font_pack_file))
    return;
font_author = ti_GetDataPtr(font_pack_file);
ti_Close(font_pack_file);

Enums

enum fontlib_newline_options_t

Options for controlling newline behavior.

Values:

enumerator FONTLIB_ENABLE_AUTO_WRAP = 0x01

Enables automatic wrapping at the end of the line.

Note

This is per-glyph; word warp is neither implemented nor planned

enumerator FONTLIB_AUTO_CLEAR_TO_EOL = 0x02

Upon any newline, clears the remainder of the line of text.

Note

Useful for printing over previously printed text when transparency is turned off, as this means each pixel in a line of text need only be visited once.

enumerator FONTLIB_PRECLEAR_NEWLINE = 0x04

Clears the NEXT line of text.

Note

Don’t combine this with AUTO_CLEAR because that just wastes CPU cycles due to erasing/drawing each pixel twice.

enumerator FONTLIB_AUTO_SCROLL = 0x08

Enables automatic scrolling when a newline would push the cursor past the bottom of the text window.

The cursor is left at the bottom left.

Note

If PRECLEAR is not set, then the bottom line of text will not be erased.

enum fontlib_load_options_t

Options for controlling how SetFont functions.

See also

fontlib_SetFont

Values:

enumerator FONTLIB_IGNORE_LINE_SPACING = 0x01

If set, then the space above/below metrics specified in the font will be ignored and set to zero.

You can still manually set them later.

enum fontlib_styles_t

Options for selecting a font by style.

Values:

enumerator FONTLIB_SERIF = 0x01

Clear = sans-serif font.

enumerator FONTLIB_OBLIQUE = 0x02

Oblique is slanted like italic text, but with the cursive-like styling.

enumerator FONTLIB_ITALIC = 0x04

If both italic and oblique are set, then assume there’s no difference between oblique and italic styles.

enumerator FONTLIB_MONOSPACED = 0x08

Monospaced font.

Note

Chances are you’re not using this library for monospaced fonts. But if you are, you’ll still have to provide a widths table where every byte is the same.

Note

This is not enforced; a variable-width font can claim to be monospaced!

enum fontlib_weights_t

Options for selecting a font by weight.

Values:

enumerator FONTLIB_THIN = 0x20
enumerator FONTLIB_EXTRA_LIGHT = 0x30
enumerator FONTLIB_LIGHT = 0x40
enumerator FONTLIB_SEMILIGHT = 0x60
enumerator FONTLIB_NORMAL = 0x80
enumerator FONTLIB_MEDIUM = 0x90
enumerator FONTLIB_SEMIBOLD = 0xA0
enumerator FONTLIB_BOLD = 0xC0
enumerator FONTLIB_EXTRA_BOLD = 0xE0
enumerator FONTLIB_BLACK = 0xF0

Functions

void fontlib_SetWindowFullScreen(void)

Sets the bounds of the window all text will appear in to be the full screen.

This is the default.

void fontlib_SetWindow(unsigned int x_min, uint8_t y_min, unsigned int width, uint8_t height)

Sets the bounds of the window all text will appear in.

Note

Clipping of partial glyphs is not supported. If a glyph, either horizontally or vertically, does not fit in the text window, it will not be printed at all.

Note

Behavior is undefined if the text cursor is positioned outside of the current text window.

Warning

Changing this does not automatically move the text cursor into the window.

Parameters
  • x_min[in] X coord base

  • y_min[in] Y coord base

  • width[in] Width

  • height[in] Height

unsigned int fontlib_GetWindowXMin(void)

Returns the starting column of the current text window.

Returns

Window X

uint8_t fontlib_GetWindowYMin(void)

Returns the starting row of the current text window.

Returns

Window Y

unsigned int fontlib_GetWindowWidth(void)

Returns the width of the current text window.

Returns

Window width

uint8_t fontlib_GetWindowHeight(void)

Returns the height of the current text window.

Returns

Window height

void fontlib_SetCursorPosition(unsigned int x, uint8_t y)

Sets the cursor position.

Behavior is undefined if the cursor is set outside of the text window.

Parameters
  • x[in] X

  • y[in] Y

unsigned int fontlib_GetCursorX(void)

Returns the cursor column.

Returns

Current cursor X

uint8_t fontlib_GetCursorY(void)

Returns the cursor row.

Returns

Current cursor Y

void fontlib_ShiftCursorPosition(int x, int y)

Adds the given (x,y) to the cursor position.

Note

Useful for tabbing, for example.

Warning

Behavior is undefined if the resulting cursor position is offscreen.

Parameters
  • x[in] x-shift

  • y[in] y-shift

void fontlib_HomeUp()

Moves the cursor to the upper left corner of the text window.

void fontlib_Home()

Moves the cursor back to the start of the current line.

bool fontlib_SetFont(const fontlib_font_t *font_data, fontlib_load_options_t flags)

Sets the current font.

Warning

If false is returned, no valid font is currently loaded and trying to print will print garbage!

Parameters
  • font_data[in] Pointer to font data

  • flags[in] Information about how to process the font (unused)

Returns

Returns false if the font seems invalid for any reason

void fontlib_SetForegroundColor(uint8_t color)

Sets the current foreground color FontLibC will use for drawing.

Note

This is NOT the same as GraphX’s current color!

Parameters

color – New color to use

void fontlib_SetBackgroundColor(uint8_t color)

Sets the current background color FontLibC will use for drawing.

Note

This is NOT the same as GraphX’s current color!

Parameters

color[in] New color to use

void fontlib_SetColors(uint8_t forecolor, uint8_t backcolor)

Sets the current colors FontLibC will use for drawing.

Note

These are NOT the same as GraphX’s current colors!

Parameters
  • forecolor[in] New foreground color to use

  • backcolor[in] New background color to use

uint8_t fontlib_GetForegroundColor(void)

Returns the current foreground color FontLibC will use for drawing.

Note

This is NOT the same as GraphX’s current color!

Returns

Current foreground color

uint8_t fontlib_GetBackgroundColor(void)

Returns the current background color FontLibC will use for drawing.

Note

This is NOT the same as GraphX’s current color!

Returns

Current background color

void fontlib_SetTransparency(bool transparency)

Controls whether FontLibC will use a transparent background for text drawing instead of the currently configured background color.

Note

This has nothing to do with GraphX’s configured transparent color

Parameters

transparency[in] true to make background transparent, false to use background color

bool fontlib_GetTransparency(void)

Returns whether FontLibC will use a transparent background for text drawing instead of the currently configured background color.

Note

This has nothing to do with GraphX’s configured transparent color

Returns

true if background will be transparent, false if background color will be used

void fontlib_SetLineSpacing(uint8_t space_above, uint8_t space_below)

Controls hows much black space will be added above and below each line of text.

If transparency is set, then the padding will not be overwritten with the background color, but padding will still be added. Padding space is added at the time each glyph is drawn.

Parameters
  • space_above[in] Blank space padding to add above

  • space_below[in] Blank space padding to add below

uint8_t fontlib_GetSpaceAbove(void)

Returns current padding space above.

Returns

Current padding space above

uint8_t fontlib_GetSpaceBelow(void)

Returns current padding space below.

Returns

Current padding space below

void fontlib_SetItalicSpacingAdjustment(uint8_t italic_spacing_adjustment)

Sets current spacing adjustment for italic text.

This causes the cursor to be moved back a certain number of pixels after every glyph is drawn.

Note

This is only useful if transparency mode is set.

Note

Italics is currently untested! (I haven’t designed an italic font yet.)

Parameters

italic_spacing_adjustment[in] Pixels to move cursor backward after each glyph

uint8_t fontlib_GetItalicSpacingAdjustment(void)

Returns current spacing adjustment for italic text.

Returns

Current spacing adjustment for italic text

uint8_t fontlib_GetCurrentFontHeight(void)

Returns the height of the current font, INCLUDING space above/below.

Returns

Height in pixels

bool fontlib_ValidateCodePoint(char code_point)

Tests whether the current font has the given code point.

Parameters

code_point[in] Code point to test

Returns

true if code_point is in current font, false if not

size_t fontlib_GetTotalGlyphs(void)

Returns the total number of printable glyphs in the font.

Note

This can return 256; no valid font has 0 printable glyphs.

Returns

Total number of printable glyphs

char fontlib_GetFirstGlyph(void)

Returns the code point of the first printable glyph.

Note

The C SDK makes char SIGNED by default, so you probably want to typecast this to unsigned char before attempting any math with it.

Returns

First print glyph code point

void fontlib_SetNewlineCode(char code_point)

Allows you to set the code point that is recognized as being a new line code.

You can set this to zero to prevent new line code processing.

Note

If FONTLIB_ENABLE_AUTO_WRAP is enabled, then wrapping will still implicitly case a newline.

Note

This defaults to 0x0A (ASCII line feed/UNIX newline)

Parameters

code_point[in] New code point to use for newline

char fontlib_GetNewlineCode(void)

Returns the code point that is currently recognized as being a newline.

If 0, newlines in strings will not be processed.

Returns

Current newline

void fontlib_SetAlternateStopCode(char code_point)

Sets an alternate code point to recognize as a stop code.

Set this to 0 if you do not want to use the alternate stop code feature. Defaults to 0.

Note

You can set this to space to make DrawString and GetStringWidth stop processing when they reach a space.

Note

NULL (0) will still be recognized as a stop code regardless of value.

Parameters

code_point[in] Additional code point to recognize as a stop code.

char fontlib_GetAlternateStopCode(void)

Returns the current alternate stop code.

Returns

Current alternate stop code.

void fontlib_SetFirstPrintableCodePoint(char code_point)

Sets the first code point considered printable.

All code points before this will be considered control codes. This defaults 0x10.

Note

Setting this to 0 (NULL) will NOT cause NULL to be ignored.

Parameters

code_point[in] First printable code point

char fontlib_GetFirstPrintableCodePoint(void)

Returns the first code point considered printable.

Returns

Current first printable code point

void fontlib_SetDrawIntCodePoints(char minus, char zero)

Sets the code points DrawInt and DrawUInt will use for the minus symbol and digits 0-9.

Parameters
  • minus[in] Minus symbol code point, defaults to ‘-‘

  • zero[in] Zero code point, defaults to ‘0’; ‘1’-‘9’ are assumed to follow

char fontlib_GetDrawIntMinus(void)

Returns the code point DrawInt and DrawUInt will use for a minus symbol Defaults to ‘-‘.

Returns

‘-‘ or whatever you set it to

char fontlib_GetDrawIntZero(void)

Returns the code point DrawInt and DrawUInt will use for ‘0’; it assumes ‘1’-‘9’ follow ‘0’ Defaults to ‘0’.

Returns

‘0’ or whatever you set it to

uint8_t fontlib_GetGlyphWidth(char codepoint)

Returns the width of the given glyph.

Parameters

codepoint[in] Codepoint to test

Returns

Width of glyph, 0 if invalid codepoint

unsigned int fontlib_GetStringWidth(const char *str)

Returns the width of a string printed in the current font.

Stops processing when it encounters ANY control code or a codepoint not in the current font.

Parameters

str[in] Pointer to string

Returns

Width of string

unsigned int fontlib_GetStringWidthL(const char *str, size_t max_characters)

Returns the width of a string printed in the current font.

Stops processing when it encounters ANY control code or a codepoint not in the current font, or when max_characters have been processed.

Parameters
  • str[in] Pointer to string

  • max_characters[in] Maximum number of characters to process

Returns

Width of string

char *fontlib_GetLastCharacterRead(void)

Gets the location of the last character processed by GetStringWidth or DrawString.

Returns

Pointer to character

size_t fontlib_GetCharactersRemaining(void)

Returns 0 if DrawStringL or GetStringWidthL returned because max_characters were processed.

Returns a non-zero number otherwise.

Returns

Either zero, or a non-zero number depending on the reason DrawStringL or GetStringWidthL returned.

uint24_t fontlib_DrawGlyph(uint8_t glyph)

Draws a glyph.

Note

This can even draw code points less than the code point specified with fontlib_SetFirstPrintableCodePoint(). It can even draw code point 0.

Note

Although this does update the cursor X/Y positions, it does NOT process window bounds at all! (Maybe this should be FIXME? On the other hand, users may want this specifically so they can handle all their own layout without the text window settings getting in their way.)

Parameters

glyph[in] Codepoint

Returns

The new X value of the cursor

uint24_t fontlib_DrawString(const char *str)

Draws a string.

This will return when it reaches the right edge of the text window if FONTLIB_ENABLE_AUTO_WRAP is turned off.

This stops drawing upon reaching NULL. It will also stop if it encounters the character code specified with fontlib_SetAlternateStopCode().

Note

The check for the alternate stop code always takes place before drawing a glyph, so if you need to also display the stop code character, you must directly call fontlib_DrawGlyph to force display the character and increment past it.

Note

Newline codes will print regardless of whether FONTLIB_ENABLE_AUTO_WRAP is enabled. To disable parsing newline codes, use fontlib_SetNewlineCode(0);

Note

THIS IS NOT REENTRANT (though if you need that, you’re probably not using C)

Parameters

str[in] Pointer to string

Returns

The new X value of the cursor (probably not useful if a newline was processed.)

uint24_t fontlib_DrawStringL(const char *str, size_t max_characters)

Draws a string, up to a maximum number of characters.

Note

This is intended to be used if you only want a portion of a string printed. (Or if you hate null-terminated strings and want length-prefixed strings instead. It still won’t print NULLs though.)

Note

THIS IS NOT REENTRANT (though if you need that, you’re probably not using C)

Parameters
  • str – Pointer to string

  • max_characters[in] Maximum number of characters to attempt to print, may return early if some other condition requires returning

Returns

The new X value of the cursor (probably not useful if a newline was processed.)

void fontlib_DrawInt(int n, uint8_t length)

Prints a signed integer.

Outputs at the current cursor position. Padded with leading zeros if necessary to satisfy the specified minimum length.

Note

This does not obey window bounds like DrawString/L

Note

length must be between 1 and 8, inclusive

Parameters
  • n[in] Integer to print

  • length[in] Minimum number of characters to print

void fontlib_DrawUInt(unsigned int n, uint8_t length)

Prints an unsigned integer.

Outputs at the current cursor position. Padded with leading zeros if necessary to satisfy the specified minimum length.

Note

This does not obey window bounds like DrawString/L

Note

length must be between 1 and 8, inclusive

Parameters
  • n[in] Unsigned integer to print

  • length[in] Minimum number of characters to print

void fontlib_ClearEOL(void)

Erases everything from the cursor to the right side of the text window (End-Of-Line).

This ignores the transparent background flag.

void fontlib_ClearWindow(void)

Erases the entire current text window.

Note

This ignores the transparent background flag. If background transparency is important, check fontlib_GetTransparency() before calling this routine.

bool fontlib_Newline(void)

Performs a newline.

Pays attention to newline flags.

Returns

Returns true if the text window is full. This only happens if scrolling is disabled.

void fontlib_SetNewlineOptions(uint8_t options)

Sets options for controlling newline behavior.

Parameters

options[in] Flags setting newline behavior

uint8_t fontlib_GetNewlineOptions(void)

Gets the current newline behavior options.

Returns

Current newline behavior options

void fontlib_ScrollWindowDown(void)

Scrolls the contents of the text window down one line, i.e.

everything in the window is copied UP one line, thus yielding the effect of scrolling down. The current text cursor position is ignored.

Note

The bottom line is not erased; you must erase or overwrite it yourself.

void fontlib_ScrollWindowUp(void)

Scrolls the contents of the text window up one line, i.e.

everything in the window is copied DOWN one line, thus yielding the effect of scrolling up. The current text cursor position is ignored.

Note

The bottom line is not erased; you must erase or overwrite it yourself.

Note

This doesn’t try to compute the location of the bottom line of text; it just blindly copies rows of pixels, so make sure the window height is an exact multiple of the font height.

char *fontlib_GetFontPackName(const char *appvar_name)

Gets the long name associated with a font pack.

Useful in a loop with ti_Detect() when searching a typeface with a specific name.

Parameters

appvar_name[in] Pointer to name of appvar

Returns

Direct pointer to font’s name; or NULL if no such appvar exists, the appvar isn’t a font pack, or the font pack does not supply a name. NOTA BENE: Any operation that can move variables around in memory can invalidate this pointer!

fontlib_font_t *fontlib_GetFontByIndexRaw(const fontlib_font_pack_t *font_pack, uint8_t index)

Gets a pointer to a font, suitable for passing to SetFont(), given a font pack’s address.

Useful if you know caching the font pack’s address is safe.

See also

ti_GetDataPtr()

Parameters
  • font_pack[in] Pointer to font pack

  • index[in] Index into font table of font pack

Returns

Direct pointer to font, or NULL if the index is invalid.

fontlib_font_t *fontlib_GetFontByIndex(const char *font_pack_name, uint8_t index)

Gets a pointer to a font, suitable for passing to SetFont(), given a font pack’s appvar’s name.

Recommended to use after any file write, create, delete, or un/archive, as all those operations could invalidate the cached data pointers to the currently loaded font.

Parameters
  • font_pack_name[in] Pointer to font pack appvar’s name

  • index[in] Index into font table of font pack

Returns

Direct pointer to font, or NULL if the index is invalid.

fontlib_font_t *fontlib_GetFontByStyleRaw(const fontlib_font_pack_t *font_pack, uint8_t size_min, uint8_t size_max, uint8_t weight_min, uint8_t weight_max, uint8_t style_bits_set, uint8_t style_bits_reset)

Gets a pointer to a font, suitable for passing to SetFont(), given a font pack’s address and a set of font properties.

Useful if you know caching the font pack’s address is safe.

See also

ti_GetDataPtr()

Parameters
  • font_pack[in] Pointer to font pack

  • size_min[in] Minimum heigh, in pixels, to accept. Space above and space below metrics are not considered.

  • size_max[in] Maximum height

  • weight_min[in] Minimum weight to accept. 0 may be used.

  • weight_max[in] Maximum weight to accept. 0xFF may be used.

  • style_bits_set[in] Mask of style bits you want set. For example, FONTLIB_SERIF | FONTLIB_MONOSPACE to look for a monospaced serifed font.

  • style_bits_reset[in] Style bits you want RESET. For example, pass FONTLIB_MONOSPACE to REJECT monospaced fonts.

Returns

Direct pointer to font, or NULL if no matching font is found

fontlib_font_t *fontlib_GetFontByStyle(const char *font_pack_name, uint8_t size_min, uint8_t size_max, uint8_t weight_min, uint8_t weight_max, uint8_t style_bits_set, uint8_t style_bits_reset)

Gets a pointer to a font, suitable for passing to SetFont(), given a font pack’s appvar’s name and a set of font properties.

Recommended to use after any file write, create, delete, or un/archive, as all those operations could invalidate the cached data pointers to the currently loaded font.

Parameters
  • font_pack_name[in] Pointer to font pack appvar’s name

  • size_min[in] Minimum heigh, in pixels, to accept. Space above and space below metrics are not considered.

  • size_max[in] Maximum height

  • weight_min[in] Minimum weight to accept. 0 may be used.

  • weight_max[in] Maximum weight to accept. 0xFF may be used.

  • style_bits_set[in] Mask of style bits you want set. For example, FONTLIB_SERIF | FONTLIB_MONOSPACE to look for a monospaced serifed font.

  • style_bits_reset[in] Style bits you want RESET. For example, pass FONTLIB_MONOSPACE to REJECT monospaced fonts.

Returns

Direct pointer to font, or NULL if no matching font is found

struct fontlib_metadata_t
#include <fontlibc.h>

Contains references to various metadata strings.

Note

Any or all of these offsets may be NULL.

Note

These should be short null-terminated C strings, but this is not enforced. Check for malformed metadata!

Public Members

int24_t length

Size of this struct, basically functions as a version field.

This does NOT include the lengths of the strings!

int24_t font_family_name

A short, human-readable typeface name, such as “Times”.

int24_t font_author

A SHORT string naming the typeface designer.

int24_t font_pseudocopyright

A SHORT copyright claim.

Do not try to include a complete license in here! Space is limited!

Note

Typefaces and bitmapped fonts cannot be copyrighted under US law. This field is therefore referred to as a pseudocopyright. HOWEVER, it IS is applicable in other jusrisdictions, such as Germany.

int24_t font_description

A BRIEF description of the font.

int24_t font_version

Note

This is a STRING, so while this should be something like “1.0.0.0” it could also be something like “1 June 2019” or even “Hahaha versioning

is overrated!”

int24_t font_code_page

Suggested values: “ASCII” “TIOS” “ISO-8859-1” “Windows 1252” “Calculator 1252”.

struct fontlib_font_t
#include <fontlibc.h>

This is the actual font format.

Directly reading from this struct is the only way to read a font’s cap_height, x_height, and baseline_height metrics.

For example:

unsigned char baseline;
fontlib_font_t *my_font = fontlib_GetFontByStyle("FONTPACK", 12, 12,
    FONTLIB_NORMAL, FONTLIB_NORMAL, FONTLIB_SERIF, 0);
if (!my_font || !fontlib_SetFont(my_font))
    return;
baseline = my_font->baseline_height;

Note

The font’s width table and bitmaps table should appear directly after this struct. The struct does not contain a member for the data because it is probably not useful for C code to parse the width or bitmap data directly.

Public Members

uint8_t fontVersion

Version ID.

Note

This must be zero or the font will be rejected as invalid.

uint8_t height

Height in pixels not including space above/below.

uint8_t total_glyphs

Total number of glyphs provided.

Note

If this is zero, then 256 glyphs are provided, not zero!

uint8_t first_glyph

Number of first glyph.

If you have no codepoints below 32, for example, you can omit the first 32 bitmaps.

int24_t widths_table

Offset/pointer to glyph widths table.

This is an OFFSET from the fontVersion member

Note

It is 24-bits long because it becomes a real pointer upon loading.

int24_t bitmaps

Offset to a table of offsets to glyph bitmaps.

Note

Parsing the bitmaps yourself is probably not useful.

Note

These offsets are only 16-bits each to save some space.

uint8_t italic_space_adjust

Specifies how much to move the cursor left after each glyph.

Total movement is width - overhang.

Note

Intended for italics.

uint8_t space_above

These suggest adding blank space above or below each line of text.

Note

This can be overridden

Note

This can increase legibility while saving space for always-blank lines.

uint8_t space_below
uint8_t weight

Specifies the boldness of the font.

uint8_t style

Specifies the style of the font.

See also

fontlib_styles_t

uint8_t cap_height

For layout, allows aligning text of differing fonts vertically.

These count pixels going down, i.e. 0 means the top of the glyph.

uint8_t x_height
uint8_t baseline_height
struct fontlib_font_pack_t
#include <fontlibc.h>

This is the format of a font pack appvar.

Parsing this directly is the only way to get metadata other than the typeface name.

FILE font_pack_file;
fontlib_font_pack_t *font_pack;
fontlib_metadata_t *metadata;
char *var_name;
char *font_author;
uint8_t *search_pos = NULL;
// Just randomly select the first font pack found
if ((var_name = ti_Detect(&search_pos, "FONTPACK")) == NULL)
    return;
// Get font pack header
font_pack_file = ti_Open(var_name, "r");
font_pack = ti_GetDataPtr(font_pack_file);
// Is metadata present?
if (!font->metadata)
    return;
if (EOF == ti_Seek(font->metadata, SEEK_SET, font_pack_file))
    return;
// Is metadata semi-valid?
metadata = ti_GetDataPtr(font_pack_file);
if (metadata->length < sizeof(fontlib_metadata_t))
    return;
// Get font's author
if (!metadata->font_author)
    return;
if (EOF == ti_Seek(metadata->font_author, SEEK_SET, font_pack_file))
    return;
font_author = ti_GetDataPtr(font_pack_file);
ti_Close(font_pack_file);

Public Members

char header[8]

Must be “FONTPACK”.

Note

This is NOT null-terminated!

int24_t metadata

Offset from first byte of header.

uint8_t fontCount

Number of fonts present.

Should be greater than zero… .

Note

Frankly, if you have more than 127 fonts in a pack, you have a problem.

int24_t font_list[1]

Array of offsets to each individual font.

Note

Despite being declared as a single element, this will be fontCount elements long.