<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Fonterator</title><link rel="icon" href="icon.svg"><link rel="stylesheet" href="style.css"/></head><body><div class="menu"><p><a href="https://libcala.github.io"><img src="https://libcala.github.io/logo.svg" alt="Cala" /></a><a href="https://libcala.github.io/fonterator">About</a><a href="https://github.com/libcala/fonterator">Source</a><a href="https://libcala.github.io/fonterator/changelog">Changelog</a></p>
</div><div class="content"><div class="page"><h1><a href="#fonterator" aria-hidden="true" class="anchor" id="fonterator"></a><a href="#fonterator">Fonterator</a></h1>
<p><a href="https://docs.rs/fonterator"><img src="https://docs.rs/fonterator/badge.svg" alt="docs.rs" /></a> <a href="https://travis-ci.com/libcala/fonterator"><img src="https://api.travis-ci.com/libcala/fonterator.svg?branch=master" alt="build status" /></a> <a href="https://crates.io/crates/fonterator"><img src="https://img.shields.io/crates/v/fonterator.svg" alt="crates.io" /></a> <a href="https://discord.gg/nXwF59K"><img src="https://img.shields.io/badge/discord-Cala%20Project-green.svg" alt="discord" /></a></p>
<p><a href="https://libcala.github.io/fonterator">About</a> | <a href="https://github.com/libcala/fonterator">Source</a> | <a href="https://libcala.github.io/fonterator/changelog">Changelog</a> | <a href="https://libcala.github.io">Cala Blog</a></p>
<p>Load fonts as vector graphics in pure Rust with advanced text layout. When you want to render text, fonterator gives you an iterator over <a href="https://crates.io/crates/footile">footile</a> <code>PathOp</code>s, which you can easily pass right into footile.</p>
<h1><a href="#simple-example" aria-hidden="true" class="anchor" id="simple-example"></a><a href="#simple-example">Simple Example</a></h1>
<pre lang="rust"><code>use fonterator as font; // For parsing font file.
use footile::{FillRule, Plotter, Raster, Rgba8}; // For rendering font text.
use png_pong::{RasterBuilder, EncoderBuilder}; // For saving PNG
const FONT_SIZE: f32 = 32.0;
fn main() {
// Example Text
let english = "Raster Text With Font";
let korean = "글꼴로 래스터 텍스트 사용";
let japanese = "フォント付きラスタテキスト";
// Init font, and paths.
let font = font::monospace_font();
// Init rendering.
let mut p = Plotter::new(512, 512);
let mut r = Raster::new(p.width(), p.height());
// Render English Left Aligned.
let path = font.render(
english,
(64.0, 0.0, 512.0 - 64.0, 512.0 - FONT_SIZE),
(FONT_SIZE, FONT_SIZE),
font::TextAlign::Left
);
let path: Vec<font::PathOp> = path.collect();
r.over(p.fill(&path, FillRule::NonZero), Rgba8::rgb(0, 0, 0));
// Render Korean Vertically
let path = font.render(
korean,
(0.0, 0.0, 512.0, 512.0 - 32.0 * 7.0),
(FONT_SIZE, FONT_SIZE),
font::TextAlign::Vertical
);
let path: Vec<font::PathOp> = path.collect();
r.over(p.fill(&path, FillRule::NonZero), Rgba8::rgb(0, 0, 0));
// Render Japanese Vertically
let path = font.render(
japanese,
(32.0, 0.0, 512.0, 512.0 - 32.0 * 7.0),
(FONT_SIZE, FONT_SIZE),
font::TextAlign::Vertical
);
let path: Vec<font::PathOp> = path.collect();
r.over(p.fill(&path, FillRule::NonZero), Rgba8::rgb(0, 0, 0));
// Save PNG
let raster = RasterBuilder::new()
.with_u8_buffer(512, 512, r.as_u8_slice());
let mut out_data = Vec::new();
let mut encoder = EncoderBuilder::new();
let mut encoder = encoder.encode_rasters(&mut out_data);
encoder.add_frame(&raster, 0).expect("Failed to add frame");
std::fs::write("out.png", out_data).expect("Failed to save image");
}
</code></pre>
<h2><a href="#features" aria-hidden="true" class="anchor" id="features"></a><a href="#features">Features</a></h2>
<ul>
<li>Load TTF/OTF fonts and font collections.</li>
<li>Automatic kerning and font layout.</li>
<li>Horizontal and vertical text layout.</li>
<li>Left-to-right and right-to-left text layout.</li>
<li>Use fallback fonts if a character is not available from one font.</li>
<li>Align text left/center/right/vertical</li>
<li>Line Wrapping</li>
</ul>
<h2><a href="#todo" aria-hidden="true" class="anchor" id="todo"></a><a href="#todo">TODO</a></h2>
<ul>
<li><a href="https://github.com/plopgrizzly/fonterator/issues/3">Arabic and other script text shaping</a></li>
<li>Better interoperability for monospace when mixing scripts.</li>
</ul>
<h1><a href="#contributing" aria-hidden="true" class="anchor" id="contributing"></a><a href="#contributing">Contributing</a></h1>
<p>Contributors are always welcome! Whether it is a bug report, bug fix, feature request, feature implementation or whatever. Don’t be shy about getting involved. I always make time to fix bugs, so usually a patched version of the library will be out soon after a report. Features take me longer, though. I’ll also always listen to any design critiques you have. If you have any questions you can email me at <a href="mailto:jeronlau@plopgrizzly.com">jeronlau@plopgrizzly.com</a>. Otherwise, <a href="https://github.com/libcala/fonterator/issues">here’s a link to the issues on GitHub</a>.</p>
<p>And, as always, make sure to always follow the <a href="https://github.com/libcala/fonterator/blob/master/CODEOFCONDUCT.md">code of conduct</a>. Happy coding!</p>
<h1><a href="#license" aria-hidden="true" class="anchor" id="license"></a><a href="#license">License</a></h1>
<p>This repository is licensed under either of the following:</p>
<ul>
<li>MIT License (MIT) - See accompanying file <a href="https://github.com/libcala/fonterator/blob/master/LICENSE_MIT.txt">LICENSE_MIT.txt</a> or copy at <a href="https://opensource.org/licenses/MIT">https://opensource.org/licenses/MIT</a></li>
<li>Boost Software License (BSL-1.0) - See accompanying file <a href="https://github.com/libcala/fonterator/blob/master/LICENSE_BSL.txt">LICENSE_BSL.txt</a> or copy at <a href="https://www.boost.org/LICENSE_1_0.txt">https://www.boost.org/LICENSE_1_0.txt</a></li>
</ul>
<p>at your option.</p>
<h2><a href="#contribution-licensing" aria-hidden="true" class="anchor" id="contribution-licensing"></a><a href="#contribution-licensing">Contribution Licensing</a></h2>
<p>Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above without any additional terms or conditions.</p>
</div></div></body>