diskfont.library β Amiga Bitmap Fonts: Concept, File Format, and Disk Loading
Overview
diskfont.library loads bitmap fonts from disk into the Amiga graphics system. Unlike modern TrueType/OpenType fonts that store mathematical curve descriptions, Amiga fonts are bitmap fonts β each glyph is a hand-drawn grid of pixels at a fixed size. A 14-pixel "Helvetica" and a 24-pixel "Helvetica" are entirely separate files, each hand-designed (or auto-scaled) for that specific pixel height.
This was the dominant font technology of the late 1980s and early 1990s. Before CPUs were fast enough to rasterize BΓ©zier curves on the fly, storing pre-rendered pixel data was the only practical option. The Amiga's bitmap font system was sophisticated for its era β proportional spacing, kerning, algorithmic bold/italic/underline, and color fonts (OS 3.0+) β but it was fundamentally pixel-bound.
Two fonts are built into every Amiga ROM: topaz 8 and topaz 9. Every other font β helvetica, times, courier, garnet, sapphire, and any third-party font β lives on disk under the FONTS: assign and must be loaded via diskfont.library.
[!NOTE] This article focuses on the disk side β font file formats, directory structure, loading pipeline, and the conceptual model. For the in-memory
TextFontstructure, rendering withText()/SetFont(), and algorithmic styles, see text_fonts.md.
The Bitmap Font Concept β Why Pixels Instead of Curves
How Bitmap Fonts Work
A bitmap font stores each character as a flat pixel grid. The letter "A" at 14 pixels tall might be a 9Γ14 pixel array:
.........
..#####..
.##...##.
.##...##.
.#######.
.##...##.
.##...##.
.........
Every glyph at every size is pre-drawn. The OS simply copies the glyph's pixel strip to the screen β no math, no rasterization, no hinting engine. This is why Amiga text rendering is so fast: it's just Blitter and BlitMaskBitMapRastPort operations under the hood.
Comparison with Modern TrueType / OpenType
| Aspect | Amiga Bitmap Fonts | TrueType / OpenType |
|---|---|---|
| Storage | Pixel grid per glyph per size | Mathematical curves (BΓ©zier splines) |
| Scaling | Each size is a separate file; scaling creates distortion | Arbitrary size rendered from same outlines |
| File size | Small per size, but multiplies by size count | One file covers all sizes |
| Quality at scale | Perfect at designed size; jagged/blurry when scaled | Smooth at any size (with hinting) |
| Rendering cost | Near-zero β just copy pixels | Requires curve rasterization + hinting |
| Rotation | Impossible (pixel grid is axis-aligned) | Built-in (curves are coordinate-independent) |
| Memory | Full glyph bitmap in Chip RAM during use | Glyph cache; outlines are small |
| Typographic features | Basic: kerning, proportional spacing | Rich: ligatures, alternates, feature tables |
Why the Amiga Used Bitmap Fonts
- CPU limitations: A 7 MHz 68000 cannot rasterize TrueType curves at interactive speeds. Even on 1990s PCs, TrueType rasterization was a noticeable cost. The Amiga solved this by pre-rendering everything.
- Memory constraints: A 14-pixel bitmap font for ASCII 32β127 fits in roughly 2β4 KB. Loading and blitting pixels uses zero CPU beyond the initial
LoadSeg(). - Hardware acceleration: The Blitter can copy glyph pixels directly to the screen's planar bitmap. This hardware-accelerated text path depends on glyphs already being in planar pixel format.
- Era conventions: In 1985, bitmap fonts were the industry standard. Apple's Macintosh (1984) used bitmap "suitcase" fonts. Windows 3.1 (1992) defaulted to bitmap system fonts. TrueType didn't become universal until the mid-1990s.
Font File Format β The Complete On-Disk Structure
The Two-File Architecture
Every Amiga bitmap font consists of two kinds of files:
FONTS:
βββ helvetica.font β Font Contents File (descriptor)
βββ helvetica/ β Font Data Directory
βββ 9 β Font Descriptor File (size 9)
βββ 11 β Font Descriptor File (size 11)
βββ 14 β Font Descriptor File (size 14)
βββ 19 β Font Descriptor File (size 19)
βββ 24 β Font Descriptor File (size 24)
graph TB
subgraph "Font Contents File<br/>(helvetica.font)"
HDR["FontContentsHeader"]
FC1["FontContents[0]: size 9"]
FC2["FontContents[1]: size 11"]
FC3["FontContents[2]: size 14"]
FC4["..."]
end
subgraph "Font Descriptor Files<br/>(helvetica/9, 11, 14β¦)"
DFH9["DiskFontHeader<br/>+ TextFont<br/>+ glyph bitmaps<br/>(size 9)"]
DFH11["DiskFontHeader<br/>+ TextFont<br/>+ glyph bitmaps<br/>(size 11)"]
DFH14["DiskFontHeader<br/>+ TextFont<br/>+ glyph bitmaps<br/>(size 14)"]
end
FC1 -.->|"points to"| DFH9
FC2 -.->|"points to"| DFH11
FC3 -.->|"points to"| DFH14
style HDR fill:#e8f4fd,stroke:#2196f3,color:#333
style DFH9 fill:#fff9c4,stroke:#f9a825,color:#333
1. The Font Contents File (.font)
This is the index file β it lists every available size for a given typeface. Its C structure:
/* libraries/diskfont.h β NDK39 */
#define MAXFONTPATH 256
struct FontContentsHeader {
UWORD fch_FileID; /* $0F00 = FCH_ID, $0F02 = TFCH_ID, $0F03 = scalable */
UWORD fch_NumEntries; /* number of FontContents entries following */
struct FontContents fch_FC[]; /* variable-length array */
};
struct FontContents {
char fc_FileName[MAXFONTPATH]; /* path to size directory, e.g. "helvetica/14" */
UWORD fc_YSize; /* pixel height */
UBYTE fc_Style; /* FSF_BOLD, FSF_ITALIC, etc. */
UBYTE fc_Flags; /* FPF_ROMFONT, FPF_DISKFONT, etc. */
};
File ID Values
| ID | Name | Meaning |
|---|---|---|
$0F00 |
FCH_ID |
Standard bitmap font (uses FontContents entries) |
$0F02 |
TFCH_ID |
Tagged bitmap font (uses TFontContents β supports TA_DeviceDPI tags) |
$0F03 |
β | Scalable outline font (Compugraphic / IntelliFont, not bitmap) |
File on Disk (Binary Layout)
Offset Size Field
ββββββ ββββ ββββββββββββββββββββββββββββββ
$00 2 fch_FileID ($0F00 for bitmap)
$02 2 fch_NumEntries (e.g. 5 sizes)
$04 260 FontContents[0]
$108 260 FontContents[1]
$20C 260 FontContents[2]
... ... (NumEntries Γ 260 bytes each)
Each FontContents entry is exactly MAXFONTPATH + 4 = 260 bytes, regardless of actual string length. The fc_FileName field is null-padded.
Per-Entry Flags
| Flag | Bit | Meaning |
|---|---|---|
FPF_ROMFONT |
0 | Font is built into ROM (topaz only) |
FPF_DISKFONT |
1 | Font is loaded from disk |
FPF_REVPATH |
2 | Designed for right-to-left text |
FPF_TALLDOT |
3 | Designed for Hires (640-pixel) screen |
FPF_WIDEDOT |
4 | Designed for Lores Interlaced screen |
FPF_PROPORTIONAL |
5 | Character widths are not constant |
FPF_DESIGNED |
6 | Hand-designed at this size (not scaled) |
FPF_REMOVED |
7 | Font has been removed from system list |
2. The Font Descriptor File (numeric filename, e.g. 14)
Each numeric file in the font directory is a loadable DOS hunk β it's literally wrapped as a HUNK_CODE so LoadSeg() can load it. The first two longwords contain a MOVEQ #0,D0 : RTS instruction pair to safely exit if the file is accidentally executed.
/* libraries/diskfont.h β NDK39 */
#define MAXFONTNAME 32
struct DiskFontHeader {
/* The 8 bytes BEFORE this struct (not part of it!) are: */
/* ULONG dfh_NextSegment; // BPTR β filled by LoadSeg */
/* ULONG dfh_ReturnCode; // MOVEQ #0,D0 : RTS */
struct Node dfh_DF; /* Exec Node β links loaded fonts together */
UWORD dfh_FileID; /* DFH_ID ($0F80) */
UWORD dfh_Revision; /* font revision number */
LONG dfh_Segment; /* segment address after LoadSeg */
char dfh_Name[MAXFONTNAME]; /* font name, e.g. "helvetica" */
struct TextFont dfh_TF; /* The actual TextFont structure */
/* Immediately after dfh_TF: glyph bitmap data, char location tables */
};
The dfh_TF is the same struct TextFont described in text_fonts.md. After it in memory come:
| Field | Description |
|---|---|
tf_CharData |
Bitmap strip containing all glyphs (one row per scanline, tf_Modulo bytes wide) |
tf_CharLoc |
Per-character location table: 2 WORDs per glyph (bit offset, width in pixels) |
tf_CharSpace |
Proportional spacing: 1 WORD per glyph (advance width) |
tf_CharKern |
Kerning table: 1 WORD per glyph (extra space after this character) |
The Font Loading Pipeline
sequenceDiagram
participant APP as Application
participant DF as diskfont.library
participant DOS as dos.library
participant DISK as FONTS: (disk)
participant GFX as graphics.library
APP->>DF: OpenDiskFont(&ta)
DF->>DISK: Open("helvetica.font", MODE_OLDFILE)
DISK-->>DF: FileHandle
DF->>DF: Read FontContentsHeader
DF->>DF: Scan entries for matching YSize & Style
DF->>DISK: Close(.font file)
alt Size found
DF->>DOS: LoadSeg("helvetica/14")
DOS-->>DF: Segment (DiskFontHeader loaded)
DF->>DF: Verify dfh_FileID == DFH_ID
DF->>DF: Build TextFont from DiskFontHeader
DF->>GFX: Link font into system font list
DF-->>APP: struct TextFont *
else Size not found
DF-->>APP: NULL
end
APP->>GFX: SetFont(rp, font)
APP->>GFX: Text(rp, "Hello", 5)
APP->>GFX: CloseFont(font)
GFX->>DF: Unlink & free font memory
Font Request Matching
When OpenDiskFont() receives a struct TextAttr, the library searches the .font file's entries:
- Exact YSize match: If the requested size exists as a
fc_YSize, that entry is selected. - No match: Returns
NULL. Unlike modern font systems, the Amiga does not automatically scale to the nearest size. - Style matching: If the requested style (
FSF_BOLD,FSF_ITALIC) doesn't exist at that size,graphics.librarycan algorithmically generate it (SetSoftStyle). - Scaled fonts (
AFF_SCALED): OS 2.0+ can auto-generate intermediate sizes by scaling the nearest designed size. These appear inAvailFonts()with theAFF_SCALEDflag. Quality is significantly worse than hand-designed sizes.
How Software Uses Different Fonts
The Standard Pattern
struct Library *DiskfontBase = OpenLibrary("diskfont.library", 0L);
/* 1. Request a specific disk font: */
struct TextAttr ta = {"helvetica.font", 14, 0, 0};
struct TextFont *font = OpenDiskFont(&ta);
if (font)
{
/* 2. Assign it to the RastPort: */
SetFont(rp, font);
/* 3. Position cursor at baseline: */
Move(rp, 10, 20 + font->tf_Baseline);
/* 4. Render text: */
Text(rp, "Disk-loaded font", 16);
/* 5. Measure text for alignment: */
UWORD w = TextLength(rp, "Centered", 8);
Move(rp, (screenWidth - w) / 2, 50 + font->tf_Baseline);
Text(rp, "Centered", 8);
/* 6. Release when done: */
CloseFont(font);
}
CloseLibrary(DiskfontBase);
ROM Font vs Disk Font β When to Use Each
| Scenario | Use | Why |
|---|---|---|
| System UI, debug output, quick text | OpenFont("topaz.font") β ROM font |
Always available, zero disk access, zero load time |
| Application body text, custom UI | OpenDiskFont("helvetica.font") β disk font |
Professional appearance; user expects non-topaz fonts |
| Word processor, DTP, final output | OpenDiskFont() with FPF_DESIGNED |
Hand-tuned glyphs look best; avoid scaled variants |
| Memory-critical (games, demos) | OpenFont("topaz.font") or embed custom font |
Disk fonts consume Chip RAM for glyph data |
| Font enumeration / chooser | AvailFonts() + iterate |
Build a font picker dialog |
Getting the User's Preferred Font
Applications should respect the system font preference set in Workbench Preferences:
/* Read the user's font preference: */
struct Preferences *prefs = AllocMem(sizeof(struct Preferences), MEMF_ANY);
GetPrefs(prefs, sizeof(struct Preferences));
struct TextAttr userFont = {
prefs->FontName, /* e.g. "helvetica.font" */
prefs->FontSize, /* e.g. 14 or YSIZE_DEFAULT */
FSF_NORMAL,
FPF_DISKFONT
};
struct TextFont *font = OpenDiskFont(&userFont);
if (!font)
{
/* Fall back to topaz if user's font is unavailable */
struct TextAttr fallback = {"topaz.font", 8, 0, FPF_ROMFONT};
font = OpenFont(&fallback);
}
SetFont(rp, font);
FreeMem(prefs, sizeof(struct Preferences));
Adding New Fonts to Amiga
Manual Installation
-
Copy the
.fontfile intoFONTS::bash Copy MyFont.font FONTS: -
Copy the font directory into
FONTS::bash Copy MyFont FONTS: ALL -
Verify the structure:
FONTS: βββ MyFont.font β font contents (index) βββ MyFont/ βββ 11 β size 11 pixels βββ 14 β size 14 pixels βββ 18 β size 18 pixels -
Re-scan available fonts (or reboot). The
AvailFonts()function automatically picks up new fonts on the next call β no reboot needed.
Extending the FONTS: Assign
The FONTS: assign can span multiple directories and volumes:
; Add a floppy disk of fonts to the search path:
Assign FONTS: FontDisk: ADD
; Add fonts from a hard drive subdirectory:
Assign FONTS: Work:MyFonts ADD
; Verify current path:
Assign FONTS:
; Output: FONTS: SYS:Fonts Work:MyFonts FontDisk:
Fonts on any path in the FONTS: assign cascade β if helvetica.font exists in both SYS:Fonts and Work:MyFonts, the first one found is used.
Creating Your Own Fonts β Font Editors
| Tool | Source | Era | Notes |
|---|---|---|---|
| FED (Font EDitor) | Commodore (shipped with Workbench) | 1985β1990 | Basic but functional; shipped with 1.x |
| Personal Fonts Maker | Cloanto | 1990β1994 | Professional drawing tools; the standard for custom bitmap fonts |
| TypeFace | β | 1992+ | Supported both bitmap and Compugraphic outline editing |
| Calligrapher | β | 1991+ | Calligraphic stroke-based font design |
| FontMachine | β | 1993+ | AmigaGuide-based font designer |
Outline Fonts β The Evolution Beyond Bitmaps
OS 2.0 introduced support for Compugraphic (CG) outline fonts, and OS 3.0 added the Agfa IntelliFont engine (via bullet.library). These are .font files with fch_FileID = $0F03 that point to scalable outline data instead of fixed-size bitmaps.
graph LR
subgraph "Bitmap (1.x+)"
B_FONT[".font file<br/>fch_FileID = $0F00"]
B_DIR["size/14<br/>(DiskFontHeader + glyph pixels)"]
B_FONT --> B_DIR
end
subgraph "Outline (2.0+)"
O_FONT[".font file<br/>fch_FileID = $0F03"]
O_ENGINE["bullet.library<br/>(IntelliFont engine)"]
O_DATA["Outline data<br/>(.otag / .ofont / .type)"]
O_FONT --> O_ENGINE
O_ENGINE --> O_DATA
end
style B_FONT fill:#fff9c4,stroke:#f9a825
style O_FONT fill:#e8f5e9,stroke:#4caf50
Outline fonts can scale to any size from a single set of curves, eliminating the need for separate per-size files. However, they require CPU rasterization and were considered slow on 68000β68020 systems β bitmap fonts remained the default for interactive applications.
Enumerating All Available Fonts
struct AvailFontsHeader *afh = NULL;
LONG bufSize = 4096;
/* Retry loop β buffer may be too small: */
do {
if (afh) { FreeMem(afh, bufSize); bufSize += 1024; }
afh = AllocMem(bufSize, MEMF_ANY | MEMF_CLEAR);
} while (AvailFonts((STRPTR)afh, bufSize, AFF_DISK | AFF_MEMORY | AFF_SCALED) > 0);
struct AvailFonts *af = &afh->afh_AF;
for (LONG i = 0; i < afh->afh_NumEntries; i++)
{
UWORD type = af[i].af_Type;
const char *source =
(type & AFF_MEMORY) ? "ROM" :
(type & AFF_DISK) ? "disk" :
(type & AFF_SCALED) ? "scaled" : "other";
Printf("%-20s y=%2ld %-6s %s%s%s\n",
af[i].af_Attr.ta_Name,
af[i].af_Attr.ta_YSize,
source,
(af[i].af_Attr.ta_Style & FSF_BOLD) ? "B" : " ",
(af[i].af_Attr.ta_Style & FSF_ITALIC) ? "I" : " ",
(af[i].af_Attr.ta_Style & FSF_UNDERLINED) ? "U" : " ");
}
FreeMem(afh, bufSize);
Memory Considerations for AvailFonts()
The buffer must be in any memory (not Chip RAM). AvailFonts() writes AvailFontsHeader + N Γ AvailFonts entries. If the buffer is too small, it returns the number of additional bytes needed. The retry loop above handles this correctly.
Color Fonts (OS 3.0+)
OS 3.0 extended bitmap fonts with color support β glyphs with multiple bitplanes:
Traditional font: 1 bitplane β black or background color
Color font: up to 8 bitplanes β 256 colors per glyph
/* graphics/text.h β NDK39 */
struct ColorTextFont {
struct TextFont ctf_TF; /* standard TextFont */
UWORD ctf_Flags; /* CT_COLORFONT, CT_GREYFONT */
UBYTE ctf_Depth; /* number of bitplanes (1β8) */
UBYTE ctf_FgColor; /* default foreground pen */
UBYTE ctf_Low; /* lowest color register used */
UBYTE ctf_High; /* highest color register used */
APTR ctf_PlanePick; /* plane selection for rendering */
APTR ctf_PlaneOnOff; /* plane on/off masks */
struct ColorFontColors *ctf_ColorTable;
APTR ctf_CharData[8]; /* per-plane glyph data pointers */
};
Color fonts store each bitplane as a separate glyph bitmap. The ctf_ColorTable maps pen numbers to the screen's actual palette β a font's "red" might be pen 17 on one screen and pen 5 on another.
[!WARNING] Color fonts require Chip RAM for all glyph data planes. A 24-pixel color font at 8 bitplanes uses 8Γ the memory of a monochrome bitmap font at the same size. On a 512 KB Chip RAM system, this can be prohibitive for multi-font applications.
Historical Context
Competitive Landscape (1985β1993)
| Platform | Font System | Scalable? | Notes |
|---|---|---|---|
| AmigaOS 1.xβ3.x | Bitmap fonts (diskfont.library) | OS 2.0+ (Compugraphic) | Proportional, kerning, algorithmic styles; color fonts in 3.0 |
| Macintosh System 1β6 | Bitmap "suitcase" fonts + FOND resources | No (until TrueType in System 7, 1991) | Multiple sizes per family; 72 DPI screen assumption |
| Windows 1.xβ3.0 | Bitmap .FON files |
No (until TrueType in 3.1, 1992) | Monospaced system font; proportional in 3.0 |
| Atari ST TOS | GDOS bitmap fonts (optional) | No (until SpeedoGDOS, 1991) | 8Γ8 default system font; GDOS added proportional fonts |
| X11 (Unix) | BDF (Bitmap Distribution Format) | No (PostScript via display PostScript) | Server-side fonts; XFT + FreeType came much later |
The Amiga was ahead of its contemporaries in font quality: proportional spacing, kerning, and algorithmic style generation were available from day one (1985). The Mac didn't get TrueType until 1991; Windows until 1992. But by 1993, the industry had shifted to outline fonts, and AmigaOS's bitmap model was showing its age.
The Compugraphic / IntelliFont Era
Commodore licensed Agfa Compugraphic (CG) outline font technology for AmigaOS 2.0, and later Agfa IntelliFont for OS 3.0. These were real outline fonts (cubic BΓ©zier curves), rendered by bullet.library. The Amiga could do what macOS and Windows did with TrueType β but on slower hardware and with a smaller font library. By the time outline fonts arrived, the Amiga market was already in decline.
Modern Analogies
| Amiga Concept | Modern Equivalent | Where It Matches / Differs |
|---|---|---|
Bitmap .font file + per-size directory |
Sprite sheets in game engines | Both are pre-rendered pixel grids; neither scales well |
OpenDiskFont() β SetFont() β Text() |
CTFontCreateWithName() β CGContextSetFont() β CTLineDraw() |
Same three-step pattern; modern APIs handle scaling transparently |
AvailFonts() enumeration |
NSFontManager.availableFonts / DirectWrite IDWriteFontCollection |
Same concept β enumerate what's installed |
| Algorithmic bold/italic | NSFontManager.convertWeight(_:of:) |
Amiga does pixel smearing/shearing; modern does weighted stroke |
FONTS: assign |
$XDG_DATA_DIRS/fonts / Windows C:\Windows\Fonts |
Same multi-path search concept |
| Compugraphic outline fonts | TrueType (Apple/Microsoft, 1991) | Both are BΓ©zier outline formats; CG predates TrueType |
Decision Guide β Bitmap vs Outline Fonts on Amiga
flowchart TD
A["Need a font for<br/>your application?"] --> B{"Target OS version?"}
B -->|"1.x"| C["β
Bitmap only<br/>OpenDiskFont()"]
B -->|"2.x+"| D{"Font quality<br/>critical?"}
B -->|"3.x+"| D
D -->|"Yes β DTP, word processor"| E{"CPU?"}
D -->|"No β UI, debug, utility"| F["β
Bitmap font<br/>fast, cheap, reliable"]
E -->|"68020+"| G["Outline font viable<br/>(bullet.library)"]
E -->|"68000"| H["β οΈ Outline too slow<br/>Use designed bitmap sizes"]
style C fill:#e8f5e9,stroke:#4caf50
style F fill:#e8f5e9,stroke:#4caf50
style G fill:#fff9c4,stroke:#f9a825
Best Practices
- Always check
OpenDiskFont()return value β the font might not be installed on the user's system; fall back to topaz - Use
FPF_DESIGNEDsizes β auto-scaled (AFF_SCALED) fonts look jagged; prefer hand-designed bitmap sizes - Close fonts when done β
CloseFont()decrements the accessor count; leaking fonts wastes Chip RAM - Cache opened fonts β opening the same font repeatedly reads from disk each time; keep a pointer if you'll use it again
- Respect the user's font preference β read
GetPrefs()and use the system font for UI elements - Use topaz for debug/development output β no disk dependency, always 8 or 9 pixels, predictable width
- Don't mix bitmap and outline font APIs β
OpenFont()andOpenDiskFont()return the sameTextFont*type, but outline fonts interact withbullet.libraryinternally
Antipatterns
| Antipattern | Why It's Wrong | Correct Approach |
|---|---|---|
| The Hardcoded Helvetica | Assuming "helvetica.font/14" exists β NULL on minimal Workbench installs | Always fall back to topaz if OpenDiskFont() returns NULL |
| The Leaked Accessor | Calling OpenDiskFont() in a loop without CloseFont() β font never freed |
Pair every OpenDiskFont() with a CloseFont() |
| The AFF_SCALED Surprise | Using AvailFonts() without checking AFF_SCALED flag β user picks a blurry scaled size |
Filter out or visually flag AFF_SCALED entries in font pickers |
| The Baseline Mishandling | Move(rp, x, y) without adding font->tf_Baseline β text renders at the wrong vertical position |
Always: Move(rp, x, y + font->tf_Baseline) |
| The Missing FONTS: Assign | Relying on FONTS: being available on a minimal boot β OpenDiskFont() fails silently |
Verify FONTS: assign exists, or open from an explicit path |
Pitfalls
1. AvailFonts() Buffer Management
Bad β single-shot allocation, might overflow:
APTR buf = AllocMem(4096, MEMF_ANY);
AvailFonts(buf, 4096, AFF_DISK); /* may return shortfall > 0 β data truncated! */
Good β retry loop until buffer is large enough:
LONG size = 4096;
struct AvailFontsHeader *afh = NULL;
LONG shortfall;
do {
if (afh) { FreeMem(afh, size); size += shortfall; }
afh = AllocMem(size, MEMF_ANY | MEMF_CLEAR);
} while ((shortfall = AvailFonts((STRPTR)afh, size, AFF_DISK | AFF_MEMORY)) > 0);
2. Font Name Includes .font Suffix
OpenDiskFont() expects the full filename including the .font extension:
/* WRONG: */
struct TextAttr ta = {"helvetica", 14, 0, 0};
OpenDiskFont(&ta); /* β NULL */
/* CORRECT: */
struct TextAttr ta = {"helvetica.font", 14, 0, 0};
OpenDiskFont(&ta); /* β works */
3. DiskFont Must Come from OpenDiskFont(), Not OpenFont()
OpenFont() searches only already-loaded (ROM/memory) fonts. OpenDiskFont() triggers the disk search pipeline:
/* WRONG for disk fonts: */
struct TextFont *f = OpenFont(&ta); /* only finds ROM fonts! */
/* CORRECT: */
struct TextFont *f = OpenDiskFont(&ta); /* searches FONTS: on disk */
4. Font Not Found After Installation Without Restart
Adding fonts via Assign FONTS: NewPath: ADD takes effect immediately. But fonts are cached after first load β if a font was previously opened and is still in memory, the new version won't be seen until the old one is CloseFont()'d by all users.
References
NDK Headers
libraries/diskfont.hβFontContentsHeader,FontContents,DiskFontHeader,AvailFontsHeadergraphics/text.hβTextFont,TextAttr,ColorTextFont, style/flags constantspreferences.hβstruct Preferences(font preference fields)
ADCD 2.1 / ROM Kernel Manual
- Libraries Manual β Chapter 29: "Graphics Library and Text" β section "Composition of a Bitmap Font on Disk"
diskfont.libraryAutodocs βOpenDiskFont(),AvailFonts()
External References
- Andrew Graham's Amiga Bitmap Fonts series β Deep dive into .font and descriptor file binary format:
- Part 1: Introduction
- Part 2: The Font Contents File
- Part 3: The Font Descriptor File
- smugpie/amiga-bitmap-font-tools β Node.js tools for reading/extracting Amiga bitmap fonts: https://github.com/smugpie/amiga-bitmap-font-tools
- Cloanto Personal Fonts Maker β The definitive Amiga bitmap font editor
- AmigaOS Manual: Workbench Fonts β Official font installation guide: https://wiki.amigaos.net/wiki/AmigaOS_Manual:_Workbench_Fonts
Cross-References in This Knowledge Base
- text_fonts.md β
TextFontstructure, rendering withText()/SetFont(), algorithmic styles, font preferences - rastport.md β RastPort text rendering context, pen position, drawing mode
- intuition_base.md β Screen font handling in Intuition
- preferences / GetPrefs() β Reading user font preferences