fschutt / printpdf

A fully-featured PDF library for Rust, WASM-ready
https://fschutt.github.io/printpdf/
MIT License
829 stars 98 forks source link

Bookmark in Unicode #188

Open strandenzee opened 1 month ago

strandenzee commented 1 month ago

I am trying to add a bookmark in Unicode (Russian and Polish text in my case) but i only get some silly signs, not the letters i would like to have. Is there a way to use Unicode Bookmarks?

use printpdf::*;
use std::fs::File;
use std::io::{BufWriter, Seek};

fn main() {
    test_unicode_bookmark();
}

fn test_unicode_bookmark() {

    // Create a new PDF document
    let (doc, page1, layer1) = PdfDocument::new("PDF with Bookmarks", Mm(210.0), Mm(297.0), "Layer 1");

    // Create a new layer
    let layer = doc.get_page(page1).get_layer(layer1);

    // Add some text to the first page
    let font = doc.add_external_font(File::open("src/assets/fonts/RobotoMedium.ttf").unwrap()).unwrap();
    let hello = String::from("Здравствуйте");
    layer.use_text(&hello, 48.0, Mm(10.0), Mm(280.0), &font);

    // Add a bookmark with Unicode text
    let bookmark_title = "Unicode Bookmark: Здравствуйте"; // Example Unicode text
    doc.add_bookmark(bookmark_title, page1);

    // Save the document
    doc.save(&mut BufWriter::new(File::create("output.pdf").unwrap())).unwrap();
}

image

fschutt commented 4 weeks ago

I didn't write the bookmarks code but it's probably this line:

https://github.com/fschutt/printpdf/blob/8e3b07290a566fef859cad6b3d6b1c1e2eec6878/src/pdf_document.rs#L714

Literal encoding means Windows-ANSI, it should be switched to Hexadecimal like this:

        let bytes = text
            .chars()
            .flat_map(|x| {
                let [b0, b1] = x.to_be_bytes();
                std::iter::once(b0).chain(std::iter::once(b1))
            })
            .collect::<Vec<u8>>();

        ("Title", String(bytes, Hexadecimal)),