qr-font: a TrueType font that renders bracketed text as QR codes
A QR code generator in a TrueType font: https://qr.jim.sh/
At a glance
- What is it?
- Jim Paris's qr-font generates an OpenType font where text inside square brackets becomes a QR symbol while the rest of the line stays readable. It is a proof of concept with hard limits on character count and shaping support.
- Who is it for?
- Adopt qr-font if you want a self-contained, offline QR symbol inside running text and your renderer applies GSUB features; the 1-L font covers 17 printable ASCII characters, so short codes and labels are the realistic target. Do not adopt it if you need arbitrary URLs, non-ASCII payloads, or output in an application that does not shape OpenType features.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 107 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 12, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem qr-font targets: a QR symbol that sits inside a sentence
Most QR generators produce an image. You get a PNG or an SVG, you place it next to your text, and the two live in separate boxes. qr-font takes the opposite route: the QR symbol is a glyph sequence in a font, so it flows with the paragraph. The README describes the goal as turning "bracket-delimited text into a QR Code symbol while leaving surrounding text readable", and gives the example `abc[hello]ghi`. The intended audience is narrow: people embedding short codes in documents, labels or web pages where an inline symbol is more convenient than a positioned image, and who can accept printable ASCII payloads of a few dozen characters. It is explicitly labelled a proof of concept, not a production barcode library.
How the generator builds glyphs, GSUB logic and Reed-Solomon parity
The fonts are generated rather than hand-authored, and this is the central design decision. According to the README, the build script emits glyph outlines and GSUB feature logic, then compiles them into `dist/qrfont-*.ttf`. The default build compiles five stages: the delimiter parser, byte expansion, the Reed-Solomon parity circuit, QR module placement, and fixed mask rendering. The result is a font whose contextual lookups decide, character by character, whether the current input is inside or outside a bracket pair.
Three font variants exist, and the difference is capacity. `qrfont-1L.ttf` is 21x21 modules and holds up to 17 characters; `qrfont-2L.ttf` is 25x25 and holds up to 32; `qrfont-3L.ttf` is 29x29 and holds up to 53. All three use byte mode, printable ASCII input, a fixed mask pattern 0, and `[` and `]` as delimiters. Printable ASCII glyphs are copied from Liberation Sans Regular and scaled into the QR Font em square, so text outside bracketed blocks renders as ordinary text in the same font. Because Liberation is a reserved font name under the source font licence, the generated families are named QR Font 1-L, QR Font 2-L and QR Font 3-L.
Building qr-font and typing your first bracketed code
The repository uses `uv` for Python dependency management, and the README gives `make` as the primary build command. The Makefile builds three TTF files plus a demo page, and it exports `UV_CACHE_DIR := .uv-cache` so the cache stays inside the project directory.
makeThat default path is the full Reed-Solomon build. The README notes it emits thousands of contextual lookups and usually takes noticeably longer than a layout-only build. If you only want to check layout, there is a faster route with placeholder zero parity:
make fast-placeholderThe generator reads Liberation Sans Regular from a fixed system path by default, and the README shows how to point it at another compatible TrueType source:
uv run tools/build_font.py --base-font /path/to/BaseFont-Regular.ttfBuild outputs are `dist/qrfont-*.ttf`, `dist/index.html` and the generated feature files under `build/qrfont-*.fea`. Open `dist/index.html` in a browser and type bracketed text such as `[hello]`; mixed input like `abc[def]ghi` should render as normal text, then a QR code for `def`, then normal text. To inspect what the shaper is doing, the README documents a debug script that takes several bracketed arguments:
uv run tools/shape_debug.py '[a]' '[b]'If you want the generated font files without building anything, the README links prebuilt downloads for all three sizes from the latest GitHub release.
The shaping requirement and the character ceiling are real constraints
Two limitations decide whether qr-font is usable for you. The first is that it relies on OpenType shaping. The README states plainly that the font "needs an environment that applies GSUB features". A text engine that ignores those features will draw the raw bracket characters and the payload as ordinary glyphs, which is a silent failure: no error, just a string of letters where a QR symbol should be. Any workflow that flattens text before rendering, or that rasterises with a shaping-blind library, is the wrong place for this font.
The second is capacity. Inputs inside a QR block are bounded to printable ASCII, up to 17, 32 or 53 characters depending on the selected font version. A typical URL with a query string will not fit in the 1-L font, and even the 3-L ceiling of 53 characters rules out long payloads. Byte mode with fixed mask pattern 0 also means the generator has already decided how the symbol is encoded; there is no option in the README to pick a different mask or an error-correction level. If your payload is not printable ASCII, this is the wrong tool.
How qr-font differs from image-producing QR generators
The obvious alternative is a conventional QR library that returns an image or a matrix, such as the widely used Python `qrcode` package or a JavaScript equivalent. The difference in approach is not cosmetic. An image generator gives you a bitmap or vector you position yourself, and it can encode arbitrary bytes, including UTF-8 text and binary payloads, with configurable error correction and mask selection. qr-font gives you inline text flow and no positioning work, but caps the payload at printable ASCII and fixes the encoding choices.
That trade-off is why the two tools answer different questions. If you need a QR code for a long URL, an image generator wins on the first requirement. If you need a short code to appear mid-sentence in a document that is already being shaped by a font engine, an image generator forces you into layout work that qr-font removes entirely. The repository's own framing supports this reading: it is a proof of concept, and the README does not present it as a replacement for a barcode library.
Maintenance, licence and the cost of regenerating fonts
The repository is not archived, and the last push was on 2026-06-28, which is recent enough that the project has not gone quiet. Release v1.0.0 carries the same date. There is a single runtime dependency, `fonttools>=4.57.0`, with `pillow` and `uharfbuzz` in a dev group, so the dependency surface is small and the upgrade cost is mostly about fonttools version drift. Python 3.11 or newer is required.
The licence situation needs care. The repository's licence field is NOASSERTION, but the README states that the generated font is a Modified Version of Liberation Sans Regular and is licensed under the SIL Open Font License, Version 1.1, pointing at `LICENSE-OFL.txt` and `NOTICE.md`. That is why the generated families avoid the reserved name Liberation. If you redistribute a generated font, the OFL notice files are the ones to carry along. This is a description of what the repository says, not legal advice; read the notice files yourself before shipping.
Editorial conclusion
Adopt qr-font if you want a self-contained, offline QR symbol inside running text and your renderer applies GSUB features; the 1-L font covers 17 printable ASCII characters, so short codes and labels are the realistic target. Do not adopt it if you need arbitrary URLs, non-ASCII payloads, or output in an application that does not shape OpenType features. Before committing, verify in your actual target application that a bracketed string shapes into a scannable symbol, and check the OFL notice files because the generated families are Modified Versions of Liberation Sans Regular.
Frequently asked questions
What format is best for a QR code?
qr-font only emits TrueType font files, so within this project the format is a TTF containing a generated OpenType font with GSUB logic. The README does not compare it against image formats such as PNG or SVG.
How to make a QR code text?
With qr-font you write the payload between square brackets, for example [hello], and the font renders that run as a QR symbol. Surrounding text stays readable, so abc[def]ghi renders as text, then a QR code for def, then text.
Where can I download a QR code font for Excel?
The README links prebuilt TTF downloads for the 1-L, 2-L and 3-L fonts from the latest GitHub release, and the build produces dist/qrfont-*.ttf. The README does not mention Excel, so whether those fonts shape correctly in Excel is not documented.
Is there a barcode font?
qr-font is a QR code font, not a general barcode font, and the README describes it as a proof-of-concept font. It encodes printable ASCII in byte mode with a fixed mask pattern 0.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jimparis-qr-font)