### Build PDF Content Streams Source: https://context7.com/typst/pdf-writer/llms.txt The `Content` builder creates PDF operators for page painting. Methods chain with `&mut Self`. Call `content.finish()` to get a `Buf` for `pdf.stream()`. ```rust use pdf_writer::{Content, Name, Str}; use pdf_writer::types::{LineCapStyle, LineJoinStyle, TextRenderingMode}; let mut content = Content::new(); // Graphics state content.save_state(); content.set_line_width(2.0); content.set_line_cap(LineCapStyle::RoundCap); content.set_line_join(LineJoinStyle::RoundJoin); content.set_stroke_rgb(0.2, 0.4, 0.8); content.set_fill_rgb(0.9, 0.1, 0.1); // Path construction and painting content.move_to(50.0, 50.0); content.line_to(200.0, 50.0); content.line_to(125.0, 180.0); content.close_path(); content.fill_nonzero_and_stroke(); // Rectangles content.rect(300.0, 300.0, 150.0, 100.0); content.set_dash_pattern([4.0, 2.0], 0.0); content.stroke(); // Text rendering content.begin_text(); content.set_font(Name(b"F1"), 16.0); content.set_text_rendering_mode(TextRenderingMode::FillStroke); content.set_char_spacing(1.0); content.next_line(50.0, 700.0); content.show(Str(b"Styled text")); // Positioned show with kerning adjustments content.show_positioned() .items() .show(Str(b"Ke")) .adjust(-80.0) // kern by -80 thousandths of text space .show(Str(b"rn")); content.end_text(); content.restore_state(); // Use the buffer let buf = content.finish(); println!("Content stream size: {} bytes", buf.as_slice().len()); ``` -------------------------------- ### Pdf::new / Pdf::with_settings Source: https://context7.com/typst/pdf-writer/llms.txt Creates a new PDF document builder with default or custom settings. `Pdf::new()` uses pretty-printing, while `Pdf::with_settings` allows disabling it for smaller output. `Pdf::with_capacity` pre-allocates buffer space. The `finish()` method serializes the document. ```APIDOC ## `Pdf::new` / `Pdf::with_settings` — Create a PDF document builder Creates the top-level document builder. `Pdf::new()` uses default settings (pretty-printing enabled, 8 KB initial buffer). `Pdf::with_settings` accepts a `Settings` struct to disable pretty-printing for smaller output. The resulting `Pdf` derefs to a `Chunk`, so all `Chunk` methods are available directly. ```rust use pdf_writer::{Pdf, Rect, Ref}; use pdf_writer::chunk::Settings; // Default builder (pretty output) let mut pdf = Pdf::new(); // Compact output for production (smaller file size) let mut pdf = Pdf::with_settings(Settings { pretty: false }); // Pre-allocate 64 KB for large documents let mut pdf = Pdf::with_capacity(64 * 1024); // Finish the document – writes xref table + trailer, returns Vec let bytes: Vec = pdf.finish(); std::fs::write("output.pdf", bytes).unwrap(); ``` ``` -------------------------------- ### Create PDF Document Builder Source: https://context7.com/typst/pdf-writer/llms.txt Use `Pdf::new()` for default settings with pretty-printing, `Pdf::with_settings` to customize (e.g., disable pretty-printing for smaller output), or `Pdf::with_capacity` to pre-allocate buffer space. The `Pdf` struct dereferences to `Chunk`, making all `Chunk` methods directly available. ```rust use pdf_writer::{Pdf, Rect, Ref}; use pdf_writer::chunk::Settings; // Default builder (pretty output) let mut pdf = Pdf::new(); // Compact output for production (smaller file size) let mut pdf = Pdf::with_settings(Settings { pretty: false }); // Pre-allocate 64 KB for large documents let mut pdf = Pdf::with_capacity(64 * 1024); // Finish the document – writes xref table + trailer, returns Vec let bytes: Vec = pdf.finish(); std::fs::write("output.pdf", bytes).unwrap(); ``` -------------------------------- ### `Content` — Content stream builder Source: https://context7.com/typst/pdf-writer/llms.txt Builds page painting instructions (PDF operators) using a fluent API. All methods return `&mut Self` for chaining. The `finish()` method returns a `Buf` to be passed to `pdf.stream()`. ```APIDOC ## `Content` — Content stream builder `Content` builds the page painting instructions (PDF operators). All methods return `&mut Self` for chaining. Call `content.finish()` to get the `Buf`, then pass it to `pdf.stream(id, &buf)`. ```rust use pdf_writer::{Content, Name, Str}; use pdf_writer::types::{LineCapStyle, LineJoinStyle, TextRenderingMode}; let mut content = Content::new(); // Graphics state content.save_state(); content.set_line_width(2.0); content.set_line_cap(LineCapStyle::RoundCap); content.set_line_join(LineJoinStyle::RoundJoin); content.set_stroke_rgb(0.2, 0.4, 0.8); content.set_fill_rgb(0.9, 0.1, 0.1); // Path construction and painting content.move_to(50.0, 50.0); content.line_to(200.0, 50.0); content.line_to(125.0, 180.0); content.close_path(); content.fill_nonzero_and_stroke(); // Rectangles content.rect(300.0, 300.0, 150.0, 100.0); content.set_dash_pattern([4.0, 2.0], 0.0); content.stroke(); // Text rendering content.begin_text(); content.set_font(Name(b"F1"), 16.0); content.set_text_rendering_mode(TextRenderingMode::FillStroke); content.set_char_spacing(1.0); content.next_line(50.0, 700.0); content.show(Str(b"Styled text")); // Positioned show with kerning adjustments content.show_positioned() .items() .show(Str(b"Ke")) .adjust(-80.0) // kern by -80 thousandths of text space .show(Str(b"rn")); content.end_text(); content.restore_state(); // Use the buffer let buf = content.finish(); println!("Content stream size: {} bytes", buf.as_slice().len()); ``` ``` -------------------------------- ### Write Document Bookmarks with Chunk::outline Source: https://context7.com/typst/pdf-writer/llms.txt Creates an interactive bookmark tree in the PDF catalog. Each bookmark points to a specific page destination and can have child bookmarks. Ensure the `PageMode::UseOutlines` is set in the catalog to display the outline. ```rust use pdf_writer::{Finish, Name, Pdf, Rect, Ref}; use pdf_writer::types::PageMode; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let pages_id = Ref::new(2); let page_id = Ref::new(3); let outline_id = Ref::new(4); let item1_id = Ref::new(5); let item2_id = Ref::new(6); pdf.catalog(catalog_id) .pages(pages_id) .outlines(outline_id) .page_mode(PageMode::UseOutlines); pdf.pages(pages_id).kids([page_id]).count(1); pdf.page(page_id) .media_box(Rect::new(0.0, 0.0, 595.0, 842.0)) .parent(pages_id) .resources(); // Root outline node pdf.outline(outline_id) .first(item1_id) .last(item2_id) .count(2); // Bookmark pointing to page top let dest_rect = Rect::new(0.0, 842.0, 595.0, 0.0); pdf.outline_item(item1_id) .title(pdf_writer::TextStr("Chapter 1")) .parent(outline_id) .next(item2_id) .dest_direct() .page(page_id) .xyz(Some(0.0), Some(842.0), None); pdf.outline_item(item2_id) .title(pdf_writer::TextStr("Chapter 2")) .parent(outline_id) .prev(item1_id) .dest_direct() .page(page_id) .xyz(Some(0.0), Some(400.0), None); std::fs::write("target/outline.pdf", pdf.finish()).unwrap(); ``` -------------------------------- ### Set Transparency and Blend Mode with ExtGraphicsState Source: https://context7.com/typst/pdf-writer/llms.txt Use `Chunk::ext_graphics` to write an external graphics state dictionary, controlling transparency with `non_stroking_alpha` and `stroking_alpha`, and compositing effects with `blend_mode`. Ensure the state is applied to the page resources. ```rust use pdf_writer::{Content, Name, Pdf, Rect, Ref}; use pdf_writer::types::BlendMode; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let pages_id = Ref::new(2); let page_id = Ref::new(3); let content_id = Ref::new(4); let ext_gs_id = Ref::new(5); let state_name = Name(b"GS1"); pdf.catalog(catalog_id).pages(pages_id); pdf.pages(pages_id).kids([page_id]).count(1); let mut page = pdf.page(page_id); page.media_box(Rect::new(0.0, 0.0, 400.0, 400.0)); page.parent(pages_id); page.contents(content_id); page.resources().ext_g_states().pair(state_name, ext_gs_id); page.finish(); // 50% transparent fill, Multiply blend mode pdf.ext_graphics(ext_gs_id) .non_stroking_alpha(0.5) .stroking_alpha(0.5) .blend_mode(BlendMode::Multiply); let mut content = Content::new(); content.set_parameters(state_name); content.set_fill_rgb(1.0, 0.0, 0.0); content.rect(50.0, 50.0, 300.0, 300.0); content.fill_nonzero(); pdf.stream(content_id, &content.finish()); std::fs::write("target/transparency.pdf", pdf.finish()).unwrap(); ``` -------------------------------- ### Serialize PDF to Bytes with Cross-Reference Table or Stream Source: https://context7.com/typst/pdf-writer/llms.txt Use `finish()` to generate PDF bytes with a classic cross-reference table. For PDF 1.5+ compatibility and potentially smaller file sizes, use `finish_with_xref_stream_and_filter()` to create a compressed cross-reference stream. Both methods panic if any indirect reference ID is reused. Ensure all necessary objects like catalog and page tree are added before finishing. ```rust use pdf_writer::{Filter, Pdf, Ref, XRefFilter}; use miniz_oxide::deflate::{compress_to_vec_zlib, CompressionLevel}; let catalog_id = Ref::new(1); let page_tree_id = Ref::new(2); let xref_id = Ref::new(3); let mut pdf = Pdf::new(); pdf.catalog(catalog_id).pages(page_tree_id); pdf.pages(page_tree_id).kids([]).count(0); // Option A: classic xref table let bytes = pdf.finish(); // Option B: compressed xref stream (PDF 1.5+) let mut pdf2 = Pdf::new(); pdf2.catalog(Ref::new(1)).pages(Ref::new(2)); pdf2.pages(Ref::new(2)).kids([]).count(0); let bytes2 = pdf2.finish_with_xref_stream_and_filter(xref_id, |data| { let level = CompressionLevel::DefaultLevel as u8; let compressed = compress_to_vec_zlib(data, level); (compressed, XRefFilter::Single(Filter::FlateDecode)) }); std::fs::write("target/out.pdf", bytes2).unwrap(); ``` -------------------------------- ### Write Document Metadata with Pdf::document_info Source: https://context7.com/typst/pdf-writer/llms.txt Use `Pdf::document_info` to register metadata such as title, author, and creation date with the PDF file trailer. Ensure all necessary IDs are initialized before calling. ```rust use pdf_writer::{Pdf, Ref, TextStr}; use pdf_writer::object::Date; let mut pdf = Pdf::new(); let info_id = Ref::new(1); let catalog_id = Ref::new(2); let pages_id = Ref::new(3); pdf.document_info(info_id) .title(TextStr("My Document")) .author(TextStr("Jane Doe")) .subject(TextStr("A demonstration PDF")) .creator(TextStr("my-app")) .creation_date( Date::new(2024) .month(6) .day(15) .hour(10) .minute(30) .second(0) .utc_offset_hour(0), ); pdf.catalog(catalog_id).pages(pages_id); pdf.pages(pages_id).kids([]).count(0); std::fs::write("target/info.pdf", pdf.finish()).unwrap(); ``` -------------------------------- ### Write PDF Pages and Page Trees Source: https://context7.com/typst/pdf-writer/llms.txt Use `pdf.pages(id)` to write a page tree node and `pdf.page(id)` for a leaf page. Set `media_box`, `parent`, `contents`, and `resources`. Pages are linked via the page tree's `kids` array. ```rust use pdf_writer::{Content, Pdf, Rect, Ref, Name, Str}; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let page_tree_id = Ref::new(2); let page_id = Ref::new(3); let font_id = Ref::new(4); let content_id = Ref::new(5); pdf.catalog(catalog_id).pages(page_tree_id); pdf.pages(page_tree_id).kids([page_id]).count(1); let mut page = pdf.page(page_id); page.media_box(Rect::new(0.0, 0.0, 595.0, 842.0)); // A4 page.parent(page_tree_id); page.contents(content_id); page.resources().fonts().pair(Name(b"F1"), font_id); page.finish(); pdf.type1_font(font_id).base_font(Name(b"Helvetica")); let mut content = Content::new(); content.begin_text(); content.set_font(Name(b"F1"), 14.0); content.next_line(50.0, 750.0); content.show(Str(b"Hello, PDF!")); content.end_text(); pdf.stream(content_id, &content.finish()); std::fs::write("target/page.pdf", pdf.finish()).unwrap(); ``` -------------------------------- ### pdf-writer Low-Level Dict, Array, Obj Writers Source: https://context7.com/typst/pdf-writer/llms.txt Shows how to use low-level Dict, Array, and Obj writers for arbitrary PDF structures when the typed API is insufficient. These writers allow direct manipulation of dictionary pairs and array items, ensuring structures are correctly finalized. ```rust use pdf_writer::{Name, Obj, Pdf, Ref, Str, TextStr, Finish}; let mut pdf = Pdf::new(); let obj_id = Ref::new(1); // Write an arbitrary dictionary as an indirect object { let mut dict = pdf.indirect(obj_id).dict(); dict.pair(Name(b"Type"), Name(b"MyType")); dict.pair(Name(b"Count"), 42_i32); dict.pair(Name(b"Flag"), true); dict.pair(Name(b"Title"), TextStr("A Title")); // Nested array via insert dict.insert(Name(b"Items")) .array() .item(Str(b"one")) .item(Str(b"two")) .item(3_i32); } // dict drops here, writing ">>\nendobj\n" // Write a raw array as an indirect object let arr_id = Ref::new(2); pdf.indirect(arr_id) .array() .item(1_i32) .item(2_i32) .item(3_i32); let _ = pdf.finish(); ``` -------------------------------- ### Create Empty A4 PDF Source: https://github.com/typst/pdf-writer/blob/main/README.md Generates a PDF file with a single, empty A4 page. Ensure the 'target' directory exists before running. ```rust use pdf_writer::{Pdf, Rect, Ref}; // Define some indirect reference ids we'll use. let catalog_id = Ref::new(1); let page_tree_id = Ref::new(2); let page_id = Ref::new(3); // Write a document catalog and a page tree with one A4 page that uses no resources. let mut pdf = Pdf::new(); pdf.catalog(catalog_id).pages(page_tree_id); pdf.pages(page_tree_id).kids([page_id]).count(1); pdf.page(page_id) .parent(page_tree_id) .media_box(Rect::new(0.0, 0.0, 595.0, 842.0)) .resources(); // Finish with cross-reference table and trailer and write to file. std::fs::write("target/empty.pdf", pdf.finish())?; ``` -------------------------------- ### Write Link Annotation with Chunk::annotation Source: https://context7.com/typst/pdf-writer/llms.txt Create interactive link annotations on a page using `Chunk::annotation`. Combine with an `Action` writer for URI actions. Ensure page resources, including fonts, are correctly set up. ```rust use pdf_writer::{Pdf, Rect, Ref, Str, TextStr}; use pdf_writer::types::{ActionType, AnnotationType, BorderType}; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let pages_id = Ref::new(2); let page_id = Ref::new(3); let annotation_id = Ref::new(4); let content_id = Ref::new(5); let font_id = Ref::new(6); pdf.catalog(catalog_id).pages(pages_id); pdf.pages(pages_id).kids([page_id]).count(1); let mut page = pdf.page(page_id); page.media_box(Rect::new(0.0, 0.0, 595.0, 842.0)); page.parent(pages_id); page.annotations([annotation_id]); page.resources().fonts().pair(pdf_writer::Name(b"F1"), font_id); page.finish(); pdf.type1_font(font_id).base_font(pdf_writer::Name(b"Helvetica")); // URI link annotation let mut ann = pdf.annotation(annotation_id); ann.subtype(AnnotationType::Link); ann.rect(Rect::new(50.0, 700.0, 200.0, 720.0)); ann.contents(TextStr("Visit Rust website")); ann.color_rgb(0.0, 0.0, 1.0); ann.action() .action_type(ActionType::Uri) .uri(Str(b"https://www.rust-lang.org/")); ann.border_style().width(1.0).style(BorderType::Underline); ann.finish(); let mut content = pdf_writer::Content::new(); content.begin_text(); content.set_font(pdf_writer::Name(b"F1"), 12.0); content.next_line(50.0, 703.0); content.show(Str(b"Visit Rust")); content.end_text(); pdf.stream(content_id, &content.finish()); std::fs::write("target/link.pdf", pdf.finish()).unwrap(); ``` -------------------------------- ### `Chunk::page` / `Chunk::pages` — Write pages and page trees Source: https://context7.com/typst/pdf-writer/llms.txt Write page tree nodes and leaf pages. Configure media box, parent, contents, and resources. Link multiple pages using the page tree's `kids` array. ```APIDOC ## `Chunk::page` / `Chunk::pages` — Write pages and page trees `pdf.pages(id)` writes a page tree node. `pdf.page(id)` writes a leaf page. Set `media_box` (the visible page area), `parent`, optional `contents` (stream ref), and `resources` (fonts, XObjects, etc.). Multiple pages are linked through the page tree's `kids` array. ```rust use pdf_writer::{Content, Pdf, Rect, Ref, Name, Str}; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let page_tree_id = Ref::new(2); let page_id = Ref::new(3); let font_id = Ref::new(4); let content_id = Ref::new(5); pdf.catalog(catalog_id).pages(page_tree_id); pdf.pages(page_tree_id).kids([page_id]).count(1); let mut page = pdf.page(page_id); page.media_box(Rect::new(0.0, 0.0, 595.0, 842.0)); // A4 page.parent(page_tree_id); page.contents(content_id); page.resources().fonts().pair(Name(b"F1"), font_id); page.finish(); pdf.type1_font(font_id).base_font(Name(b"Helvetica")); let mut content = Content::new(); content.begin_text(); content.set_font(Name(b"F1"), 14.0); content.next_line(50.0, 750.0); content.show(Str(b"Hello, PDF!")); content.end_text(); pdf.stream(content_id, &content.finish()); std::fs::write("target/page.pdf", pdf.finish()).unwrap(); ``` ``` -------------------------------- ### Write the Document Catalog Source: https://context7.com/typst/pdf-writer/llms.txt The `pdf.catalog(id)` method writes the mandatory document catalog and registers it for the file trailer. Chain `.pages(page_tree_id)` to link to the root of the page tree. Additional methods like `.page_layout()`, `.page_mode()`, and `.lang()` can be used to configure document-wide properties. ```rust use pdf_writer::{Pdf, Rect, Ref, TextStr}; use pdf_writer::types::{PageLayout, PageMode}; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let page_tree_id = Ref::new(2); pdf.catalog(catalog_id) .pages(page_tree_id) .page_layout(PageLayout::SinglePage) .page_mode(PageMode::UseOutlines) .lang(TextStr("en-US")); pdf.pages(page_tree_id).kids([]).count(0); std::fs::write("target/catalog.pdf", pdf.finish()).unwrap(); ``` -------------------------------- ### Parallel PDF Object Writing with `Chunk` Source: https://context7.com/typst/pdf-writer/llms.txt Demonstrates using `Chunk` to write PDF objects independently, allowing for parallel operations. The `Chunk` can be merged back into the main `Pdf` object using `extend`. IDs can be remapped using `renumber`. ```rust use std::collections::HashMap; use pdf_writer::{Chunk, Content, Name, Pdf, Rect, Ref}; let mut alloc = Ref::new(1); let mut pdf = Pdf::new(); let mut secondary = Chunk::new(); let page_tree_id = alloc.bump(); let page_id = alloc.bump(); let content_id = alloc.bump(); // Write page into the main pdf (borrows pdf mutably) let mut page = pdf.page(page_id); page.media_box(Rect::new(0.0, 0.0, 595.0, 842.0)); page.parent(page_tree_id); page.contents(content_id); page.finish(); // release the borrow // While page borrow is released, write to secondary let mut content = Content::new(); content.move_to(0.0, 0.0).line_to(595.0, 842.0).stroke(); secondary.stream(content_id, &content.finish()); // Merge and finish pdf.extend(&secondary); pdf.pages(page_tree_id).kids([page_id]).count(1); pdf.catalog(alloc.bump()).pages(page_tree_id); // Renumber IDs to consecutive range starting at 1 let mut next = Ref::new(1); let mut map = HashMap::new(); let renumbered_chunk = secondary.renumber(|old| { *map.entry(old).or_insert_with(|| next.bump()) }); std::fs::write("target/chunks.pdf", pdf.finish()).unwrap(); ``` -------------------------------- ### Pdf::finish / Pdf::finish_with_xref_stream Source: https://context7.com/typst/pdf-writer/llms.txt Serializes the PDF document into bytes. `finish()` creates a classic cross-reference table, while `finish_with_xref_stream` generates a compressed cross-reference stream (PDF 1.5+). Both methods panic if indirect reference IDs are reused. ```APIDOC ## `Pdf::finish` / `Pdf::finish_with_xref_stream` — Serialize to bytes `finish()` writes a classic cross-reference table and file trailer and returns the complete PDF bytes. `finish_with_xref_stream(xref_id)` writes a compressed cross-reference stream instead (PDF 1.5+, required when object streams are used). Both panic if any indirect reference ID was used more than once. ```rust use pdf_writer::{Filter, Pdf, Ref, XRefFilter}; use miniz_oxide::deflate::{compress_to_vec_zlib, CompressionLevel}; let catalog_id = Ref::new(1); let page_tree_id = Ref::new(2); let xref_id = Ref::new(3); let mut pdf = Pdf::new(); pdf.catalog(catalog_id).pages(page_tree_id); pdf.pages(page_tree_id).kids([]).count(0); // Option A: classic xref table let bytes = pdf.finish(); // Option B: compressed xref stream (PDF 1.5+) let mut pdf2 = Pdf::new(); pdf2.catalog(Ref::new(1)).pages(Ref::new(2)); pdf2.pages(Ref::new(2)).kids([]).count(0); let bytes2 = pdf2.finish_with_xref_stream_and_filter(xref_id, |data| { let level = CompressionLevel::DefaultLevel as u8; let compressed = compress_to_vec_zlib(data, level); (compressed, XRefFilter::Single(Filter::FlateDecode)) }); std::fs::write("target/out.pdf", bytes2).unwrap(); ``` ``` -------------------------------- ### `Chunk::outline` / `Chunk::outline_item` — Document bookmarks Source: https://context7.com/typst/pdf-writer/llms.txt Writes an interactive outline (bookmark tree) in the document catalog. Each `OutlineItem` points to a destination page and can have children. ```APIDOC ## `Chunk::outline` / `Chunk::outline_item` — Document bookmarks Writes an interactive outline (bookmark tree) in the document catalog. Each `OutlineItem` points to a destination page and can have children. ```rust use pdf_writer::{Finish, Name, Pdf, Rect, Ref}; use pdf_writer::types::PageMode; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let pages_id = Ref::new(2); let page_id = Ref::new(3); let outline_id = Ref::new(4); let item1_id = Ref::new(5); let item2_id = Ref::new(6); pdf.catalog(catalog_id) .pages(pages_id) .outlines(outline_id) .page_mode(PageMode::UseOutlines); pdf.pages(pages_id).kids([page_id]).count(1); pdf.page(page_id) .media_box(Rect::new(0.0, 0.0, 595.0, 842.0)) .parent(pages_id) .resources(); // Root outline node pdf.outline(outline_id) .first(item1_id) .last(item2_id) .count(2); // Bookmark pointing to page top let dest_rect = Rect::new(0.0, 842.0, 595.0, 0.0); pdf.outline_item(item1_id) .title(pdf_writer::TextStr("Chapter 1")) .parent(outline_id) .next(item2_id) .dest_direct() .page(page_id) .xyz(Some(0.0), Some(842.0), None); pdf.outline_item(item2_id) .title(pdf_writer::TextStr("Chapter 2")) .parent(outline_id) .prev(item1_id) .dest_direct() .page(page_id) .xyz(Some(0.0), Some(400.0), None); std::fs::write("target/outline.pdf", pdf.finish()).unwrap(); ``` ``` -------------------------------- ### Create Repeating Fill Patterns with Chunk::tiling_pattern Source: https://context7.com/typst/pdf-writer/llms.txt Defines a tiling pattern that can be used as a fill or stroke color. The pattern consists of a small tile that repeats across the specified area. The pattern must be registered in the page's resources and then applied using `set_fill_pattern` or `set_stroke_pattern`. ```rust use pdf_writer::{Content, Name, Pdf, Rect, Ref}; use pdf_writer::types::PaintType; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let pages_id = Ref::new(2); let page_id = Ref::new(3); let pattern_id = Ref::new(4); let content_id = Ref::new(5); let pat_name = Name(b"P1"); pdf.catalog(catalog_id).pages(pages_id); pdf.pages(pages_id).kids([page_id]).count(1); let mut page = pdf.page(page_id); page.media_box(Rect::new(0.0, 0.0, 300.0, 300.0)); page.parent(pages_id); page.contents(content_id); page.resources().patterns().pair(pat_name, pattern_id); page.finish(); // A 20×20 pt tile with a small blue circle let mut tile = Content::new(); tile.set_fill_rgb(0.0, 0.2, 0.8); tile.move_to(10.0, 15.0); tile.cubic_to(15.0, 15.0, 20.0, 10.0, 20.0, 10.0); tile.cubic_to(20.0, 5.0, 15.0, 0.0, 10.0, 0.0); tile.cubic_to(5.0, 0.0, 0.0, 5.0, 0.0, 10.0); tile.cubic_to(0.0, 15.0, 5.0, 15.0, 10.0, 15.0); tile.fill_nonzero(); pdf.tiling_pattern(pattern_id, &tile.finish()) .paint_type(PaintType::Colored) .tiling_type(pdf_writer::types::TilingType::ConstantSpacing) .bbox(Rect::new(0.0, 0.0, 20.0, 20.0)) .x_step(20.0) .y_step(20.0) .resources(); // Fill a rectangle with the pattern let mut content = Content::new(); content.set_fill_color_space(pdf_writer::types::ColorSpaceOperand::Pattern); content.set_fill_pattern([], pat_name); content.rect(10.0, 10.0, 280.0, 280.0); content.fill_nonzero(); pdf.stream(content_id, &content.finish()); std::fs::write("target/pattern.pdf", pdf.finish()).unwrap(); ``` -------------------------------- ### `Chunk::tiling_pattern` — Repeating fill patterns Source: https://context7.com/typst/pdf-writer/llms.txt Writes a tiling pattern that can be used as a fill or stroke color via `set_fill_pattern` / `set_stroke_pattern` in a content stream. ```APIDOC ## `Chunk::tiling_pattern` — Repeating fill patterns Writes a tiling pattern that can be used as a fill or stroke color via `set_fill_pattern` / `set_stroke_pattern` in a content stream. ```rust use pdf_writer::{Content, Name, Pdf, Rect, Ref}; use pdf_writer::types::PaintType; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let pages_id = Ref::new(2); let page_id = Ref::new(3); let pattern_id = Ref::new(4); let content_id = Ref::new(5); let pat_name = Name(b"P1"); pdf.catalog(catalog_id).pages(pages_id); pdf.pages(pages_id).kids([page_id]).count(1); let mut page = pdf.page(page_id); page.media_box(Rect::new(0.0, 0.0, 300.0, 300.0)); page.parent(pages_id); page.contents(content_id); page.resources().patterns().pair(pat_name, pattern_id); page.finish(); // A 20×20 pt tile with a small blue circle let mut tile = Content::new(); tile.set_fill_rgb(0.0, 0.2, 0.8); tile.move_to(10.0, 15.0); tile.cubic_to(15.0, 15.0, 20.0, 10.0, 20.0, 10.0); tile.cubic_to(20.0, 5.0, 15.0, 0.0, 10.0, 0.0); tile.cubic_to(5.0, 0.0, 0.0, 5.0, 0.0, 10.0); tile.cubic_to(0.0, 15.0, 5.0, 15.0, 10.0, 15.0); tile.fill_nonzero(); pdf.tiling_pattern(pattern_id, &tile.finish()) .paint_type(PaintType::Colored) .tiling_type(pdf_writer::types::TilingType::ConstantSpacing) .bbox(Rect::new(0.0, 0.0, 20.0, 20.0)) .x_step(20.0) .y_step(20.0) .resources(); // Fill a rectangle with the pattern let mut content = Content::new(); content.set_fill_color_space(pdf_writer::types::ColorSpaceOperand::Pattern); content.set_fill_pattern([], pat_name); content.rect(10.0, 10.0, 280.0, 280.0); content.fill_nonzero(); pdf.stream(content_id, &content.finish()); std::fs::write("target/pattern.pdf", pdf.finish()).unwrap(); ``` ``` -------------------------------- ### Pdf::document_info Source: https://context7.com/typst/pdf-writer/llms.txt Registers a document information dictionary (title, author, creation date, etc.) with the file trailer. ```APIDOC ## Pdf::document_info — Write document metadata Registers a document information dictionary (title, author, creation date, etc.) with the file trailer. ```rust use pdf_writer::{Pdf, Ref, TextStr}; use pdf_writer::object::Date; let mut pdf = Pdf::new(); let info_id = Ref::new(1); let catalog_id = Ref::new(2); let pages_id = Ref::new(3); pdf.document_info(info_id) .title(TextStr("My Document")) .author(TextStr("Jane Doe")) .subject(TextStr("A demonstration PDF")) .creator(TextStr("my-app")) .creation_date( Date::new(2024) .month(6) .day(15) .hour(10) .minute(30) .second(0) .utc_offset_hour(0), ); pdf.catalog(catalog_id).pages(pages_id); pdf.pages(pages_id).kids([]).count(0); std::fs::write("target/info.pdf", pdf.finish()).unwrap(); ``` ``` -------------------------------- ### Chunk::ext_graphics / ExtGraphicsState Source: https://context7.com/typst/pdf-writer/llms.txt Writes an external graphics state dictionary. Use `non_stroking_alpha` / `stroking_alpha` for transparency, `blend_mode` for compositing effects, and `soft_mask` for complex masking. ```APIDOC ## Chunk::ext_graphics / ExtGraphicsState — Transparency and graphics state Writes an external graphics state dictionary. Use `non_stroking_alpha` / `stroking_alpha` for transparency, `blend_mode` for compositing effects, and `soft_mask` for complex masking. ```rust use pdf_writer::{Content, Name, Pdf, Rect, Ref}; use pdf_writer::types::BlendMode; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let pages_id = Ref::new(2); let page_id = Ref::new(3); let content_id = Ref::new(4); let ext_gs_id = Ref::new(5); let state_name = Name(b"GS1"); pdf.catalog(catalog_id).pages(pages_id); pdf.pages(pages_id).kids([page_id]).count(1); let mut page = pdf.page(page_id); page.media_box(Rect::new(0.0, 0.0, 400.0, 400.0)); page.parent(pages_id); page.contents(content_id); page.resources().ext_g_states().pair(state_name, ext_gs_id); page.finish(); // 50% transparent fill, Multiply blend mode pdf.ext_graphics(ext_gs_id) .non_stroking_alpha(0.5) .stroking_alpha(0.5) .blend_mode(BlendMode::Multiply); let mut content = Content::new(); content.set_parameters(state_name); content.set_fill_rgb(1.0, 0.0, 0.0); content.rect(50.0, 50.0, 300.0, 300.0); content.fill_nonzero(); pdf.stream(content_id, &content.finish()); std::fs::write("target/transparency.pdf", pdf.finish()).unwrap(); ``` ``` -------------------------------- ### Write Raw and Compressed Streams Source: https://context7.com/typst/pdf-writer/llms.txt Use `pdf.stream(id, &buf)` to write stream objects. Auto-calculates `/Length`. Attach filters like `Filter::FlateDecode` for compression. Useful for content, CMaps, and profiles. ```rust use pdf_writer::{Content, Filter, Pdf, Rect, Ref}; use miniz_oxide::deflate::{compress_to_vec_zlib, CompressionLevel}; let mut pdf = Pdf::new(); let content_id = Ref::new(10); // Uncompressed stream let mut content = Content::new(); content.rect(10.0, 10.0, 100.0, 100.0); content.fill_nonzero(); pdf.stream(content_id, &content.finish()); // FlateDecode-compressed stream let raw_content = content.finish(); let level = CompressionLevel::DefaultLevel as u8; let compressed = compress_to_vec_zlib(raw_content.as_slice(), level); let compressed_id = Ref::new(11); pdf.stream(compressed_id, &compressed) .filter(Filter::FlateDecode); ``` -------------------------------- ### Ref Source: https://context7.com/typst/pdf-writer/llms.txt Manages indirect object references and ID allocation. `Ref::new(n)` creates a reference with a specific ID, while `Ref::bump()` provides a convenient bump allocator pattern for sequential ID generation. ```APIDOC ## `Ref` — Indirect object reference and ID allocator `Ref::new(n)` creates a typed indirect reference with a positive integer ID. `Ref::bump()` increments the ID in place and returns the old value, making it a convenient bump allocator. References are used everywhere you need to link objects together. ```rust use pdf_writer::Ref; // Manual allocation let catalog_id = Ref::new(1); let page_tree_id = Ref::new(2); let page_id = Ref::new(3); // Bump allocator pattern for dynamic documents let mut alloc = Ref::new(1); let catalog_id = alloc.bump(); // returns Ref(1), alloc is now Ref(2) let page_tree_id = alloc.bump(); // returns Ref(2), alloc is now Ref(3) let page_id = alloc.bump(); // returns Ref(3) let content_id = alloc.bump(); // returns Ref(4) println!("catalog = {}", catalog_id.get()); // 1 println!("next = {}", page_id.next().get()); // 4 ``` ``` -------------------------------- ### Chunk::annotation Source: https://context7.com/typst/pdf-writer/llms.txt Creates an annotation dictionary on a page. Combine with an Action writer for interactive links, URI actions, or launch actions. ```APIDOC ## Chunk::annotation — Write link and other annotations Creates an annotation dictionary on a page. Combine with an `Action` writer for interactive links, URI actions, or launch actions. ```rust use pdf_writer::{Pdf, Rect, Ref, Str, TextStr}; use pdf_writer::types::{ActionType, AnnotationType, BorderType}; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let pages_id = Ref::new(2); let page_id = Ref::new(3); let annotation_id = Ref::new(4); let content_id = Ref::new(5); let font_id = Ref::new(6); pdf.catalog(catalog_id).pages(pages_id); pdf.pages(pages_id).kids([page_id]).count(1); let mut page = pdf.page(page_id); page.media_box(Rect::new(0.0, 0.0, 595.0, 842.0)); page.parent(pages_id); page.annotations([annotation_id]); page.resources().fonts().pair(pdf_writer::Name(b"F1"), font_id); page.finish(); pdf.type1_font(font_id).base_font(pdf_writer::Name(b"Helvetica")); // URI link annotation let mut ann = pdf.annotation(annotation_id); ann.subtype(AnnotationType::Link); ann.rect(Rect::new(50.0, 700.0, 200.0, 720.0)); ann.contents(TextStr("Visit Rust website")); ann.color_rgb(0.0, 0.0, 1.0); ann.action() .action_type(ActionType::Uri) .uri(Str(b"https://www.rust-lang.org/")); ann.border_style().width(1.0).style(BorderType::Underline); ann.finish(); let mut content = pdf_writer::Content::new(); content.begin_text(); content.set_font(pdf_writer::Name(b"F1"), 12.0); content.next_line(50.0, 703.0); content.show(Str(b"Visit Rust")); content.end_text(); pdf.stream(content_id, &content.finish()); std::fs::write("target/link.pdf", pdf.finish()).unwrap(); ``` ``` -------------------------------- ### Pdf::catalog Source: https://context7.com/typst/pdf-writer/llms.txt Writes the document catalog, which is a required element for any valid PDF. It returns a `Catalog` writer and automatically registers it with the file trailer. The `.pages()` method links to the root of the page tree. ```APIDOC ## `Pdf::catalog` — Write the document catalog (required) Every valid PDF must have exactly one document catalog. `pdf.catalog(id)` returns a `Catalog` writer and also registers it with the file trailer automatically. Chain `.pages(page_tree_id)` to point to the page tree root. ```rust use pdf_writer::{Pdf, Rect, Ref, TextStr}; use pdf_writer::types::{PageLayout, PageMode}; let mut pdf = Pdf::new(); let catalog_id = Ref::new(1); let page_tree_id = Ref::new(2); pdf.catalog(catalog_id) .pages(page_tree_id) .page_layout(PageLayout::SinglePage) .page_mode(PageMode::UseOutlines) .lang(TextStr("en-US")); pdf.pages(page_tree_id).kids([]).count(0); std::fs::write("target/catalog.pdf", pdf.finish()).unwrap(); ``` ``` -------------------------------- ### pdf-writer Primitive Types: Name, Str, TextStr, Rect, Date Source: https://context7.com/typst/pdf-writer/llms.txt Demonstrates the usage of core primitive types in pdf-writer for representing PDF names, byte strings, Unicode text strings, rectangles, and dates. Ensure correct type usage for proper PDF encoding. ```rust use pdf_writer::{Date, Name, Rect, Str, TextStr}; // Name – rendered as /Helvetica let font_name = Name(b"Helvetica"); // Byte string – rendered as (Hello) or hex for non-ASCII let ascii_str = Str(b"Hello, PDF!"); let binary_str = Str(b"\xFF\xFE\x00\x41"); // hex-encoded in output // Unicode text string – UTF-16-BE with BOM for non-ASCII let title = TextStr("Hello"); // ASCII: stays as (Hello) let unicode = TextStr("こんにちは"); // encoded as // Rectangle [x1 y1 x2 y2] let a4 = Rect::new(0.0, 0.0, 595.28, 841.89); let corners = a4.to_quad_points(); // [x1,y1, x2,y1, x2,y2, x1,y2] // Date with full timezone info let date = Date::new(2024) .month(11) .day(28) .hour(14) .minute(30) .second(0) .utc_offset_hour(1) .utc_offset_minute(0); // Serialized: (D:20241128143000+01'00) ```