Skrift
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.
Philosophy
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.
The gems
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.
Why a monorepo
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.
Development
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.
Tasks
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-x11License
ISC, the same permissive license as libschrift. See each gem's LICENSE.txt.
