pub mod arc;
pub mod chrome;
pub mod chrome_text;
pub mod edge_3d;
pub mod glyph;
pub mod grid;
pub mod lines;
pub mod solid;
pub mod text;
mod text_common;

pub use arc::ArcPipeline;
pub use chrome::{ChromeInstance, ChromePipeline};
pub use chrome_text::{ChromeTextPipeline, SdfGlyphInstance};
pub(crate) use edge_3d::{Edge3dPipeline, EdgeProjection, EdgeView, HiddenEdges};
pub use glyph::GlyphPipeline;
pub use grid::GridPipeline;
pub use lines::LinesPipeline;
pub(crate) use solid::{FaceFill, SolidPipeline, SolidView};
pub use text::TextPipeline;

use crate::camera::Camera2;
use crate::snapshot::Style;

#[repr(C, align(16))]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub(crate) struct FrameUniform {
    pub clip_from_world: [f32; 16],
    pub stroke_color: [f32; 4],
    pub construction_color: [f32; 4],
    pub pixels_per_mm: f32,
    pub dash_period_px: f32,
    pub dash_on_ratio: f32,
    pub _pad: f32,
}

pub(crate) const FRAME_UNIFORM_SIZE: u64 = core::mem::size_of::<FrameUniform>() as u64;

pub(crate) const CONSTRUCTION_BIT: u32 = 1;

#[allow(
    clippy::cast_possible_truncation,
    clippy::cast_precision_loss,
    reason = "zoom factor and stroke widths fit f32 mantissa at CAD scales"
)]
pub(crate) fn build_frame_uniform(camera: Camera2, style: &Style) -> FrameUniform {
    let strokes = style.strokes();
    FrameUniform {
        clip_from_world: camera.clip_from_world_mm(),
        stroke_color: strokes.stroke().to_rgba_array(),
        construction_color: strokes.construction().to_rgba_array(),
        pixels_per_mm: camera.zoom().value() as f32,
        dash_period_px: strokes.construction_dash_period_px(),
        dash_on_ratio: strokes.construction_dash_on_ratio(),
        _pad: 0.0,
    }
}
