9.7 KiB
ADA §703 Font Compliance Analyzer — CoWork Context
Tool file: ada-font-analyzer.html
Version: 1.0
Status: Active
Owner: Bryan Gilliom — Message Point Media
Built in: claude.ai (May 2026)
Adoption target: CoWork (CoWork session should register this as a Tool-type project in the Project Registry)
Purpose
Standalone browser-based tool for MPM's design and content team. Evaluates fonts against the 2010 ADA Standards for Accessible Design, Chapter 7 (Signs), Section §703.5 — the governing standard for digital signage character legibility. Used to select and validate fonts before deploying to the ~2,000-display RDMC/OnSign.tv installed base.
This tool lives in the MPM Odoo Knowledge base, embedded via iframe in the ADA Signage Guidelines article at https://portal.mpmedia.tv/knowledge/article/4638.
What the Tool Does
Three tabs, all self-contained in a single HTML file. No backend. No API keys. No dependencies. Runs entirely in the browser.
Tab 1 — Browse Curated Fonts
- 25 hand-curated Google Fonts pre-evaluated against all five §703.5 criteria
- Filter by: All / Fully compliant / Transit-tested / Use with caution
- Each card shows: live font preview, compliance badge, per-criterion dot indicators, notes
- Actions per card: Select for download, View on Google Fonts (specimen page), Download TTF/OTF (GF ZIP endpoint)
- Sidebar: selected font list with per-item download/specimen links, "Download all selected" bulk action (opens GF ZIP per family with stagger)
Tab 2 — Test a Google Font
- User types any Google Fonts family name; tool loads it via the CSS2 API
- Renders uppercase I and O to a hidden HTML5 canvas at 120px
- Pixel-scans bounding boxes to derive O:I proportion ratio and stroke-to-height ratio
- Scores against all five §703.5 criteria; shows pass/fail per criterion with measured values
- Weight selector (100–900) — re-scores live when weight changes
- Light-on-dark preview panel for contrast testing
- Download link to Google Fonts ZIP for the tested family
- "Add to selected fonts" button carries result back to Tab 1 sidebar
Tab 3 — Upload TTF / OTF File
- Drag-and-drop or file picker; accepts TTF, OTF, WOFF, WOFF2
- For TTF/OTF: parses the binary font file directly using a custom JS DataView parser — no library
- For WOFF/WOFF2: falls back to canvas-only measurement (WOFF decompression not implemented)
- Live preview rendered via FontFace API + blob URL
- Raw metrics table showing exact values from each font table, with source attribution (TTF table vs. canvas)
- Full §703.5 scoring identical to Tab 2 but using higher-accuracy table-derived measurements
ADA §703.5 Criteria Implemented
| Criterion | Standard ref | How measured |
|---|---|---|
| Sans-serif, conventional form | §703.5.3 | Name heuristics + OS/2 panose bFamilyType + fsSelection |
| O:I width ratio 55–110% | §703.5.4 | Canvas: rendered pixel widths. TTF: hmtx advance widths ÷ sCapHeight |
| Stroke weight 10–30% of height | §703.5.7 | Canvas: thinnest ink row scan. TTF: usWeightClass → stroke % mapping |
| Character spacing 10–35% | §703.5.8 | Condensed-variant name detection |
| No italic/script/decorative | §703.5.3 | fsSelection italic/oblique bits + panose family type + name table |
TTF Binary Parser — Tables Read
The Tab 3 parser (parseTTF() function) reads these tables directly from the binary:
| Table | Fields extracted |
|---|---|
head |
unitsPerEm |
OS/2 |
usWeightClass, fsSelection, panose[10], sCapHeight (ver≥2) |
hhea |
ascender, lineGap |
cmap |
Format 4 Unicode map → glyph IDs for U+0049 (I) and U+004F (O) |
hmtx |
Advance widths for glyphs I and O |
name |
nameID=1 (family name), nameID=2 (subfamily) — both platform 3 (UTF-16BE) and platform 1 |
Parser is pure JS, self-contained in the HTML file. No external libraries.
Architecture Decisions
Single-file, no build step. Everything — HTML, CSS, JS, data, parser — is in one ada-font-analyzer.html file. This is intentional: Odoo Knowledge iframe embedding requires a stable hosted URL to a single file. No bundler, no node_modules, no deployment pipeline needed.
Google Fonts CSS2 API for preview loading. Tab 2 loads fonts via https://fonts.googleapis.com/css2?family=...&display=swap. No API key required. The Google Fonts download ZIP endpoint (https://fonts.google.com/download?family=...) is used for all download links — same endpoint GF's own website uses.
Canvas measurement accuracy. ~±5%. Sufficient for screening; not appropriate as a final compliance certification for permanent physical signage. This is documented in the UI.
TTF parser accuracy. O:I ratio from hmtx is exact (within font-unit precision). Stroke weight from usWeightClass is a model-based estimate (±2-3%). Canvas pixel scan runs as a cross-check and both values are shown.
No localStorage, no cookies, no external requests except Google Fonts. Tool is privacy-safe for Odoo embedding.
Curated Font List — Maintenance Notes
The 25 curated fonts are defined in the FONTS array in the JavaScript. Each entry:
{
name: "Font Name", // Display name — must match Google Fonts exactly for GF links
style: "Humanist", // Typographic classification
cat: "Description", // Short category label shown on card
tags: ["best","transit"], // Filter tags: "best"=fully compliant, "transit"=transit-tested, "caution"=use with caution
compliance: { // Per-criterion pass/fail (drives dot indicators and badge)
style: true,
proportion: true,
stroke: true,
spacing: true,
form: true
},
notes: "...", // Notes shown on card — weight restrictions, O:I ratio, etc.
gf: "Font+Name" // URL-encoded family name for Google Fonts API/download links
}
To add a font: append an entry to the FONTS array. Use Tab 2 or Tab 3 to measure it first.
To update compliance data: edit the compliance object and notes string for that entry.
Transit-tested badge: assigned to fonts with known real-world deployment in public transit signage systems (Roboto, Open Sans, Inter, Work Sans, Noto Sans, Atkinson Hyperlegible, Montserrat). Not a formal certification — update based on documented deployments.
Known Limitations & Planned Improvements
| Item | Notes |
|---|---|
| WOFF/WOFF2 binary parsing | Not implemented — requires inflate/brotli decompression. Falls back to canvas. Future: add pako.js for WOFF2 support. |
| Google Fonts full catalog scan | The 25 curated fonts are a hand-selected subset of ~1,500+ GF fonts. A full programmatic scan would require the Google Fonts Developer API key + font file metric extraction pipeline. Candidate for a separate CoWork tool. |
| Line spacing check (§703.5.9) | Not currently measured. Requires rendering multi-line text and measuring baseline-to-baseline distance. Planned. |
| Weight-specific compliance | Currently the compliance object reflects worst-case (light weights). Could be enhanced to show per-weight compliance table. |
| OTF CFF table support | The TTF parser reads hmtx/cmap which also exist in OTF. CFF-flavored OTFs (PostScript outlines) may have glyph metrics in the CFF table instead — parser falls back to canvas gracefully. |
| Odoo iframe sizing | At narrow viewport widths the two-column layout collapses to single column. Test at your iframe width. |
Embedding in Odoo Knowledge
The tool is designed to be embedded as an iframe in the ADA Signage Guidelines Knowledge article.
<iframe
src="https://git.alwisp.com/jason/ada-font-analyzer/raw/branch/main/ada-font-analyzer.html"
width="100%"
height="900px"
frameborder="0"
style="border-radius:8px;">
</iframe>
Hosting options:
- Gitea raw file URL (CoWork-native, recommended) —
https://git.alwisp.com/jason/ada-font-analyzer/raw/branch/main/ada-font-analyzer.html - MPM server / CDN static file host
- Odoo attachment with direct URL (check if Odoo serves raw attachment files)
The file has no cross-origin dependencies other than fonts.googleapis.com and fonts.gstatic.com, both of which are public CDN resources.
Session Handoff Instructions
When starting a CoWork session to maintain or extend this tool:
- Read this file first to understand scope, architecture, and current limitations
- Load the HTML file — from Gitea:
https://git.alwisp.com/jason/ada-font-analyzer/raw/branch/main/ada-font-analyzer.html - Key functions to know:
parseTTF(buffer)— binary font table parser, returns{tables, metrics, errors}canvasMeasure(fontName, weight)— canvas pixel scan, returns{oiRatio, strokePct}renderScoreUI(...)— shared scoring renderer used by both Tab 2 and Tab 3FONTS[]— curated font data arrayrenderGrid()— re-renders Tab 1 grid from current filter/search state
- Do not add external library dependencies without updating this context file
- Test all three tabs after any change — they share the canvas element and score renderer
- Update the version number in the
<title>tag and in this context file when making changes - Register this project in the CoWork Project Registry if not already done — Type: Tool, Owner: Bryan Gilliom
Change Log
| Date | Version | Change | Session |
|---|---|---|---|
| 2026-05-05 | 1.0 | Initial build — three tabs: Browse curated fonts, Test Google Font, Upload TTF/OTF. Binary TTF parser, canvas cross-check, GF download links. | claude.ai |
| 2026-05-05 | 1.0 | Registered as CW-005 in CoWork Project Registry. Gitea repo created. Drive coordination folder created. | CoWork |