Expand description
Document writer: a NEW PDF, one full-page JPEG per page, optional embedded ICC profile.
The editing half of this crate changes existing files; this module creates one from nothing, for print, slideshow and book exports that place a JPEG on every page.
use rightkit_pdf::write::Document;
let mut doc = Document::new("1.4")?;
let srgb = doc.add_icc_profile(srgb_profile_bytes, 3)?;
doc.add_jpeg_page(595.0, 842.0, jpeg_bytes, Some(srgb))?;
let pdf: Vec<u8> = doc.finish();
doc.write_to(path)?; // feature `edit`: rightkit-fs atomic replace§What is written
- The header is
%PDF-<version>(1.0 to 1.7) plus the binary-marker comment, then a classic cross-reference table (no object or xref streams), so a PDF 1.4 reader accepts it. - Per page:
/Pagewith/MediaBox [0 0 w h], a content streamq w 0 0 h 0 0 cm /Im0 Do Q, and an image XObject with/Filter /DCTDecode,/BitsPerComponent 8. The JPEG bytes are copied unchanged (no re-encoding). - Colour space:
/DeviceRGB(3 components) or/DeviceGray(1), or, when an ICC profile is chosen,[/ICCBased n 0 R]with the profile as a stream (/N,/Alternate). A profile is written once however many pages use it. - Deterministic: object numbers follow insertion order, no dates, no
/Info, and the trailer/IDis the SHA-256 of the body. The same calls give the same bytes.
§Limits
- JPEG: baseline, extended-sequential or progressive Huffman (SOF0, SOF1, SOF2), 8 bits per
component, 1 or 3 components. 4-component (CMYK/YCCK, whose Adobe inversion needs a
/Decodearray), 12-bit, lossless and arithmetic-coded files are refused, not guessed. The ICC profile’s component count must equal the JPEG’s. - The ICC profile is checked for the
acspsignature at byte 36 and a header of at least 128 bytes, not for validity. Streams are stored uncompressed (this module has no deflate). - One image per page, full page, no rotation or crop: the image is stretched to the media box, so pass the JPEG’s own aspect ratio.
- Text (feature
fonts, on by default):Document::add_fonttakes a TrueType font (glyf/loca outlines,.ttfor a TrueType collection face; CFF/OpenType-CFF is refused by the subsetter) andDocument::draw_textdraws a string with it. At finish each used font is subset to exactly the glyphs drawn (font::subset_for_pdf) and embedded as Type0 / CIDFontType2 /FontFile2,/Encoding /Identity-H,/CIDToGIDMap /Identity, a/Wwidths array and aToUnicodeCMap, so CJK or any covered script is real, selectable text. The string is shown as 2-byte glyph codes in a hex string; there is no shaping, kerning, bidi or line breaking (onedraw_textcall is one run at one point), and a character the font has no glyph for is refused (WriteError::MissingGlyph), never substituted. A font whose OS/2fsTypeforbids embedding or subsetting is refused. Text is painted after the page image. Subset tags and/BaseFontare derived from the font and the glyph set, so output stays deterministic. - The PDF is built in memory;
lopdfis used by the tests to read it back. - Not embedded: font hinting programs beyond what the subsetter keeps,
/CIDSet, glyph variations (a variable font is written at its default instance, as the subsetter does).
Structs§
- Document
- A PDF being built. See the module documentation.
- FontId
- Handle to a font added with
Document::add_font. - IccId
- Handle to an ICC profile added with
Document::add_icc_profile. - Jpeg
Info - What a JPEG header says.
- PageId
- Handle to a page added with
Document::add_page(its zero-based index).
Enums§
Constants§
- MAX_
PAGE_ SIDE_ PT - Longest page side accepted, in points (the PDF 1.4 implementation limit, 200 inches).