diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e8afdb..6a22de0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +> The release tag (v0.2.0) is **deferred** until the Asteroid TUI demo (#E, draft +> PR [#26](https://github.com/jowch/TextMeasure.jl/pull/26)) lands; the work below +> stays under `[Unreleased]` until then. + ### Added +#### Engine + - `subprep(prep, r)` + `Prepared(; segments, metrics)` kwargs constructor: slice a `Prepared` over a segment sub-range, reusing measured widths (no re-measurement). - `FigletBackend`: measurement backend for FIGlet ASCII-art fonts, shipped as a weakdep @@ -31,4 +37,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 producing aligned lines and overall block extent. - `line_top(lay, ln)`: top-left y of a laid-out line (block top = 0). +#### Examples / demos + +A gallery of measurement-driven layout demos under [`examples/`](examples/) (indexed by +[`examples/README.md`](examples/README.md)), each a self-contained Julia project: + +- **`examples/layouts`** — `TextMeasureLayouts`: shared `shape_pack` shape-conforming text + packing (#C) with multi-interval per-band packing (#C2, unblocks two-sided wrap), plus the + stretch `knuth_plass` / `greedy_justify` justification utilities (#K). +- **`examples/silhouettes`** — `Silhouettes` (#D): procedural asteroid polygons, Voronoi + shatter, and rasterization built on `DelaunayTriangulation`/`GeometryOps`. +- **`examples/doi_infograph`** — DOIInfograph (#F): adaptive, measurement-driven + academic-paper infographic generator; the README hero is a 6-up grid of six papers composed + by one template (offline from a committed API cache). +- **`examples/map_feature`** — MapFeature (#G): a CairoMakie state map-feature page with + editorial prose wrapping around the silhouette as an irregular obstacle (Vermont, offline). +- **`examples/cover`** — Cover (#H): the "Newer Yorker" correctness exhibit — a vector-PDF + editorial cover whose every offset is measurement-derived (no manual offsets). +- **`examples/justification`** — a greedy-vs-Knuth–Plass justification comparison exhibit + with river detection (#K). + +In progress: the **Asteroid TUI** demo (#E) — draft PR +[#26](https://github.com/jowch/TextMeasure.jl/pull/26), not yet on `main`. + [Unreleased]: https://github.com/jowch/TextMeasure.jl/tree/main diff --git a/README.md b/README.md index 60e08da..aac9e68 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,27 @@ end Backends: `MonospaceBackend` (zero-dep, built in), `FreeTypeBackend` (`using FreeTypeAbstraction`), `MakieBackend` (`using Makie`; measurements match -Makie's `text!` at `px_per_unit = 1`). +Makie's `text!` at `px_per_unit = 1`), and `FigletBackend` (`using FIGlet`; install +via `Pkg.add("FIGlet")`) — which measures in **character cells** for FIGlet ASCII-art +fonts rather than pixels. **Not in scope:** rendering, repel/treemap/annotation consumers (downstream), UAX-#14 line-breaking, CJK, hyphenation, justification, rotation. + +## Demos / Gallery + +The [`examples/`](examples/) directory is a gallery of measurement-driven layout demos +built on this engine — editorial covers, map feature pages, justification comparisons, +shape-conforming text packing, and an adaptive academic-paper infographic. See +**[examples/README.md](examples/README.md)** for the full index with screenshots and +run instructions for each. + +The hero is the **DOIInfograph 6-up grid** (`examples/doi_infograph/`): six very +different papers — short and 125-char titles, 8 to 446 authors, with and without +abstracts — all composed by the *same* measurement-driven template. That uniformity +is the proof of adaptiveness. + +[![DOIInfograph 6-up grid](examples/doi_infograph/assets/grid_hero.png)](examples/doi_infograph/assets/grid_hero.pdf) + +GitHub shrinks the PNG above; for per-panel detail open the high-resolution vector +composite (selectable text): **[`grid_hero.pdf`](examples/doi_infograph/assets/grid_hero.pdf)**. diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..4ff0a32 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,141 @@ + +# TextMeasure.jl — demo gallery + +A gallery of **measurement-driven layout** demos built on +[TextMeasure.jl](../README.md): editorial covers, a map feature page, a justification +comparison, shape-conforming text packing, and an adaptive academic-paper infographic. +Each demo is a self-contained Julia project under `examples//` with its own +`Project.toml` and `README.md`. + +## Running a demo + +Every demo activates its own environment and develops the in-repo `TextMeasure` +(and, where used, `TextMeasureLayouts`) packages — they are not registered, so they +must be `dev`-ed from this repo before instantiating: + +```bash +# from the repo root — sets up examples/'s environment +julia --project=examples/ -e 'using Pkg; Pkg.develop([PackageSpec(path="."), PackageSpec(path="examples/layouts")]); Pkg.instantiate()' +``` + +(`examples/layouts` and `examples/silhouettes` are library-only and depend on +`TextMeasure` alone, so `Pkg.develop(path=".")` suffices for them.) Each demo's own +`README.md` has the exact run command; the per-demo entries below summarize them. + +--- + +## DOIInfograph — adaptive academic-paper infographic (#F) + +[![DOIInfograph 6-up grid](doi_infograph/assets/grid_hero.png)](doi_infograph/assets/grid_hero.pdf) + +Give it a DOI; it fetches the metadata and *measures* its way to a composed editorial +cover — the title autoshrinks, a long author list collapses to "et al.", the abstract +drop-caps and wraps around a figure pillar, concept pills wrap into a strip. The hero is +a **6-up grid of six very different papers** (short and 125-char titles, 8 to 446 authors, +with and without abstracts), all composed by the *same* template — that uniformity is the +proof of adaptiveness. Runs fully offline from a committed API cache. + +GitHub shrinks the PNG; open the high-resolution vector composite for per-panel detail: +**[`grid_hero.pdf`](doi_infograph/assets/grid_hero.pdf)**. + +```bash +julia --project=examples/doi_infograph -e 'using Pkg; Pkg.develop([PackageSpec(path="."), PackageSpec(path="examples/layouts")]); Pkg.instantiate()' +julia --project=examples/doi_infograph examples/doi_infograph/render_hero.jl # regenerates the hero +``` + +→ [`doi_infograph/README.md`](doi_infograph/README.md) + +--- + +## Cover — the "Newer Yorker" correctness exhibit (#H) + +![Cover demo](cover/assets/showcase.png) + +A hand-set editorial cover rendered to a **vector PDF** with CairoMakie: display title, +drop cap, body text flowing around an SVG illustration inset on **both** sides, and a +pull-quote callout. Its job is to prove correctness — the honest acceptance test is +*"no manual offsets"*: move the inset and re-render, and every other element re-aligns +because every offset is measurement-derived. + +```bash +julia --project=examples/cover -e 'using Pkg; Pkg.develop([PackageSpec(path="."), PackageSpec(path="examples/layouts")]); Pkg.instantiate()' +julia --project=examples/cover examples/cover/render.jl examples/cover/data/cover-v1.toml /tmp/cover-v1.pdf +``` + +→ [`cover/README.md`](cover/README.md) + +--- + +## MapFeature — state map-feature page (#G) + +![MapFeature demo (Vermont)](map_feature/assets/showcase.png) + +A US-state silhouette rendered as a cartographic map (capital, cities, landmarks, natural +features) with **editorial prose that wraps around the silhouette as an irregular +obstacle** — the *Dynamic Layout* pattern applied to real geography. Vermont renders +entirely from a bundled ≈26 KB shapefile and bundled POIs — no network. + +```bash +julia --project=examples/map_feature -e 'using Pkg; Pkg.develop([PackageSpec(path="."), PackageSpec(path="examples/layouts")]); Pkg.instantiate()' +julia --project=examples/map_feature examples/map_feature/render_vermont.jl # writes vermont.png + vermont.pdf +``` + +→ [`map_feature/README.md`](map_feature/README.md) + +--- + +## Justification — greedy vs. Knuth–Plass (#K, stretch) + +![Justification comparison](justification/assets/showcase.png) + +The **same paragraph** set three ways — wide greedy, narrow greedy, and narrow +Knuth–Plass — so the cost of greedy line-breaking is visible next to badness-minimized +breaks. A *river* (overlaid in red) is a run of inter-word gaps aligned across ≥3 lines; +at a tight measure greedy pools them and K-P breaks them up at roughly half the badness. + +```bash +julia --project=examples/justification -e 'using Pkg; Pkg.develop([PackageSpec(path="."), PackageSpec(path="examples/layouts")]); Pkg.instantiate()' +julia --project=examples/justification examples/justification/demo.jl # → comparison.pdf +``` + +→ [`justification/README.md`](justification/README.md) + +--- + +## TextMeasureLayouts — shared layout utilities (#C / #C2 / #K) + +*Library, no standalone render.* Houses `shape_pack` (shape-conforming text packing into +the intervals returned by a `chord_fn`, with multi-interval per-band packing for two-sided +wrap) and the stretch `knuth_plass` / `greedy_justify` justification utilities. Consumed by +the cover, map-feature, doi-infograph, and justification demos via `Pkg.develop`. + +```bash +julia --project=examples/layouts -e 'using Pkg; Pkg.develop(path="."); Pkg.instantiate()' +julia --project=examples/layouts examples/layouts/test/runtests.jl +``` + +→ [`layouts/README.md`](layouts/README.md) + +--- + +## Silhouettes — procedural 2-D shapes (#D) + +*Library, no standalone render.* Procedural asteroid silhouettes (polar Perlin noise), +Voronoi shatter (`DelaunayTriangulation` + Sutherland–Hodgman clip), and rasterization to +a `BitMatrix` matching `shape_pack`'s `raster_chord_fn` convention. Built for the Asteroid +TUI demo (#E). + +```bash +julia --project=examples/silhouettes -e 'using Pkg; Pkg.develop(path="."); Pkg.instantiate(); Pkg.test()' +``` + +→ [`silhouettes/README.md`](silhouettes/README.md) + +--- + +## Asteroid TUI (#E) — 🚧 work in progress + +An interactive terminal demo driving `Silhouettes` + `shape_pack` (text packed into a +fracturing asteroid). **Not yet on `main`** — tracked in draft PR +[#26](https://github.com/jowch/TextMeasure.jl/pull/26). No gallery image yet; its assets +aren't committed. diff --git a/examples/cover/assets/showcase.png b/examples/cover/assets/showcase.png new file mode 100644 index 0000000..3342b59 Binary files /dev/null and b/examples/cover/assets/showcase.png differ diff --git a/examples/justification/assets/showcase.png b/examples/justification/assets/showcase.png new file mode 100644 index 0000000..abbb905 Binary files /dev/null and b/examples/justification/assets/showcase.png differ diff --git a/examples/map_feature/assets/showcase.png b/examples/map_feature/assets/showcase.png new file mode 100644 index 0000000..f81bc9f Binary files /dev/null and b/examples/map_feature/assets/showcase.png differ