3 unstable releases
Uses new Rust 2024
| 0.2.1 | Apr 30, 2026 |
|---|---|
| 0.2.0 | Apr 29, 2026 |
| 0.1.0 | Apr 29, 2026 |
#125 in Visualization
Used in 2 crates
5.5MB
193K
SLoC
BLAND
Pure-Rust library for paper-ready, monochrome, hatch-patterned technical plots in the visual tradition of 1960s–80s engineering reports.
BLAND emits SVG. Plots look at home next to a title block, a set of fastener callouts, and a stack of punched cards — black ink on white paper, serif type, thin rules, hatched fills. No color, no gradients, no drop shadows.
use bland::{Figure, PaperSize, Stroke, TitleBlock};
let xs: Vec<f64> = (0..=200).map(|i| i as f64 / 20.0).collect();
let response: Vec<f64> = xs.iter().map(|t| (-t / 4.0).exp() * t.cos()).collect();
let envelope: Vec<f64> = xs.iter().map(|t| (-t / 4.0).exp()).collect();
let fig = Figure::new()
.size(PaperSize::A5Landscape)
.title("Damped oscillation")
.xlabel("t [s]")
.ylabel("x(t)")
.line(&xs, &response, |s| s.label("response"))
.line(&xs, &envelope, |s| s.label("envelope").stroke(Stroke::Dashed))
.hline(0.0, |s| s.stroke(Stroke::Dotted))
.legend_top_right()
.title_block(
TitleBlock::new()
.project("BLAND Reference")
.title("Fig. 1 · Damped oscillation")
.drawn_by("JM")
.date("2026-04-21")
.scale("1:1")
.sheet("1 of 1")
.rev("A"),
);
std::fs::write("oscillation.svg", fig.to_svg()).unwrap();
See the docs.rs page for embedded example images of every plot type.
Why monochrome?
- Prints clean. Plots look the same on a laser printer, a color printer, and a photocopy. No "figure unreadable in proceedings" surprises.
- Accessible by default. Hatching, stroke dashing, and marker shape distinguish series — so plots survive grayscale rendering and are legible to readers with color vision deficiency.
Features
- Series: line, scatter, bar (grouped), area, histogram, heatmap, polygon, error bars, box plots, stem plots, quiver / vector fields, contour iso-lines, reference rules
- Hatch patterns: 13 presets — diagonals, crosshatch, dots, brick, zigzag, checker
- Markers: 12 shape presets, alternating open / filled
- Stroke dashes: solid, dashed, dotted, dash-dot, long-dash, fine
- Paper presets: A4, A5, Letter, Legal, Square — portrait & landscape
- Themes:
report_1972(serif),blueprint(monospace),gazette(newspaper) - Engineering title block with project / drawn-by / date / scale / sheet / revision
- Annotations: in-data text and arrows with anti-overlap halos
- Linear and log axes with nice-rounded tick placement
- Projections: polar, Smith chart, Mercator, equirectangular
- Built-in basemaps: Earth coastlines & borders (Natural Earth 1:110m, optional 1:50m), reference parallels, lunar maria
- Multi-panel layouts and composite helpers (Bode, Q-Q)
- Pure Rust, zero runtime dependencies
Cargo features
gui— addsFigure::show(): a matplotlib-style blocking display window that renders the figure in an OS-native webview, with a Save SVG button and zoom controls. Pulls intaoandwry. On Linux you must havelibwebkit2gtk-4.1-devinstalled system-wide.high-res-basemaps— adds Natural Earth 1:50m coastline and country data (~3 MB compiled). Off by default; the 1:110m datasets and the schematic outlines are always available.regen-basemaps— builds the dev-onlyregen_basemapsbinary that re-converts Natural Earth GeoJSON into the static Rust data modules. Off by default socargo install blanddoes not install a developer tool.
Quick GUI usage
use bland::{Figure, PaperSize};
# fn main() {
let xs: Vec<f64> = (0..=100).map(|i| i as f64 / 10.0).collect();
let ys: Vec<f64> = xs.iter().map(|t| t.sin()).collect();
Figure::new()
.size(PaperSize::A5Landscape)
.title("sin(t)")
.line(&xs, &ys, |s| s)
.show(); // blocks until the window is closed
# }
Run the bundled demo with:
cargo run --features gui --example show_demo
Examples
The repo ships 22 runnable examples covering every plot type. Run any of them via:
cargo run --example damped_oscillation
cargo run --example world_map
cargo run --example smith
Output goes to out/.
License
MIT.
This crate ports the Elixir BLAND library; the Natural Earth data
embedded under src/basemaps/data/ is in the public domain.
Dependencies
~0–43MB
~539K SLoC