pdf-min 0.1.16

Very minimal crate for writing PDFs
Documentation
//!# Test example
//!
//! ```
//!      use pdf_min::{Writer, html, writer::Fetcher, image::{ImageSpec,Image}};
//!      struct MyFetcher;
//!      impl Fetcher for MyFetcher {
//!         fn image(&mut self, w: &mut Writer, _name: &str) -> Image {         
//!             let mut data = Vec::new();
//!             for i in 0..3 * 16 * 16 {
//!                 data.push( i as u8 );  // Red
//!                 data.push( (i + 85 ) as u8 ); // Green
//!                 data.push( (i + 170 ) as u8 ); // Blue
//!             }
//!             let ims = ImageSpec{ data: &data, width:16, height:16, 
//!                 bits_per_component:8, color_space: b"/DeviceRGB", other: b"" };
//!             Image::new( &ims, &mut w.b )
//!         }
//!      }
//!      let mut w = Writer::default();
//!      w.b.nocomp = true;
//!      w.font_size = 20;
//!      w.fetcher = Some(Box::new(MyFetcher));
//!   
//!      // Draw text with image
//!      html( &mut w, b"<p>Image <img width=32 src=myimg> Text after image" );
//!      let bytes = w.finish();
//!   
//!      use std::fs::File;
//!      use std::io::prelude::*;
//!   
//!      let mut file = File::create("image_test.pdf").unwrap();
//!      file.write_all(bytes).unwrap();
//! ```

use crate::*;
use crate::BasicPdfWriter;
use crate::page::Page;
use format_bytes::write_bytes as wb;

/// PDF image specification - byte data and attributes that describe how image is encoded.
pub struct ImageSpec<'a> {
    /// Image data - length is width * height * (bits_per_component/8) * 3 (for RGB).
    pub data: &'a [u8],
    /// Width
    pub width: Px,
    /// Height
    pub height: Px,
    /// Bits per component, usually 8
    pub bits_per_component: u8,
    /// Color space, such as b"/DeviceGray", b"/DeviceRGB", b"/DeviceCMYK"
    pub color_space: &'a [u8],
    /// Any other attributes, e.g. b"/Filter/DCT" for a jpeg
    pub other: &'a [u8],
}

/// PDF image - obj id, width and height
pub struct Image {
    /// PDF obj id
    pub obj: usize,
    /// Width
    pub width: Px,
    /// Height
    pub height: Px,
}

impl Image {
    /// Writes the specified image attributes and data to the PDF, returns Image with obj id, width and height.
    pub fn new(s: &ImageSpec, w: &mut BasicPdfWriter) -> Image {
        let obj = w.begin();
        let _ = wb!(
            &mut w.b,
            b"<</Type/XObject/Subtype/Image/Width {}/Height {}/ColorSpace{}/BitsPerComponent {}/Length {}{}>>stream\n",
            s.width, s.height, s.color_space, s.bits_per_component, s.data.len(), s.other
        );
        w.b.extend_from_slice(s.data);
        w.b.extend_from_slice(b"\nendstream");
        w.end();
        Image { obj, width: s.width, height: s.height }
    }

    /// Draw image on page.
    pub fn draw(&self, page: &mut Page, x: f32, y: f32, scale: f32) {
        let w = (self.width as f32) * scale;
        let h = (self.height as f32) * scale;
        page.xobjs.insert(self.obj);
        let _ = wb!(
            &mut page.os,
            b"\nq {} 0 0 {} {} {} cm /X{} Do Q",
            w, h, x, y, self.obj
        );
    }
}