Pure-Ruby TrueType / OpenType glyph rendering — a Ruby port of
libschrift.
Rendered by examples/showcase.rb: the text and non-Latin scripts by
skrift, the box-drawing of the W3C UTF-8 alignment test
by skrift-boxdrawing, the colour emoji by skrift-color, all composited onto X11 by skrift-x11.
Skrift rasterises TrueType/OpenType outlines to 8-bit anti-aliased coverage, in
pure Ruby with no native extensions. If you need performance and don't mind a C
dependency, use libschrift; if you want pure Ruby — and are happy to cache
glyphs after rendering — this is for you.
"Skrift" is Norwegian for "text" / "writing" / "scripture", a close cognate of
"Schrift" — chosen to set this apart from libschrift and leave that name free
for a direct C wrapper.
Skrift is deliberately small and opinionated (the full version lives in
skrift/README.md):
- Small code is a virtue — as long as it improves rather than hinders understanding. Every feature is weighed against its complexity cost.
- Big features belong in separate gems. The core stays a minimal rasteriser; optional capabilities are opt-in plugins that build on it.
- No platform code in the core. Rendering to 8-bit greyscale lets skrift integrate cleanly with the likes of XRender — through a thin adapter, not by pushing platform code into the library.
- Anti-aliased by default; idiomatic Ruby over micro-optimisation; low coupling without architecture acrobatics (no factories, no abstract-interface zoos).
This repository is that philosophy made concrete: a monorepo holding the core alongside the plugins and adapter it was designed to grow.
Each subdirectory is an independently publishable gem with its own
gemspec, Gemfile and test suite:
| Gem | Subdir | What it is |
|---|---|---|
skrift |
skrift/ |
The core: TTF/OTF parsing, the scanline rasteriser, FontSet, GlyphCache, cmap incl. format 14 (variation / presentation selectors). Pure Ruby, no deps. |
skrift-boxdrawing |
skrift-boxdrawing/ |
Crisp Unicode box-drawing glyphs (U+2500–257F) and the full block █ as Images — the connecting lines and edge-to-edge fill a font breaks when scaled into a cell. Depends on skrift. |
skrift-color |
skrift-color/ |
Colour-glyph (emoji) rendering — COLR/CPAL v0 + CBDT/CBLC — to an RGBA image. Depends on skrift. |
skrift-x11 |
skrift-x11/ |
Thin XRender adapter: skrift Images → X11 glyph sets. Depends on skrift, skrift-boxdrawing, pure-x11; uses skrift-color when colour is requested. |
Consumers such as ruby-term live in their own repositories.
These gems change in lockstep often — a single feature regularly touches the core, an adapter and a plugin at once. The monorepo gives atomic cross-gem commits and one test gate, while each gem keeps its own gemspec so it still publishes independently.
Each gem's Gemfile pulls its siblings from the monorepo with a git do … end
block (so Bundler finds each gemspec in its subdir). To work against your local
checkout instead of github, set one Bundler local override at the repo
root — once, globally:
bundle config set --global disable_local_branch_check true
bundle config set --global local.skrift "$PWD" # run from the repo rootThat single override redirects the whole skrift.git source to this checkout,
for every gem and for downstream consumers (ruby-term, …) alike.
Published dependencies are declared as version constraints in each
*.gemspec — never path:/git: — so installing any gem from RubyGems
resolves its siblings correctly.
Aggregate rake tasks at the repo root operate over every gem in dependency order:
rake test # run every gem's suite
rake build # build every gem into pkg/
rake publish # build + push every gem to RubyGems
rake build:skrift # …or operate on a single gem
rake publish:skrift-x11ISC, the same permissive license as libschrift. See each gem's LICENSE.txt.