plushie-renderer-lib 0.7.1

Shared renderer engine for Plushie
Documentation
//! String constants for the stdin/stdout protocol.
//!
//! Subscription keys, default values, and other protocol constants
//! used across the renderer module. Centralised here so typos are
//! caught at compile time and the full set is discoverable.

// -- Subscription keys -------------------------------------------------------

/// Catch-all event subscription (keyboard, mouse, touch, IME).
pub const SUB_EVENT: &str = "on_event";

pub const SUB_KEY_PRESS: &str = "on_key_press";
pub const SUB_KEY_RELEASE: &str = "on_key_release";
pub const SUB_MODIFIERS_CHANGED: &str = "on_modifiers_changed";

pub const SUB_POINTER_MOVE: &str = "on_pointer_move";
pub const SUB_POINTER_BUTTON: &str = "on_pointer_button";
pub const SUB_POINTER_SCROLL: &str = "on_pointer_scroll";

pub const SUB_POINTER_TOUCH: &str = "on_pointer_touch";

pub const SUB_IME: &str = "on_ime";

/// Catch-all window lifecycle subscription.
pub const SUB_WINDOW_EVENT: &str = "on_window_event";
pub const SUB_WINDOW_OPEN: &str = "on_window_open";
pub const SUB_WINDOW_CLOSE: &str = "on_window_close";
pub const SUB_WINDOW_MOVE: &str = "on_window_move";
pub const SUB_WINDOW_RESIZE: &str = "on_window_resize";
pub const SUB_WINDOW_FOCUS: &str = "on_window_focus";
pub const SUB_WINDOW_UNFOCUS: &str = "on_window_unfocus";

pub const SUB_FILE_DROP: &str = "on_file_drop";
pub const SUB_ANIMATION_FRAME: &str = "on_animation_frame";
pub const SUB_THEME_CHANGE: &str = "on_theme_change";

// -- Defaults ----------------------------------------------------------------

pub const DEFAULT_WINDOW_TITLE: &str = "Plushie";

/// Default theme when no theme is specified in Settings or after a Reset.
pub const DEFAULT_THEME: iced::Theme = iced::Theme::Dark;

/// Maximum decoded font data size for runtime `load_font` operations.
/// Font files are typically under 1 MB; large CJK fonts top out around
/// 15-17 MB. Anything beyond this limit is rejected as likely not a font.
pub const MAX_FONT_BYTES: usize = 16 * 1024 * 1024;

/// Maximum number of fonts that can be loaded across a process
/// lifetime. Each `load_font` call (and each startup-inline font)
/// permanently leaks font bytes into iced's global font system (no
/// unload API), so the cap is the single gate against unbounded
/// memory growth from a misbehaving host.
pub const MAX_LOADED_FONTS: u32 = 256;

/// Process-wide counter of fonts loaded into the global font system.
/// Shared between the dynamic `load_font` widget op and the startup
/// inline-font path so both participate in the same cap.
pub static LOADED_FONT_COUNT: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0);

/// Atomically reserve a single font slot against the process-wide
/// cap. Returns true if a slot was reserved; the caller is now
/// responsible for actually loading the font. Returns false when
/// the cap is exhausted.
///
/// Uses compare_exchange instead of `load + fetch_add` so concurrent
/// callers cannot race past the cap. The dynamic load_font widget op,
/// the headless `load_font` payload path, and the file-path startup
/// loader all share this gate.
pub fn try_reserve_font_slot() -> bool {
    use std::sync::atomic::Ordering;
    let mut current = LOADED_FONT_COUNT.load(Ordering::Relaxed);
    loop {
        if current >= MAX_LOADED_FONTS {
            return false;
        }
        match LOADED_FONT_COUNT.compare_exchange(
            current,
            current + 1,
            Ordering::Relaxed,
            Ordering::Relaxed,
        ) {
            Ok(_) => return true,
            Err(actual) => current = actual,
        }
    }
}