chiark / gitweb /
bundles: Parse size of out of our generated usvgs, wip for base64
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 22 May 2021 20:07:52 +0000 (21:07 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 22 May 2021 21:10:35 +0000 (22:10 +0100)
This is not really useful atm, but it proves the principle.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Cargo.lock
Cargo.toml
src/bundles.rs

index 9f3095bea6f4cb44d22c73f0b0c3e00bb7f0b8ad..e7178559cd083a07fce3778b59d9296b677971ec 100644 (file)
@@ -2384,6 +2384,7 @@ dependencies = [
  "url 2.2.2",
  "usvg",
  "vecdeque-stableix",
+ "xmlparser",
  "zip",
 ]
 
index 3b253ad6a4c77683bbb34b77d8aabddfc68b56b0..c9f6a9293130783b0edc8628eff128c6d8a0d926 100644 (file)
@@ -82,6 +82,7 @@ unicase="2"
 unicode-width="0.1"
 url="2"
 vecdeque-stableix="1"
+xmlparser = "0.13"
 zip="0.5"
 
 enum-map     = { version="1"    , features=["serde"       ] }
index 1cd162661bc45c15365dd22e1f4d5e649e68acb6..dd2bd8f0edc6944ba7bc48eb19126560582968a7 100644 (file)
@@ -752,6 +752,53 @@ fn image_usvg(zfname: &str, input: File, output: File,
   output.flush().context("flush output?").map_err(IE::from)?;
 }
 
+#[throws(InternalError)]
+fn usvg_size(f: &mut BufReader<File>) -> [f64;2] {
+  let mut buf = [0; 1024];
+  f.read(&mut buf).context("read start of usvg to get size")?;
+
+  let s = str::from_utf8(&buf).unwrap_or_else(
+    |e| str::from_utf8(&buf[0.. e.valid_up_to()]).unwrap());
+  
+  let mut stream = xmlparser::Tokenizer::from(s);
+  let mut token = || Ok::<_,AE>(
+    stream.next().ok_or_else(||anyhow!("eof or too far"))??
+  );
+  use xmlparser::Token as XT;
+  (|| Ok::<_,AE>( loop {
+    match token()? {
+      XT::ElementStart { local,.. } => {
+        ensure_eq!( local.as_str(), "svg" );
+        break;
+      },
+      _ => { },
+    }
+  }))().context("looking for svg element")?;
+
+  let mut size: [Option<f64>; 2] = default();
+  (|| Ok::<_,AE>( loop {
+    match token()? {
+      XT::Attribute { local, value, .. } => {
+        size[match local.as_str() {
+          "width" => 0,
+          "height" => 1,
+          _ => continue,
+        }] = Some(
+          value.parse().context("parse width/height")?
+        );
+
+        if_chain!{
+          if let Some(width)  = size[0];
+          if let Some(height) = size[1];
+          then { break [width,height] }
+        }
+      },
+      XT::ElementEnd {..} => throw!(anyhow!("not found")),
+      _ => { }
+    }
+  }))().context("looking for width/height attributes")?
+}
+
 #[throws(LE)]
 fn make_usvg(za: &mut IndexedZip, progress_count: &mut usize,
              mut for_progress: &mut dyn progress::Originator,
@@ -798,6 +845,9 @@ fn make_usvg(za: &mut IndexedZip, progress_count: &mut usize,
           zf.name(), got.status, String::from_utf8_lossy(&got.stderr)
         )));
       }
+      let t_f = File::open(&usvg_path).context("reopen").map_err(IE::from)?;
+      let size = usvg_size(&mut BufReader::new(t_f))?;
+      dbgc!(size);
     },
     PF::Png => image_usvg(zf.name(),input,output, IF::Png, "image/png")?,
   }