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

Code before:

    if let Some(outline_root_id) = outline_root_id {
        catalog.outlines(outline_root_id);
    }

    if let Some(lang) = lang {
        catalog.lang(TextStr(lang.as_str()));
    }

    catalog.finish();
}

fn write_and_collect_destinations<'a>(
    ctx: &mut PdfContext,
) -> Vec<(Str<'a>, Ref, Ref, f32, f32)> {
    let mut destinations = vec![];

    let elements = ctx.document.introspector.query(&HeadingElem::elem().select());
    for elem in elements.iter() {
        let heading = elem.to_packed::<HeadingElem>().unwrap();
        if_chain!(
            if let Some(label) = heading.label();
            if let Some(first) = ctx.document.introspector.query_first(&Selector::And(eco_vec![
                HeadingElem::elem().select(),
                Selector::Label(label)
            ]));
            if heading == first.to_packed::<HeadingElem>().unwrap();
            if let Some(loc) = heading.location();
            let name = Str(label.as_str().as_bytes());
            let pos = ctx.document.introspector.position(loc);
            let index = pos.page.get() - 1;
            let y = (pos.point.y - Abs::pt(10.0)).max(Abs::zero());
            if let Some(page) = ctx.pages.get(index);
            then {
                let page_ref = ctx.page_refs[index];
                let x = pos.point.x.to_f32();
                let y = (page.size.y - y).to_f32();
                let dest_ref = ctx.alloc.bump();
                destinations.push((name, dest_ref, page_ref, x, y))
            }
        );
    }
    destinations.sort_by_key(|i| i.0);
    for (_name, dest_ref, page_ref, x, y) in destinations.iter().copied() {
        ctx.pdf.destination(dest_ref).page(page_ref).xyz(x, y, None);
    }
    destinations
}

/// Compress data with the DEFLATE algorithm.
fn deflate(data: &[u8]) -> Vec<u8> {

Review comment (suggestion):
I think rather than querying again here we could just keep a hash set of which labels we have already seen.

Code after:
    if let Some(outline_root_id) = outline_root_id {
        catalog.outlines(outline_root_id);
    }

    if let Some(lang) = lang {
        catalog.lang(TextStr(lang.as_str()));
    }

    catalog.finish();
}

fn write_and_collect_destinations<'a>(
    ctx: &mut PdfContext,
) -> Vec<(Str<'a>, Ref, Ref, f32, f32)> {
    let mut destinations = vec![];

    let mut seen_labels = HashSet::new();
    let elements = ctx.document.introspector.query(&HeadingElem::elem().select());
    for elem in elements.iter() {
        let heading = elem.to_packed::<HeadingElem>().unwrap();
        if let Some(label) = heading.label() {
            if !seen_labels.contains(&label) {
                let loc = heading.location().unwrap();
                let name = Str(label.as_str().as_bytes());
                let pos = ctx.document.introspector.position(loc);
                let index = pos.page.get() - 1;
                let y = (pos.point.y - Abs::pt(10.0)).max(Abs::zero());
                if let Some(page) = ctx.pages.get(index) {
                    seen_labels.insert(label);
                    let page_ref = ctx.page_refs[index];
                    let x = pos.point.x.to_f32();
                    let y = (page.size.y - y).to_f32();
                    let dest_ref = ctx.alloc.bump();
                    destinations.push((name, dest_ref, page_ref, x, y))
                }
            }
        }
    }
    destinations.sort_by_key(|i| i.0);
    for (_name, dest_ref, page_ref, x, y) in destinations.iter().copied() {
        ctx.pdf.destination(dest_ref).page(page_ref).xyz(x, y, None);
    }
    destinations
}

/// Compress data with the DEFLATE algorithm.
fn deflate(data: &[u8]) -> Vec<u8> {
    const COMPRESSION_LEVEL: u8 = 6;
    miniz_oxide::deflate::compress_to_vec_zlib(data, COMPRESSION_LEVEL)
}