Generate every distribution variant of the Ambhora brand assets
Project description
ambhora-brandkit
Generates every distribution variant of the Ambhora brand assets from the pristine sources, which are never modified.
pip install .[render]
brandkit build -o dist
No Inkscape required
The original plan was to shell out to Inkscape for everything. That turned out to be unnecessary. The work splits into four parts, and only one of them actually needs a renderer:
| Step | How it is done | Dependency |
|---|---|---|
| Recolour, recanvas, background plate | lxml tree surgery |
lxml |
| Ink bounding box (for padding) | analytic geometry, svgbbox.py |
none |
| SVG output | serialised straight from lxml | none |
| PNG and PDF output | a pluggable backend | one of three |
So SVG-only builds run with nothing but lxml. PNG and PDF need exactly one of:
cairosvg— a pip-installable library, sopip install .[render]gives a complete install with no external binaries. Writes true vector PDFs. Default.rsvg-convert— from librsvg. Excellent SVG conformance, very fast, and already present on most Linux systems and via Homebrew.inkscape— still supported. It is the slowest of the three, but it is the only backend that can measure and render live text, which makes it the right choice for thesourceset (see below).
brandkit info reports which backends are usable on the current machine, and
--engine picks one explicitly.
Why the bounding box did not need Inkscape either
Padding has to be measured from the ink, not from the page, so the one thing
genuinely worth calling inkscape --query-all for was the bounding box.
svgbbox.py computes it directly instead: Bézier segments are bounded by their
real stationary points, elliptical arcs are converted to cubics first, and
affine transforms are composed down the tree and applied to control points
before extrema are solved — which keeps the result exact under rotation and
skew. Against a 4000-point resampling of random cubics it agrees to 1.5e-5.
On the real assets it reproduces the page geometry exactly: the icon measures 1600×1600 to the last decimal.
The one thing it cannot do is measure live <text>, because that needs font
metrics and shaping. This only affects the source set. When it happens the
build says so and falls back to the document page, or you can pass
--engine inkscape on a machine with the brand font installed.
The variant matrix
Three marks × three inks × three backgrounds × three formats, minus the two illegible pairings (black on black, white on white):
| transparent | white plate | black plate | |
|---|---|---|---|
| colour | yes | yes | yes |
| white | yes | — | yes |
| black | yes | yes | — |
Seven legible combinations per mark, per padding rule, in svg, pdf and
png (at each requested raster width). With the default two padding rules and
three PNG widths that is 210 files.
Output is laid out as dist/<mark>/<format>/<name>, with self-describing
names:
dist/icon/svg/ambhora-icon-white-on-black-clearspace.svg
dist/icon/png/ambhora-icon-color-on-transparent-none-512px.png
dist/wordmark/pdf/ambhora-wordmark-black-on-white-clearspace.pdf
A dist/manifest.json records every file with its size, SHA-256, canvas
geometry and the digest of the pristine source it came from, so a build is
auditable and reproducible.
Padding
Yes, padded variants work — and they are exact, because padding is applied as
a change of window, not a transform of the artwork. The viewBox is widened
around the ink box; not a single coordinate in the drawing moves. A test
asserts this by re-measuring the ink after padding and comparing it to the
original.
Clear space is expressed as a fraction of the mark's ink height, applied equally on all four sides. Height is the right reference here because the wordmark is roughly 7:1 — a width-derived margin would swallow it, whereas a height-derived margin is how exclusion zones are specified in practice, as a multiple of the cap height.
| Rule | Margin | Use |
|---|---|---|
none |
— | Original page, framed exactly like the pristine file. Default. |
tight |
10% of ink height | App icon / favicon safe area; artwork at ~80% of canvas. |
clearspace |
25% of ink height | Minimum brand exclusion zone. Default. |
generous |
50% of ink height | Hero placements, covers, title slides. |
avatar |
10%, then squared | Profile pictures. Intended for icon; squaring the wide logo lockup leaves a lot of empty canvas. |
brandkit paddings prints this at the terminal. Select rules with repeated
--padding flags.
The share directory
The pristine assets live in share/ambhora-brandkit/{primary,source} and are
byte-for-byte identical to the originals. They install as shared data, to
<prefix>/share/ambhora-brandkit/, rather than being buried inside the Python
package — so a Makefile, a LaTeX build or a shell script can reach them just as
easily as Python can.
At runtime they are looked up in this order:
$AMBHORA_BRANDKIT_SHARE<sys.prefix>/share/ambhora-brandkit— a normal or virtualenv install<site.USER_BASE>/share/...— apip install --user/usr/local/share/...,/usr/share/...— system packagesshare/ambhora-brandkitabove the source tree — editable installs and plain checkouts, so the tool works straight from a clone
primary has all type converted to outlines and is what you should build from.
source keeps editable text and needs the ADLaM Display brand font installed
to render correctly.
Usage
brandkit info # assets, palette, backend status
brandkit list # print the variant matrix
brandkit paddings # explain the clear-space rules
brandkit build -o dist # everything
brandkit build -n # dry run, writes nothing
brandkit build --asset icon --format png --padding avatar --png-width 512
brandkit build --format svg # needs no rendering backend at all
brandkit build --engine rsvg -j 8
brandkit build --asset-set source --engine inkscape
Also available as python -m ambhora_brandkit.
Layout
pyproject.toml
share/ambhora-brandkit/ pristine assets, installed to <prefix>/share/
primary/ type outlined — build from this
source/ live text — needs the brand font
src/ambhora_brandkit/
geometry.py affine matrices, rectangles, transform parsing
svgbbox.py analytic ink bounding boxes
svgdoc.py recolour, recanvas, background plate
padding.py clear-space rules
spec.py the variant matrix and naming scheme
engines.py cairosvg / rsvg / inkscape backends
build.py planning, execution, manifest
cli.py command line interface
tests/
Licensing
The brand assets under share/ carry their original CC-BY-4.0 headers and
are unchanged. The Python code is marked MIT, since CC licences are not
intended for software — change it if you would rather it matched the assets.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ambhora_brandkit-1.0.0.tar.gz.
File metadata
- Download URL: ambhora_brandkit-1.0.0.tar.gz
- Upload date:
- Size: 148.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: Hatch/1.16.2 cpython/3.14.6 HTTPX/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d211d8414e6d69ea54598d815629c9045e2bcd7a86f2a44cbc5aed4b61ace045
|
|
| MD5 |
ea907d64ebcbb619aa4c30017fa7a4cb
|
|
| BLAKE2b-256 |
fdb59a4015ae1e905853ec4a52a2b64ef25d6d6e6b311d184fc1ce9fcd1dac73
|
File details
Details for the file ambhora_brandkit-1.0.0-py3-none-any.whl.
File metadata
- Download URL: ambhora_brandkit-1.0.0-py3-none-any.whl
- Upload date:
- Size: 150.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: Hatch/1.16.2 cpython/3.14.6 HTTPX/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aad27e4b499e9678ef61cbfb7fd027cba08cac49fa05b1b0ebe25bbaa1a6fa19
|
|
| MD5 |
1a8b900e0db03cc1c4bab734d8e6be1c
|
|
| BLAKE2b-256 |
f7e3574238fff8d0126c44a01cfca9e463e55a73e3cc2b63c634b5e48b8b3395
|