949 lines · 30.4 KB · Rust
RawDownload
// todo("windows"): remove#![cfg_attr(windows, allow(dead_code))] use schemars::JsonSchema;use serde::{Deserialize, Serialize}; use crate::{    AtlasTextureId, AtlasTile, Background, Bounds, ContentMask, Corners, Edges, Hsla, Pixels,    Point, Radians, ScaledPixels, Size, bounds_tree::BoundsTree, point,};use std::{    fmt::Debug,    iter::Peekable,    ops::{Add, Range, Sub},    slice,}; #[allow(non_camel_case_types, unused)]#[expect(missing_docs)]pub type PathVertex_ScaledPixels = PathVertex<ScaledPixels>; #[expect(missing_docs)]pub type DrawOrder = u32; /// A boolean stored as a `u32` so that GPU-facing structs contain no/// compiler-inserted padding bytes, which would be undefined behavior to/// reinterpret as `&[u8]` when writing instance buffers. Guaranteed to be/// `0` or `1` by construction; shaders read it as a `u32`/`uint`.#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]#[repr(transparent)]pub struct PaddedBool32(u32); impl From<bool> for PaddedBool32 {    fn from(value: bool) -> Self {        PaddedBool32(value as u32)    }} #[derive(Default)]#[expect(missing_docs)]pub struct Scene {    pub(crate) paint_operations: Vec<PaintOperation>,    primitive_bounds: BoundsTree<ScaledPixels>,    layer_stack: Vec<DrawOrder>,    pub shadows: Vec<Shadow>,    pub quads: Vec<Quad>,    pub paths: Vec<Path<ScaledPixels>>,    pub underlines: Vec<Underline>,    pub monochrome_sprites: Vec<MonochromeSprite>,    pub subpixel_sprites: Vec<SubpixelSprite>,    pub polychrome_sprites: Vec<PolychromeSprite>,    pub surfaces: Vec<PaintSurface>,} #[expect(missing_docs)]impl Scene {    pub fn clear(&mut self) {        self.paint_operations.clear();        self.primitive_bounds.clear();        self.layer_stack.clear();        self.paths.clear();        self.shadows.clear();        self.quads.clear();        self.underlines.clear();        self.monochrome_sprites.clear();        self.subpixel_sprites.clear();        self.polychrome_sprites.clear();        self.surfaces.clear();    }     pub fn len(&self) -> usize {        self.paint_operations.len()    }     pub fn push_layer(&mut self, bounds: Bounds<ScaledPixels>) {        let order = self.primitive_bounds.insert(bounds);        self.layer_stack.push(order);        self.paint_operations            .push(PaintOperation::StartLayer(bounds));    }     pub fn pop_layer(&mut self) {        self.layer_stack.pop();        self.paint_operations.push(PaintOperation::EndLayer);    }     pub fn insert_primitive(&mut self, primitive: impl Into<Primitive>) {        let mut primitive = primitive.into();        let clipped_bounds = primitive            .bounds()            .intersect(&primitive.content_mask().bounds);         if clipped_bounds.is_empty() {            return;        }         let order = self            .layer_stack            .last()            .copied()            .unwrap_or_else(|| self.primitive_bounds.insert(clipped_bounds));        match &mut primitive {            Primitive::Shadow(shadow) => {                shadow.order = order;                self.shadows.push(*shadow);            }            Primitive::Quad(quad) => {                quad.order = order;                self.quads.push(*quad);            }            Primitive::Path(path) => {                path.order = order;                path.id = PathId(self.paths.len());                self.paths.push(path.clone());            }            Primitive::Underline(underline) => {                underline.order = order;                self.underlines.push(*underline);            }            Primitive::MonochromeSprite(sprite) => {                sprite.order = order;                self.monochrome_sprites.push(*sprite);            }            Primitive::SubpixelSprite(sprite) => {                sprite.order = order;                self.subpixel_sprites.push(*sprite);            }            Primitive::PolychromeSprite(sprite) => {                sprite.order = order;                self.polychrome_sprites.push(*sprite);            }            Primitive::Surface(surface) => {                surface.order = order;                self.surfaces.push(surface.clone());            }        }        self.paint_operations            .push(PaintOperation::Primitive(primitive));    }     pub fn replay(&mut self, range: Range<usize>, prev_scene: &Scene) {        for operation in &prev_scene.paint_operations[range] {            match operation {                PaintOperation::Primitive(primitive) => self.insert_primitive(primitive.clone()),                PaintOperation::StartLayer(bounds) => self.push_layer(*bounds),                PaintOperation::EndLayer => self.pop_layer(),            }        }    }     pub fn finish(&mut self) {        self.shadows.sort_by_key(|shadow| shadow.order);        self.quads.sort_by_key(|quad| quad.order);        self.paths.sort_by_key(|path| path.order);        self.underlines.sort_by_key(|underline| underline.order);        self.monochrome_sprites            .sort_by_key(|sprite| (sprite.order, sprite.tile.tile_id));        self.subpixel_sprites            .sort_by_key(|sprite| (sprite.order, sprite.tile.tile_id));        self.polychrome_sprites            .sort_by_key(|sprite| (sprite.order, sprite.tile.tile_id));        self.surfaces.sort_by_key(|surface| surface.order);    }     #[cfg_attr(        all(            any(target_os = "linux", target_os = "freebsd"),            not(any(feature = "x11", feature = "wayland"))        ),        allow(dead_code)    )]    pub fn batches(&self) -> impl Iterator<Item = PrimitiveBatch> + '_ {        BatchIterator {            shadows_start: 0,            shadows_iter: self.shadows.iter().peekable(),            quads_start: 0,            quads_iter: self.quads.iter().peekable(),            paths_start: 0,            paths_iter: self.paths.iter().peekable(),            underlines_start: 0,            underlines_iter: self.underlines.iter().peekable(),            monochrome_sprites_start: 0,            monochrome_sprites_iter: self.monochrome_sprites.iter().peekable(),            subpixel_sprites_start: 0,            subpixel_sprites_iter: self.subpixel_sprites.iter().peekable(),            polychrome_sprites_start: 0,            polychrome_sprites_iter: self.polychrome_sprites.iter().peekable(),            surfaces_start: 0,            surfaces_iter: self.surfaces.iter().peekable(),        }    }} #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Default)]#[cfg_attr(    all(        any(target_os = "linux", target_os = "freebsd"),        not(any(feature = "x11", feature = "wayland"))    ),    allow(dead_code))]pub(crate) enum PrimitiveKind {    Shadow,    #[default]    Quad,    Path,    Underline,    MonochromeSprite,    SubpixelSprite,    PolychromeSprite,    Surface,} pub(crate) enum PaintOperation {    Primitive(Primitive),    StartLayer(Bounds<ScaledPixels>),    EndLayer,} #[derive(Clone)]#[expect(missing_docs)]pub enum Primitive {    Shadow(Shadow),    Quad(Quad),    Path(Path<ScaledPixels>),    Underline(Underline),    MonochromeSprite(MonochromeSprite),    SubpixelSprite(SubpixelSprite),    PolychromeSprite(PolychromeSprite),    Surface(PaintSurface),} #[expect(missing_docs)]impl Primitive {    pub fn bounds(&self) -> &Bounds<ScaledPixels> {        match self {            Primitive::Shadow(shadow) => &shadow.bounds,            Primitive::Quad(quad) => &quad.bounds,            Primitive::Path(path) => &path.bounds,            Primitive::Underline(underline) => &underline.bounds,            Primitive::MonochromeSprite(sprite) => &sprite.bounds,            Primitive::SubpixelSprite(sprite) => &sprite.bounds,            Primitive::PolychromeSprite(sprite) => &sprite.bounds,            Primitive::Surface(surface) => &surface.bounds,        }    }     pub fn content_mask(&self) -> &ContentMask<ScaledPixels> {        match self {            Primitive::Shadow(shadow) => &shadow.content_mask,            Primitive::Quad(quad) => &quad.content_mask,            Primitive::Path(path) => &path.content_mask,            Primitive::Underline(underline) => &underline.content_mask,            Primitive::MonochromeSprite(sprite) => &sprite.content_mask,            Primitive::SubpixelSprite(sprite) => &sprite.content_mask,            Primitive::PolychromeSprite(sprite) => &sprite.content_mask,            Primitive::Surface(surface) => &surface.content_mask,        }    }} #[cfg_attr(    all(        any(target_os = "linux", target_os = "freebsd"),        not(any(feature = "x11", feature = "wayland"))    ),    allow(dead_code))]struct BatchIterator<'a> {    shadows_start: usize,    shadows_iter: Peekable<slice::Iter<'a, Shadow>>,    quads_start: usize,    quads_iter: Peekable<slice::Iter<'a, Quad>>,    paths_start: usize,    paths_iter: Peekable<slice::Iter<'a, Path<ScaledPixels>>>,    underlines_start: usize,    underlines_iter: Peekable<slice::Iter<'a, Underline>>,    monochrome_sprites_start: usize,    monochrome_sprites_iter: Peekable<slice::Iter<'a, MonochromeSprite>>,    subpixel_sprites_start: usize,    subpixel_sprites_iter: Peekable<slice::Iter<'a, SubpixelSprite>>,    polychrome_sprites_start: usize,    polychrome_sprites_iter: Peekable<slice::Iter<'a, PolychromeSprite>>,    surfaces_start: usize,    surfaces_iter: Peekable<slice::Iter<'a, PaintSurface>>,} impl<'a> Iterator for BatchIterator<'a> {    type Item = PrimitiveBatch;     fn next(&mut self) -> Option<Self::Item> {        let mut orders_and_kinds = [            (                self.shadows_iter.peek().map(|s| s.order),                PrimitiveKind::Shadow,            ),            (self.quads_iter.peek().map(|q| q.order), PrimitiveKind::Quad),            (self.paths_iter.peek().map(|q| q.order), PrimitiveKind::Path),            (                self.underlines_iter.peek().map(|u| u.order),                PrimitiveKind::Underline,            ),            (                self.monochrome_sprites_iter.peek().map(|s| s.order),                PrimitiveKind::MonochromeSprite,            ),            (                self.subpixel_sprites_iter.peek().map(|s| s.order),                PrimitiveKind::SubpixelSprite,            ),            (                self.polychrome_sprites_iter.peek().map(|s| s.order),                PrimitiveKind::PolychromeSprite,            ),            (                self.surfaces_iter.peek().map(|s| s.order),                PrimitiveKind::Surface,            ),        ];        orders_and_kinds.sort_by_key(|(order, kind)| (order.unwrap_or(u32::MAX), *kind));         let first = orders_and_kinds[0];        let second = orders_and_kinds[1];        let (batch_kind, max_order_and_kind) = if first.0.is_some() {            (first.1, (second.0.unwrap_or(u32::MAX), second.1))        } else {            return None;        };         match batch_kind {            PrimitiveKind::Shadow => {                let shadows_start = self.shadows_start;                let mut shadows_end = shadows_start + 1;                self.shadows_iter.next();                while self                    .shadows_iter                    .next_if(|shadow| (shadow.order, batch_kind) < max_order_and_kind)                    .is_some()                {                    shadows_end += 1;                }                self.shadows_start = shadows_end;                Some(PrimitiveBatch::Shadows(shadows_start..shadows_end))            }            PrimitiveKind::Quad => {                let quads_start = self.quads_start;                let mut quads_end = quads_start + 1;                self.quads_iter.next();                while self                    .quads_iter                    .next_if(|quad| (quad.order, batch_kind) < max_order_and_kind)                    .is_some()                {                    quads_end += 1;                }                self.quads_start = quads_end;                Some(PrimitiveBatch::Quads(quads_start..quads_end))            }            PrimitiveKind::Path => {                let paths_start = self.paths_start;                let mut paths_end = paths_start + 1;                self.paths_iter.next();                while self                    .paths_iter                    .next_if(|path| (path.order, batch_kind) < max_order_and_kind)                    .is_some()                {                    paths_end += 1;                }                self.paths_start = paths_end;                Some(PrimitiveBatch::Paths(paths_start..paths_end))            }            PrimitiveKind::Underline => {                let underlines_start = self.underlines_start;                let mut underlines_end = underlines_start + 1;                self.underlines_iter.next();                while self                    .underlines_iter                    .next_if(|underline| (underline.order, batch_kind) < max_order_and_kind)                    .is_some()                {                    underlines_end += 1;                }                self.underlines_start = underlines_end;                Some(PrimitiveBatch::Underlines(underlines_start..underlines_end))            }            PrimitiveKind::MonochromeSprite => {                let texture_id = self.monochrome_sprites_iter.peek().unwrap().tile.texture_id;                let sprites_start = self.monochrome_sprites_start;                let mut sprites_end = sprites_start + 1;                self.monochrome_sprites_iter.next();                while self                    .monochrome_sprites_iter                    .next_if(|sprite| {                        (sprite.order, batch_kind) < max_order_and_kind                            && sprite.tile.texture_id == texture_id                    })                    .is_some()                {                    sprites_end += 1;                }                self.monochrome_sprites_start = sprites_end;                Some(PrimitiveBatch::MonochromeSprites {                    texture_id,                    range: sprites_start..sprites_end,                })            }            PrimitiveKind::SubpixelSprite => {                let texture_id = self.subpixel_sprites_iter.peek().unwrap().tile.texture_id;                let sprites_start = self.subpixel_sprites_start;                let mut sprites_end = sprites_start + 1;                self.subpixel_sprites_iter.next();                while self                    .subpixel_sprites_iter                    .next_if(|sprite| {                        (sprite.order, batch_kind) < max_order_and_kind                            && sprite.tile.texture_id == texture_id                    })                    .is_some()                {                    sprites_end += 1;                }                self.subpixel_sprites_start = sprites_end;                Some(PrimitiveBatch::SubpixelSprites {                    texture_id,                    range: sprites_start..sprites_end,                })            }            PrimitiveKind::PolychromeSprite => {                let texture_id = self.polychrome_sprites_iter.peek().unwrap().tile.texture_id;                let sprites_start = self.polychrome_sprites_start;                let mut sprites_end = sprites_start + 1;                self.polychrome_sprites_iter.next();                while self                    .polychrome_sprites_iter                    .next_if(|sprite| {                        (sprite.order, batch_kind) < max_order_and_kind                            && sprite.tile.texture_id == texture_id                    })                    .is_some()                {                    sprites_end += 1;                }                self.polychrome_sprites_start = sprites_end;                Some(PrimitiveBatch::PolychromeSprites {                    texture_id,                    range: sprites_start..sprites_end,                })            }            PrimitiveKind::Surface => {                let surfaces_start = self.surfaces_start;                let mut surfaces_end = surfaces_start + 1;                self.surfaces_iter.next();                while self                    .surfaces_iter                    .next_if(|surface| (surface.order, batch_kind) < max_order_and_kind)                    .is_some()                {                    surfaces_end += 1;                }                self.surfaces_start = surfaces_end;                Some(PrimitiveBatch::Surfaces(surfaces_start..surfaces_end))            }        }    }} #[derive(Debug)]#[cfg_attr(    all(        any(target_os = "linux", target_os = "freebsd"),        not(any(feature = "x11", feature = "wayland"))    ),    allow(dead_code))]#[allow(missing_docs)]pub enum PrimitiveBatch {    Shadows(Range<usize>),    Quads(Range<usize>),    Paths(Range<usize>),    Underlines(Range<usize>),    MonochromeSprites {        texture_id: AtlasTextureId,        range: Range<usize>,    },    #[cfg_attr(target_os = "macos", allow(dead_code))]    SubpixelSprites {        texture_id: AtlasTextureId,        range: Range<usize>,    },    PolychromeSprites {        texture_id: AtlasTextureId,        range: Range<usize>,    },    Surfaces(Range<usize>),} impl PrimitiveBatch {    #[expect(missing_docs)]    pub fn label(&self) -> String {

Lines 1–500 of 949.