BREP_app 0.4.0

The BREP CAD application: an eframe (egui + wgpu) host that draws the brep-render 3D engine into an egui frame — native + wasm from one codebase.
Documentation
//! The inline-icon catalog: every `assets/glyphs/*.svg` as SVG source, keyed by
//! the character it draws.
//!
//! This is the lookup half of the SVG-icon feature; [`crate::icon_text`] is the
//! drawing half. The table itself is generated by `build.rs` at compile time
//! from the glyph SVGs, so an icon is catalogued by existing, with no list here
//! to fall out of step. See `build.rs` for the two transforms it applies (the
//! `#111` ink sentinel, and the viewBox-derived aspect ratio).
//!
//! Why both a font and an SVG catalog: the font is what egui lays out inside
//! ordinary text, and it stays the fallback for every glyph that is drawn as
//! text (toolbar buttons, `ui.label`s not yet converted). The catalog is what
//! lets the same character be drawn as a real image — which is what makes
//! genuine multi-colour icons possible, since a TrueType glyph can only be one
//! colour. The stacked private-use layers in
//! [`crate::panels::toolbar_button`] exist only to work around that limit.
//!
//! Three icons already take that route — the bug (U+1F41E), the book
//! (U+1F4DA) and the pencil (U+270D). Each was composed from the very layers
//! `toolbar_button` stacks by hand, in the same palette, so they are the same
//! artwork expressed once instead of assembled at paint time. Their glyph SVGs
//! mark the ink layer `brep:font-outline="1"`, so the TTF is byte-for-byte what
//! it was and a text use of those characters still renders exactly as before —
//! the colour is additive, visible only through this catalog.

// The generated `pub static ICONS: &[Icon]`, sorted by codepoint.
include!(concat!(env!("OUT_DIR"), "/icon_catalog.rs"));

/// One catalogued icon: the SVG source for a character, plus what the renderer
/// needs to place and colour it.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Icon {
    /// The character this icon draws — what a string must contain to select it.
    pub ch: char,
    /// PostScript glyph name (e.g. `icon_2699`), for debugging and docs.
    pub name: &'static str,
    /// A stable, per-icon `bytes://…svg` URI. egui caches the decoded texture
    /// under it, so it must be constant across frames — and it must end in
    /// `.svg`, which is how `egui_extras`' loader recognises the format.
    pub uri: &'static str,
    /// The SVG source, with `mono` artwork already rewritten to white.
    pub svg: &'static str,
    /// width / height of the viewBox — the proportion the font draws it at.
    pub aspect: f32,
    /// SVG cropped to painted bounds, for standalone artwork in icon tiles.
    pub artwork_svg: &'static str,
    /// Aspect ratio of the painted artwork, excluding canvas padding.
    pub artwork_aspect: f32,
    /// Monochrome artwork that should take the colour of the surrounding text.
    /// `false` means the SVG carries its own colours and must not be tinted.
    pub mono: bool,
}

/// The icon for `ch`, or `None` if the catalog has none — in which case the
/// character stays ordinary text and the font draws it.
pub fn lookup(ch: char) -> Option<&'static Icon> {
    let i = ICONS.binary_search_by_key(&ch, |icon| icon.ch).ok()?;
    Some(&ICONS[i])
}

/// Whether `ch` has an icon. Cheaper to read at a call site than `lookup().is_some()`.
pub fn has(ch: char) -> bool {
    lookup(ch).is_some()
}

/// The catalogued artwork for a label that is exactly one character.
///
/// This is the test every icon-drawing site makes — toolbar buttons, tree rows,
/// palette rows — so they all agree on what is an icon. `None` for a
/// multi-character label (a composite, not an icon) and for an uncatalogued
/// character; both are drawn as ordinary text.
///
/// MONOCHROME artwork is included. It used to be excluded, on the grounds that
/// the icon font already drew it in the live text colour for free — but that
/// exclusion was the last thing keeping a font in the binary. Callers tint a
/// `mono` icon to their text colour (it is white in the catalog, so a multiply
/// lands it exactly) and leave a colour one alone.
pub fn artwork(glyph: &str) -> Option<&'static Icon> {
    let mut chars = glyph.chars();
    let icon = lookup(chars.next()?)?;
    chars.next().is_none().then_some(icon)
}

// BREP private tests: 4d18c45d7a290280