mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-12 08:52:32 +00:00
PhotoCraft's `photocraft-psd` crate (crates/psd at storytold/photocraft 63b641b55e54bf8f5c83efd977fdb16a2c255431) as `craft-psd`: the lossless PSD/PSB model, reader, writer and builder, descriptors, the Photoshop resource files that share its primitives (.abr, .asl, .aco, .act, .ase, .grd, .pat, .atn, .csh, .shc) and the Photoshop blocks of a layered TIFF. The crate had no dependency on any other PhotoCraft crate. Code is unchanged apart from the crate name, craft-libs' rustfmt width, comments that named other PhotoCraft crates, issue references (now `photocraft#N`), and the corpus tests' directory (`CRAFT_PSD_CORPUS` or `corpus/` at the workspace root). Tests, proptests, fuzz targets and fixtures move with it. Part of #778, #786.
88 lines
3.9 KiB
Rust
88 lines
3.9 KiB
Rust
//! Print the actions and steps of `.atn` files, one event per line, with the top-level keys of
|
|
//! each step's descriptor: `cargo run -p craft-psd --example atn_dump -- set.atn…`
|
|
//!
|
|
//! Handy when adding a Photoshop event to the engine's `.atn` import table: it shows the event
|
|
//! id, the panel name and the parameter keys Photoshop recorded.
|
|
|
|
use craft_psd::atn;
|
|
use craft_psd::descriptor::{Descriptor, ReferenceItem, Value};
|
|
|
|
fn summary(v: &Value) -> String {
|
|
match v {
|
|
Value::Integer(i) => i.to_string(),
|
|
Value::Double(d) => format!("{d}"),
|
|
Value::UnitFloat { unit, value } => format!("{value}{}", String::from_utf8_lossy(unit)),
|
|
Value::Boolean(b) => b.to_string(),
|
|
Value::Text(t) => format!("{:?}", t.to_string_lossy()),
|
|
Value::Enumerated { type_id, value } => {
|
|
format!("{}.{}", String::from_utf8_lossy(type_id.as_bytes()), String::from_utf8_lossy(value.as_bytes()))
|
|
}
|
|
Value::Descriptor(d) | Value::GlobalObject(d) => format!("{{{}}}", keys(d)),
|
|
Value::List(l) => format!("[{}]", l.iter().map(summary).collect::<Vec<_>>().join(", ")),
|
|
Value::Reference(r) => format!("ref[{}]", r.iter().map(reference).collect::<Vec<_>>().join(" ")),
|
|
other => format!("{other:?}").chars().take(40).collect(),
|
|
}
|
|
}
|
|
|
|
fn id(i: &craft_psd::descriptor::Id) -> String {
|
|
String::from_utf8_lossy(i.as_bytes()).trim().to_string()
|
|
}
|
|
|
|
fn reference(item: &ReferenceItem) -> String {
|
|
match item {
|
|
ReferenceItem::Property { class, key } => format!("prop({},{})", id(&class.class_id), id(key)),
|
|
ReferenceItem::Class(c) => format!("Clss({})", id(&c.class_id)),
|
|
ReferenceItem::Enumerated { class, type_id, value } => format!("Enmr({},{}.{})", id(&class.class_id), id(type_id), id(value)),
|
|
ReferenceItem::Offset { class, offset } => format!("rele({},{offset})", id(&class.class_id)),
|
|
ReferenceItem::Identifier { class, id: v } => format!("Idnt({},{v})", id(&class.class_id)),
|
|
ReferenceItem::Index { class, index } => format!("indx({},{index})", id(&class.class_id)),
|
|
ReferenceItem::Name { class, name } => format!("name({},{:?})", id(&class.class_id), name.to_string_lossy()),
|
|
}
|
|
}
|
|
|
|
fn keys(d: &Descriptor) -> String {
|
|
d.items.iter().map(|(k, v)| format!("{}={}", String::from_utf8_lossy(k.as_bytes()), summary(v))).collect::<Vec<_>>().join(" ")
|
|
}
|
|
|
|
fn main() {
|
|
let mut failed = false;
|
|
for path in std::env::args().skip(1) {
|
|
let bytes = match std::fs::read(&path) {
|
|
Ok(b) => b,
|
|
Err(e) => {
|
|
eprintln!("{path}: {e}");
|
|
failed = true;
|
|
continue;
|
|
}
|
|
};
|
|
match atn::parse(&bytes) {
|
|
Ok(f) => {
|
|
println!(
|
|
"== {path}: set {:?}, {} actions{}{}",
|
|
f.name.to_string_lossy(),
|
|
f.actions.len(),
|
|
f.encoding.as_deref().map(|e| format!(", names in {e}")).unwrap_or_default(),
|
|
if f.warnings.is_empty() { String::new() } else { format!(" ({})", f.warnings.join("; ")) }
|
|
);
|
|
for a in &f.actions {
|
|
println!(" action {:?} ({} steps)", a.name.to_string_lossy(), a.items.len());
|
|
for item in &a.items {
|
|
let flags = format!("{}{}", if item.enabled { "" } else { " off" }, if item.with_dialog { " dialog" } else { "" });
|
|
match &item.descriptor {
|
|
Some(d) => println!(" {:<22} {:<28}{flags} {}", item.event.id(), f.item_label(item), keys(d)),
|
|
None => println!(" {:<22} {:<28}{flags}", item.event.id(), f.item_label(item)),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
println!("== {path}: {e}");
|
|
failed = true;
|
|
}
|
|
}
|
|
}
|
|
if failed {
|
|
std::process::exit(1);
|
|
}
|
|
}
|