mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-25 10:17:02 -06:00
File › Open, Other Library… and the User Defined library folder read .ase files. Colors keep their model, global and spot colors stay global and spot, and color groups stay groups. The library readers take a file's bytes. On the web, File › Open passes a swatch library file to swatch.library.load as dataBase64 instead of as lossy UTF-8 text. Swatch and group names in a library are now unique, in .gpl files too. Add to Swatches puts each color group of a library into one document group when the document already has a swatch with the group's name. The library fuzz helpers fail when a command panics.
62 lines
2.3 KiB
Rust
62 lines
2.3 KiB
Rust
//! Hand-written swatch exchange (`.ase`) files for swatch library tests: version 1.0, big-endian,
|
||
//! with colors in each model and color type, and color groups.
|
||
|
||
/// One block of a swatch exchange file.
|
||
#[derive(Clone, Debug)]
|
||
pub enum Block<'a> {
|
||
/// A color group starts (its name).
|
||
GroupStart(&'a str),
|
||
/// The open color group ends.
|
||
GroupEnd,
|
||
/// A color: its name, model (`b"RGB "`, `b"CMYK"`, `b"LAB "` or `b"Gray"`), components and
|
||
/// color type (0 global, 1 spot, 2 process).
|
||
Color(&'a str, &'a [u8; 4], &'a [f32], u16),
|
||
}
|
||
|
||
/// A name: a `u16` count of UTF-16 code units, the terminating zero included, then the units.
|
||
fn name(out: &mut Vec<u8>, name: &str) {
|
||
let units: Vec<u16> = name.encode_utf16().chain([0]).collect();
|
||
out.extend(u16::try_from(units.len()).unwrap().to_be_bytes());
|
||
out.extend(units.iter().flat_map(|u| u.to_be_bytes()));
|
||
}
|
||
|
||
/// A swatch exchange file of `blocks`.
|
||
pub fn ase(blocks: &[Block]) -> Vec<u8> {
|
||
let mut out = b"ASEF\0\x01\0\0".to_vec();
|
||
out.extend(u32::try_from(blocks.len()).unwrap().to_be_bytes());
|
||
for b in blocks {
|
||
let mut body = vec![];
|
||
let kind: u16 = match b {
|
||
Block::GroupStart(n) => {
|
||
name(&mut body, n);
|
||
0xC001
|
||
}
|
||
Block::GroupEnd => 0xC002,
|
||
Block::Color(n, model, values, kind) => {
|
||
name(&mut body, n);
|
||
body.extend(*model);
|
||
body.extend(values.iter().flat_map(|v| v.to_be_bytes()));
|
||
body.extend(kind.to_be_bytes());
|
||
0x0001
|
||
}
|
||
};
|
||
out.extend(kind.to_be_bytes());
|
||
out.extend(u32::try_from(body.len()).unwrap().to_be_bytes());
|
||
out.extend(body);
|
||
}
|
||
out
|
||
}
|
||
|
||
/// A library of four colors: "Sky" (global RGB) and "Ink" (spot CMYK), then the group "Neutrals"
|
||
/// of the process colors "Mist" (Gray, 25% ink) and "Clay" (Lab 50, 20, −30).
|
||
pub fn sample() -> Vec<u8> {
|
||
ase(&[
|
||
Block::Color("Sky", b"RGB ", &[0.0, 0.5, 1.0], 0),
|
||
Block::Color("Ink", b"CMYK", &[1.0, 0.5, 0.0, 0.2], 1),
|
||
Block::GroupStart("Neutrals"),
|
||
Block::Color("Mist", b"Gray", &[0.75], 2),
|
||
Block::Color("Clay", b"LAB ", &[0.5, 20.0, -30.0], 2),
|
||
Block::GroupEnd,
|
||
])
|
||
}
|