mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-13 22:12:12 +00:00
* craft-affinity: bounded reader for native Affinity documents, moved from VectorCraft The reader of .af, .afdesign, .afphoto and .afpub files (archive, object stream and document model) as it is in storytold/vectorcraft at 6e873b80 (crates/affinity), under a neutral name. Its corpus tests read the pinned public documents scripts/fetch-affinity-corpus.sh fetches. * craft-affinity: fold in what only PhotoCraft's copy of the reader had From storytold/photocraft at 63b641b5 (crates/affinity), onto the VectorCraft copy: - Special shapes: clouds, hearts, cogs, callouts, arrows, double stars, tears, crescents, diamonds and segments come in as their own outlines, not their bounding ellipse. - Null slots of object lists are charged to the document's work before a list is scanned, on every visit of a shared object (children, attachments, effects, compound operands, page lists, paint lists, gradient colours, text blocks and runs, table cells, tile lists). - A colour or gradient position record is decoded only as far as its components are read. - 16-bit and 8-bit planes are interleaved through tables, not an f64 for each pixel. - Limits::max_pixel_bytes: the caller sets what the pixel layers of one import may hold. - Pixels::cmyka8_to_rgba8 for a caller without colour management. The crate README and docs describe the model on its own terms. * craft-affinity: a callout with a right-to-left box no longer panics; an oversized shape imports as its box Ported from storytold/photocraft#10473 by DJHoltkamp. A callout rectangle clamped its tail with clamp(x0, x1), which panics when the box is stored right to left. A box with finite corners whose size overflows gave infinite or NaN outline points; it now imports as its box with a warning. Also drops the inflated doc.dat once it is parsed.
53 lines
1.7 KiB
Rust
53 lines
1.7 KiB
Rust
//! Reader for native Affinity documents (`.af`, and `.afdesign`/`.afphoto`/`.afpub` from
|
|
//! Affinity 1 and 2): the archive container, the tagged object stream in `doc.dat`, and the
|
|
//! part of the document model the crate README lists, as a neutral [`Document`].
|
|
//!
|
|
//! Layouts follow the MIT-licensed afread reference and were checked against public documents
|
|
//! saved by Affinity 1.x to 3.x (container versions 8 to 12); see the crate README for provenance
|
|
//! and the exact supported subset. Nothing here writes Affinity files.
|
|
#![forbid(unsafe_code)]
|
|
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
|
|
|
use std::fmt;
|
|
|
|
mod access;
|
|
pub mod container;
|
|
mod geometry;
|
|
pub mod model;
|
|
pub mod overlay;
|
|
pub mod paint;
|
|
pub mod preview;
|
|
mod raster;
|
|
mod shapes;
|
|
pub mod stream;
|
|
#[cfg(any(test, feature = "synth"))]
|
|
pub mod synth;
|
|
mod text;
|
|
|
|
pub use container::{Archive, Limits, MAGIC, is_affinity};
|
|
pub use model::{Document, read};
|
|
pub use preview::{MAX_PREVIEW_BYTES, MAX_PREVIEW_DIMENSION, Preview, preview};
|
|
|
|
/// Why a file could not be read. Messages are short reasons; callers add advice.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum Error {
|
|
Malformed(&'static str),
|
|
Unsupported(&'static str),
|
|
Limit(&'static str),
|
|
}
|
|
|
|
impl fmt::Display for Error {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Self::Malformed(s) => write!(f, "damaged Affinity file: {s}"),
|
|
Self::Unsupported(s) => write!(f, "unsupported Affinity file: {s}"),
|
|
Self::Limit(s) => write!(f, "Affinity file exceeds a safety limit: {s}"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for Error {}
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|