Repository: typst/typst
File: crates/typst-pdf/src/lib.rs (Rust)

Code before:
/// Returns the raw bytes making up the PDF file.
///
/// The `ident` parameter, if given, shall be a string that uniquely and stably
/// identifies the document. It should not change between compilations of the
/// same document.  **If you cannot provide such a stable identifier, just pass
/// `Smart::Auto` rather than trying to come up with one.** The CLI, for
/// example, does not have a well-defined notion of a long-lived project and as
/// such just passes `Smart::Auto`.
///
/// If an `ident` is given, the hash of it will be used to create a PDF document
/// identifier (the identifier itself is not leaked). If `ident` is `Auto`, a
/// hash of the document's title and author is used instead (which is reasonably
/// unique and stable).
///
/// The `timestamp`, if given, is expected to be the creation date of the
/// document as a UTC datetime. It will only be used if `set document(date: ..)`
/// is `auto`.
///
/// The `page_ranges` option specifies which ranges of pages should be exported
/// in the PDF. When `None`, all pages should be exported.
#[typst_macros::time(name = "pdf")]
pub fn pdf(
    document: &Document,
    ident: Smart<&str>,
    timestamp: Option<Datetime>,
    page_ranges: Option<Vec<Range<NonZeroUsize>>>,
) -> Vec<u8> {
    let mut ctx = PdfContext::new(document, page_ranges.map(PageRanges::new));
    page::construct_pages(&mut ctx, &document.pages);
    font::write_fonts(&mut ctx);
    image::write_images(&mut ctx);
    gradient::write_gradients(&mut ctx);
    extg::write_external_graphics_states(&mut ctx);
    pattern::write_patterns(&mut ctx);
    write_named_destinations(&mut ctx);
    page::write_page_tree(&mut ctx);
    page::write_global_resources(&mut ctx);
    write_catalog(&mut ctx, ident, timestamp);
    ctx.pdf.finish()
}

/// Context for exporting a whole PDF document.
struct PdfContext<'a> {
    /// The document that we're currently exporting.
    document: &'a Document,
    /// The writer we are writing the PDF into.
    pdf: Pdf,
    /// Content of exported pages.
    pages: Vec<Option<EncodedPage>>,
    /// Page ranges to export.
    /// When `None`, all pages are exported.

Review comment (suggestion):
In the web app, we encode it as:

```rust
ranges: Option<Vec<ExportRange>>
type ExportRange = RangeInclusive<Option<NonZeroUsize>>;
```

I think, ideally it be directly parsed as that in the `CompileCommand`.

Unforunately, `args.rs` can't use types from Typst because of the clap_mangen stuff ..., so we can probably not directly use a shared type.

Code after:
pub fn pdf(
    document: &Document,
    ident: Smart<&str>,
    timestamp: Option<Datetime>,
    page_ranges: Option<PageRanges>,
) -> Vec<u8> {
    let mut ctx = PdfContext::new(document, page_ranges);
    page::construct_pages(&mut ctx, &document.pages);
    font::write_fonts(&mut ctx);
    image::write_images(&mut ctx);
    gradient::write_gradients(&mut ctx);
    extg::write_external_graphics_states(&mut ctx);
    pattern::write_patterns(&mut ctx);
    write_named_destinations(&mut ctx);
    page::write_page_tree(&mut ctx);
    page::write_global_resources(&mut ctx);
    write_catalog(&mut ctx, ident, timestamp);
    ctx.pdf.finish()
}

/// Context for exporting a whole PDF document.
struct PdfContext<'a> {
    /// The document that we're currently exporting.
    document: &'a Document,
    /// The writer we are writing the PDF into.
    pdf: Pdf,
    /// Content of exported pages.
    pages: Vec<Option<EncodedPage>>,
    /// Page ranges to export.
    /// When `None`, all pages are exported.
    exported_pages: Option<PageRanges>,
    /// For each font a mapping from used glyphs to their text representation.
    /// May contain multiple chars in case of ligatures or similar things. The
    /// same glyph can have a different text representation within one document,
    /// then we just save the first one. The resulting strings are used for the
    /// PDF's /ToUnicode map for glyphs that don't have an entry in the font's
    /// cmap. This is important for copy-paste and searching.
    glyph_sets: HashMap<Font, BTreeMap<u16, EcoString>>,
    /// The number of glyphs for all referenced languages in the document.
    /// We keep track of this to determine the main document language.
    /// BTreeMap is used to write sorted list of languages to metadata.
    languages: BTreeMap<Lang, usize>,

    /// Allocator for indirect reference IDs.
    alloc: Ref,
    /// The ID of the page tree.
    page_tree_ref: Ref,
    /// The ID of the globally shared Resources dictionary.
    global_resources_ref: Ref,
    /// The ID of the resource dictionary shared by Type3 fonts.
    ///