Files
craft-libs/Cargo.toml
T
Dylan M. TaylorandJordi Altayó 5538d8a0d7 Add craft-pptx: the PresentationML model (from DeckCraft) (#1044)
* Add craft-drawingml: units, colours, preset shapes, custom geometry and text warps

The parts of DrawingML that need no document model, moved from DeckCraft
(60f91f78): crates/color, crates/geom (preset, warp, Xfrm and the EMU
conversions) and crates/pptx/src/custgeom.rs with CustomPath from
crates/model.

The code is unchanged except that custgeom reads craft-xml trees and writes
to a craft-xml Writer instead of DeckCraft's own XML helper, and matches
elements by local name. The 59 tests of the moved code come with it; six
more cover the custom geometry limits.

* drawingml: evaluate a custom geometry's guide lists once per coordinate space

read_cust_geom rebuilt Guides and evaluated avLst and gdLst again for every
path: up to 1,000 paths times up to 10,000 guides, each name copied and
hashed.

Guides are now cached per path coordinate space (w, h). At most 16 spaces
and 4 MiB of guide names are kept per geometry; paths in further spaces are
left out. The first space is always kept, and a geometry without guides is
not capped.

Ported from storytold/deckcraft#1789. A list counts as having guides only
when it has gd children, as that PR's review asked.

* drawingml: the model types for fills, lines, text, tables, charts and diagrams

Moved from DeckCraft (60f91f78) crates/model/src: style.rs, text.rs,
table.rs, chart.rs, numfmt.rs and trendline.rs, plus Diagram, DiagramNode
and the MediaId and SlideId newtypes from lib.rs.

The files are unchanged except that deckcraft_color:: is crate::color:: and
Fill and TableBorder allow clippy::large_enum_variant. Their 60 tests come
with them. Readers and writers follow.

* drawingml: the theme model (colour, font and format schemes)

Moved from DeckCraft crates/model/src/theme.rs at 60f91f78: FontSet, ScriptFont, FontScheme,
FormatScheme, Theme and default_format. The app's theme gallery, its variants and its own default
theme stay in the app. Theme::default() is a plain theme built in place, so nothing here depends
on a gallery.

* drawingml: readers and writers for fills, lines, text, charts, themes, table styles and diagrams

Moved from DeckCraft crates/pptx/src at 60f91f78: read/dml.rs, write/dml.rs, read/chart.rs,
read/chartex.rs, write/chart.rs, read/theme.rs, write/theme.rs, tables.rs and dgm.rs, onto
craft-xml. Package lookups (Imp, Part, Exp, Out) are the caller's part::Source and part::Sink.
The chart frame budget and kept-part capture stay with the presentation reader.

* drawingml: what WordCraft and GridCraft read that DeckCraft's copy did not

Every ST_PresetColorVal name has its colour, in any case and with the dk/lt/med abbreviations;
a sysClr without lastClr takes the usual value of its name; a Strict percentage (50%) reads
anywhere a percentage does; a chart series keeps its c:f formulas and the writer uses them.

* craft-drawingml: extra named theme colours and explicit tint rows

Ported from the format part of storytold/deckcraft#1746 by @jagjordi: ColorScheme::{extra, tints,
computed_tints}, ExtraColor, GalleryVariant, variants_of, and the a:clrScheme extension that
keeps them in a file.

* drawingml xmlx: copy only used, bounded namespace declarations onto kept fragments and mc branches

From storytold/deckcraft#1740 (988a4920), which landed after the extraction commit 60f91f78.

* Add craft-pptx: the PresentationML model (from DeckCraft)

Presentation, masters, layouts, slides, shapes, placeholders, media,
comments, sections, show settings, properties, embedded fonts, kept parts
and drawing guides from DeckCraft's crates/model/src/lib.rs, and
transitions and animations from anim.rs. The DrawingML types come from
craft-drawingml. The placeholder matching from DeckCraft's resolve.rs
moves as placeholder::parents, without the rest of resolve.

Presentation::default() is now an empty 16:9 deck with no masters; the
starting deck stays with the application.

---------

Co-authored-by: Jordi Altayó <jordiag@kth.se>
2026-11-11 21:04:26 -05:00

197 lines
9.1 KiB
TOML

[workspace]
resolver = "3"
members = ["crates/*"]
exclude = ["vendor/krilla", "vendor/hayro", "vendor/hayro-interpret", "vendor/hayro-syntax", "vendor/hayro-jbig2", "vendor/hayro-cmap", "vendor/hayro-postscript", "vendor/linesweeper"]
[workspace.package]
version = "0.1.0"
edition = "2024"
license = "MIT OR Apache-2.0"
rust-version = "1.95"
repository = "https://github.com/storytold/craft-libs"
[workspace.dependencies]
# internal: add each crate here as `craft-<name> = { path = "crates/<name>" }`
craft-platform = { path = "crates/platform" }
craft-aep = { path = "crates/aep" }
craft-affinity = { path = "crates/affinity" }
craft-ai-core = { path = "crates/ai-core" }
craft-pdf = { path = "crates/pdf", version = "=0.1.0" }
craft-pdn = { path = "crates/pdn" }
craft-plate-test = { path = "crates/plate-test" }
krilla = { version = "=0.8.2", default-features = false, features = ["raster-images"] }
hayro = { version = "=0.7.1", default-features = false }
hayro-interpret = { version = "=0.7.0", default-features = false, features = ["embed-fonts", "embed-cmaps"] }
hayro-syntax = { version = "=0.7.2", default-features = false, features = ["std"] }
bytemuck = "1"
kurbo = "0.13"
thiserror = "2"
craft-aaf = { path = "crates/aaf" }
craft-atomic = { path = "crates/atomic" }
craft-captions = { path = "crates/captions" }
craft-cfb = { path = "crates/cfb" }
craft-codepage = { path = "crates/codepage" }
craft-cms = { path = "crates/cms" }
craft-crs = { path = "crates/crs" }
craft-crw = { path = "crates/crw" }
craft-csv = { path = "crates/csv" }
craft-dav = { path = "crates/dav" }
craft-dialogs = { path = "crates/dialogs" }
craft-docx = { path = "crates/docx" }
craft-dxf = { path = "crates/dxf" }
craft-drawingml = { path = "crates/drawingml" }
craft-eps = { path = "crates/eps" }
craft-doc = { path = "crates/doc" }
craft-docpath = { path = "crates/docpath" }
craft-dpx = { path = "crates/dpx" }
craft-ecproj-format = { path = "crates/ecproj-format" }
craft-figma-rest = { path = "crates/figma-rest" }
craft-exr = { path = "crates/exr" }
craft-font-catalog = { path = "crates/font-catalog" }
craft-font-manager = { path = "crates/font-manager" }
craft-font-store = { path = "crates/font-store" }
craft-gainmap = { path = "crates/gainmap" }
craft-flow = { path = "crates/flow" }
craft-gcode = { path = "crates/gcode" }
craft-gif = { path = "crates/gif" }
craft-hdr = { path = "crates/hdr" }
craft-mesh = { path = "crates/mesh" }
craft-html = { path = "crates/html" }
craft-heif = { path = "crates/heif" }
craft-fig = { path = "crates/fig" }
craft-fonts-build = { path = "crates/fonts-build" }
craft-i18n = { path = "crates/i18n" }
craft-idml = { path = "crates/idml" }
craft-jmap = { path = "crates/jmap" }
craft-ical = { path = "crates/ical" }
craft-jpeg = { path = "crates/jpeg" }
craft-kiwi = { path = "crates/kiwi" }
craft-keymap = { path = "crates/keymap" }
craft-assuan = { path = "crates/assuan" }
craft-kra = { path = "crates/kra" }
craft-audio = { path = "crates/audio" }
# No default features, so craft-audio's `encode` builds craft-media without `isobmff`.
craft-latex = { path = "crates/latex" }
craft-markdown = { path = "crates/markdown" }
craft-math = { path = "crates/math" }
craft-media = { path = "crates/media", default-features = false }
craft-media-testkit = { path = "crates/media-testkit" }
craft-midi = { path = "crates/midi" }
craft-mime = { path = "crates/mime" }
craft-odf = { path = "crates/odf" }
craft-ods = { path = "crates/ods" }
craft-prc = { path = "crates/prc" }
craft-lottie = { path = "crates/lottie" }
craft-menu = { path = "crates/menu" }
craft-metafile = { path = "crates/metafile" }
craft-offcrypto = { path = "crates/offcrypto" }
craft-opc = { path = "crates/opc" }
craft-ora = { path = "crates/ora" }
craft-pptx = { path = "crates/pptx" }
craft-penpot = { path = "crates/penpot" }
craft-pcraft-format = { path = "crates/pcraft-format" }
craft-plotter = { path = "crates/plotter" }
craft-prepress = { path = "crates/prepress" }
craft-print = { path = "crates/print" }
craft-proof = { path = "crates/proof" }
craft-raster-codecs = { path = "crates/raster-codecs" }
craft-psd = { path = "crates/psd" }
craft-pst = { path = "crates/pst" }
craft-quit = { path = "crates/quit" }
craft-rtf = { path = "crates/rtf" }
craft-raw = { path = "crates/raw" }
craft-sheet = { path = "crates/sheet" }
craft-sketch = { path = "crates/sketch" }
craft-settings = { path = "crates/settings" }
craft-silhouette-studio = { path = "crates/silhouette-studio" }
craft-svg = { path = "crates/svg" }
craft-svg-paths = { path = "crates/svg-paths" }
craft-stream-codecs = { path = "crates/stream-codecs" }
craft-text = { path = "crates/text" }
craft-tga = { path = "crates/tga" }
craft-timeline = { path = "crates/timeline" }
craft-tiff = { path = "crates/tiff" }
craft-metadata = { path = "crates/metadata" }
craft-ui = { path = "crates/ui" }
craft-update = { path = "crates/update" }
craft-vcard = { path = "crates/vcard" }
craft-vectorcraft-format = { path = "crates/vectorcraft-format" }
craft-vectordrawable = { path = "crates/vectordrawable" }
craft-xls = { path = "crates/xls" }
craft-wordmodel = { path = "crates/wordmodel" }
craft-xlsx = { path = "crates/xlsx" }
craft-xcf = { path = "crates/xcf" }
craft-xml = { path = "crates/xml" }
craft-zip = { path = "crates/zip" }
craft-y4m = { path = "crates/y4m" }
craft-epub = { path = "crates/epub" }
craft-ews = { path = "crates/ews" }
craft-video = { path = "crates/video" }
craft-web-api = { path = "crates/web-api" }
craft-window = { path = "crates/window" }
craft-web-host = { path = "crates/web-host" }
craft-webp = { path = "crates/webp" }
egui = { version = "0.37", default-features = false }
md5 = { package = "md-5", version = "0.10", default-features = false }
rayon = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
proptest = "1"
# Character sets of the WHATWG Encoding Standard (craft-mime). (Apache-2.0 OR MIT) AND BSD-3-Clause.
encoding_rs = "0.8"
# All date/time conversion goes through chrono (no hand-rolled calendar code beyond the 400-year range extension; AGENTS.md).
chrono = { version = "0.4.45", default-features = false, features = ["std"] }
[workspace.lints.rust]
unsafe_code = "forbid"
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(craft_pdf_unicode_fixtures)"] }
[workspace.lints.clippy]
cognitive_complexity = "deny"
too_many_arguments = "deny"
wildcard_imports = "deny"
dbg_macro = "warn"
todo = "warn"
[patch.crates-io]
krilla = { path = "vendor/krilla" }
hayro = { path = "vendor/hayro" }
hayro-interpret = { path = "vendor/hayro-interpret" }
hayro-syntax = { path = "vendor/hayro-syntax" }
hayro-jbig2 = { path = "vendor/hayro-jbig2" }
hayro-cmap = { path = "vendor/hayro-cmap" }
hayro-postscript = { path = "vendor/hayro-postscript" }
linesweeper = { path = "vendor/linesweeper" }
ecolor = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
emath = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
epaint = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
epaint_default_fonts = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui-winit = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui-wgpu = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_glow = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_extras = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_kittest = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_system_font_provider = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
eframe = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_demo_lib = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_inspection = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
winit = { git = "https://github.com/storytold/winit.git", rev = "a517b3846ee8457d84ee4975110bfda6797c44dc" }
# symphonia's FLAC decoder restores LPC samples as `residual + (prediction as i32)`. In a valid
# 32-bit stream the prediction can leave the i32 range while the sum does not, so a debug build
# panics where a release build wraps to the right sample. Apps that decode 32-bit FLAC through
# craft-audio's `decode` need the same override in their own workspace.
[profile.dev.package.symphonia-bundle-flac]
overflow-checks = false
# Codec hot loops: the oracle and conformance tests of a debug build take minutes below opt-level 3.
[profile.dev.package.craft-video]
opt-level = 3
# The object-stream parser follows nesting 384 levels deep: unoptimised, its frames overflow the
# 2 MiB stack of a test thread. The apps this reader came from build their crates at this level.
[profile.dev.package.craft-affinity]
opt-level = 1