use crate::svg::{SvgParser, SvgRasterizer};
use super::png_writer::to_png;
pub const DEFAULT_SIZES: [u32; 6] = [16, 32, 48, 64, 128, 256];
pub fn to_zip(svg: &str, sizes: &[u32]) -> Vec<u8> {
let sizes = if sizes.is_empty() { &DEFAULT_SIZES } else { sizes };
let doc = SvgParser::parse(svg);
let entries: Vec<(String, Vec<u8>)> = sizes
.iter()
.map(|size| {
let pixmap = SvgRasterizer::rasterize(&doc, *size).expect("favicon PNG 光栅化失败");
(format!("avatar-{}.png", size), to_png(&pixmap))
})
.collect();
let mut buf = Vec::new();
let mut central = Vec::new();
for (name, data) in &entries {
let offset = buf.len() as u32;
let crc = crc32fast::hash(data);
write_le32(&mut buf, 0x04034b50);
write_le16(&mut buf, 20);
write_le16(&mut buf, 0x0800);
write_le16(&mut buf, 0); write_le16(&mut buf, 0); write_le16(&mut buf, 0x0021); write_le32(&mut buf, crc);
write_le32(&mut buf, data.len() as u32);
write_le32(&mut buf, data.len() as u32);
write_le16(&mut buf, name.len() as u16);
write_le16(&mut buf, 0);
buf.extend_from_slice(name.as_bytes());
buf.extend_from_slice(data);
write_le32(&mut central, 0x02014b50);
write_le16(&mut central, 20); write_le16(&mut central, 20); write_le16(&mut central, 0x0800);
write_le16(&mut central, 0);
write_le16(&mut central, 0);
write_le16(&mut central, 0x0021);
write_le32(&mut central, crc);
write_le32(&mut central, data.len() as u32);
write_le32(&mut central, data.len() as u32);
write_le16(&mut central, name.len() as u16);
write_le16(&mut central, 0);
write_le16(&mut central, 0);
write_le16(&mut central, 0);
write_le16(&mut central, 0);
write_le32(&mut central, 0);
write_le32(&mut central, offset);
central.extend_from_slice(name.as_bytes());
}
let cd_offset = buf.len() as u32;
buf.extend_from_slice(¢ral);
write_le32(&mut buf, 0x06054b50);
write_le16(&mut buf, 0); write_le16(&mut buf, 0); write_le16(&mut buf, entries.len() as u16);
write_le16(&mut buf, entries.len() as u16);
write_le32(&mut buf, central.len() as u32);
write_le32(&mut buf, cd_offset);
write_le16(&mut buf, 0); buf
}
pub fn to_ico(svg: &str, sizes: &[u32]) -> Vec<u8> {
let sizes = if sizes.is_empty() { &DEFAULT_SIZES } else { sizes };
let doc = SvgParser::parse(svg);
let pngs: Vec<Vec<u8>> = sizes
.iter()
.map(|size| {
let pixmap = SvgRasterizer::rasterize(&doc, *size).expect("ICO PNG 光栅化失败");
to_png(&pixmap)
})
.collect();
let mut offset: u32 = 6 + 16 * sizes.len() as u32; let mut bos = Vec::with_capacity(offset as usize + 64 * 1024);
write_le16(&mut bos, 0);
write_le16(&mut bos, 1);
write_le16(&mut bos, sizes.len() as u16);
for (i, size) in sizes.iter().enumerate() {
let s = *size;
bos.push(if s >= 256 { 0 } else { s as u8 }); bos.push(if s >= 256 { 0 } else { s as u8 }); bos.push(0); bos.push(0); write_le16(&mut bos, 1); write_le16(&mut bos, 32); write_le32(&mut bos, pngs[i].len() as u32); write_le32(&mut bos, offset); offset += pngs[i].len() as u32;
}
for png in &pngs {
bos.extend_from_slice(png);
}
bos
}
fn write_le16(out: &mut Vec<u8>, v: u16) {
out.push((v & 0xFF) as u8);
out.push((v >> 8) as u8);
}
fn write_le32(out: &mut Vec<u8>, v: u32) {
out.push((v & 0xFF) as u8);
out.push((v >> 8) as u8);
out.push((v >> 16) as u8);
out.push((v >> 24) as u8);
}