mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-31 14:07:06 -06:00
121 lines
4.3 KiB
Rust
121 lines
4.3 KiB
Rust
//! The DeckCraft renderer: draws slides, layouts and masters with `vello_cpu`.
|
|
//!
|
|
//! One code path serves the editor canvas, thumbnails, image/PDF-raster export and the slide show:
|
|
//! [`render_slide`] draws the background, the master and layout graphics, then the slide's shapes
|
|
//! (fills with theme shading, gradients, pictures, outlines with dashes and arrowheads, shadows,
|
|
//! glow and soft edges, text, tables, charts, groups), optionally with per-shape animation state.
|
|
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
|
#![forbid(unsafe_code)]
|
|
|
|
mod bevel;
|
|
mod camera;
|
|
mod chart;
|
|
mod chartex;
|
|
mod colr;
|
|
mod extrude;
|
|
mod light;
|
|
|
|
mod compound;
|
|
mod extent;
|
|
mod images;
|
|
mod metafile;
|
|
mod morph_path;
|
|
mod morph_text;
|
|
mod paint;
|
|
mod pattern;
|
|
|
|
mod pathgrad;
|
|
mod placed;
|
|
mod radar;
|
|
mod ramp;
|
|
mod table;
|
|
mod transition;
|
|
mod warp;
|
|
|
|
use std::collections::HashMap;
|
|
use std::sync::Arc;
|
|
|
|
use deckcraft_color::Rgba;
|
|
use deckcraft_fonts::FontDb;
|
|
use deckcraft_geom::preset::{self, FillMode, Geometry, SubPath};
|
|
use deckcraft_model::resolve::{self, Ctx};
|
|
use deckcraft_model::style::{Effects, Fill, Line};
|
|
use deckcraft_model::text::TextBody;
|
|
use deckcraft_model::{Geom, PhType, Presentation, Shape, ShapeId, ShapeKind, Slide};
|
|
use deckcraft_text::datetime::{self, DateTime};
|
|
use deckcraft_text::{Fields, Opts};
|
|
use kurbo::{Affine, BezPath, PathEl, Point, Rect, Shape as _, Vec2};
|
|
use vello_common::filter_effects::{EdgeMode, Filter, FilterPrimitive};
|
|
use vello_cpu::{RenderContext, Resources, peniko};
|
|
|
|
pub use deckcraft_anim::{transition_frame, transition_layers, uses_slide_parts};
|
|
pub use extent::{Region, TILE, layout_extent, pasteboard_region, slide_extent};
|
|
pub use images::{decode as decode_image, gif_frame};
|
|
pub use morph_path::PathMorph;
|
|
pub use morph_text::TextMorph;
|
|
pub use pattern::{is_fg as pattern_is_fg, presets as pattern_presets, tile as pattern_tile};
|
|
pub use placed::{Placed, PlacedLink, PlacedShape, PlacedText, place_master_texts, place_slide, text_outline};
|
|
pub use table::cell_body as table_cell_body;
|
|
pub use table::cell_rects as table_cell_rects;
|
|
pub use table::row_heights as table_row_heights;
|
|
pub use transition::{SlideParts, composite_transition, render_transition};
|
|
|
|
mod geometry;
|
|
mod opts;
|
|
mod raster;
|
|
mod renderer;
|
|
mod slide;
|
|
mod stroke;
|
|
mod text_draw;
|
|
|
|
use geometry::shade;
|
|
pub use geometry::{camera_turn, crop_dest, parse_path, shape_geometry};
|
|
pub(crate) use geometry::{color, scale_of};
|
|
use opts::SlideFields;
|
|
pub use opts::{ParaState, RenderOpts, ShapeState};
|
|
pub use raster::{Image, MAX_SIDE, dpi_for_scale, image_dpi};
|
|
#[cfg(test)]
|
|
use renderer::RENDERER;
|
|
pub use renderer::Renderer;
|
|
pub use slide::{
|
|
SlidePart, needs_filters, panics_caught, render_blend, render_layout, render_shape, render_shapes, render_slide, render_slide_drawn,
|
|
render_slide_part,
|
|
};
|
|
pub(crate) use stroke::stroke;
|
|
#[cfg(test)]
|
|
use stroke::{MAX_DASHES, dash_with_caps, head_size, limit_dash_count, trim_ends};
|
|
use text_draw::preview_empty_bullets;
|
|
pub(crate) use text_draw::{draw_glyph, fill_deco, glyph, glyph_place};
|
|
pub use text_draw::{draw_layout, draw_layout_with, draw_text, text_transform, text_warp};
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|
|
|
|
#[cfg(test)]
|
|
mod tests_wild;
|
|
|
|
#[cfg(test)]
|
|
mod mt_tests {
|
|
use super::*;
|
|
|
|
/// Regression: multithreaded rendering of a slide with shadows panicked inside vello_cpu.
|
|
#[test]
|
|
fn effects_render_with_threads_requested() {
|
|
let mut s = deckcraft_model::Presentation::default();
|
|
let sl = std::sync::Arc::make_mut(&mut s.slides[0]);
|
|
let mut sh = deckcraft_model::Shape {
|
|
id: ShapeId(900),
|
|
xfrm: Some(deckcraft_geom::Xfrm::new(10.0, 10.0, 100.0, 100.0)),
|
|
style: Some(deckcraft_model::ShapeStyle::accent(deckcraft_color::SchemeSlot::Accent1)),
|
|
..Default::default()
|
|
};
|
|
sh.effects = Some(deckcraft_model::Effects { soft_edge: Some(5.0), ..Default::default() });
|
|
sl.shapes.push(sh);
|
|
assert!(needs_filters(&s, &s.slides[0]));
|
|
let img = RENDERER.with(|r| r.borrow_mut().slide(&s, &s.slides[0], 0, &RenderOpts { scale: 0.5, threads: 4, ..Default::default() }));
|
|
assert_eq!(img.width, 480);
|
|
// The shape itself is drawn (not a blank fallback).
|
|
assert_ne!(img.pixel(30, 30), [255, 255, 255, 255]);
|
|
}
|
|
}
|