mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-02 22:20:50 -06:00
PDF import: PDF and .ai layer names without a byte order mark are read as PDFDocEncoding
The layers of PDF and PDF-compatible .ai files come from their optional content groups, whose /Name is a PDF text string. The import read a name without a byte order mark as Latin-1. Such a string is PDFDocEncoding (ISO 32000-1 Annex D, Table D.2), which differs from Latin-1 at 0x18 to 0x1F and 0x80 to 0xA0. A group named (Art\205final) opened as a layer named "Art", U+0085, "final" instead of "Art–final", and curly double quotes (0x8D, 0x8E) and the euro sign (0xA0) became control characters and a no-break space. text_string now reads such a string with the PDFDocEncoding table that File Info already used for the document information dictionary. The table moves from file_info.rs to import_scan.rs, and File Info reads the information dictionary's strings with text_string.
This commit is contained in:
@@ -59,6 +59,23 @@ fn layers_option_keeps_or_flattens_optional_content() {
|
||||
assert!(open(&mut s, &bytes, json!({"layers": "no"})).unwrap_err().to_string().contains("layers must be true or false"));
|
||||
}
|
||||
|
||||
/// A PDF-compatible `.ai` without the editor's private data opens its layers from its optional
|
||||
/// content groups, whose names without a byte order mark are PDFDocEncoding.
|
||||
#[test]
|
||||
fn ai_layer_names_are_read_as_pdf_doc_encoding() {
|
||||
let (a, b) = (first_extra(1), first_extra(1) + 1);
|
||||
let catalog = format!("/OCProperties << /OCGs [{a} 0 R {b} 0 R] /D << >> >> ");
|
||||
let page = PdfPage {
|
||||
resources: format!("/Properties << /A {a} 0 R /B {b} 0 R >>"),
|
||||
..PdfPage::new(100.0, 100.0, "/OC /A BDC 0 g 0 0 10 10 re f EMC /OC /B BDC 0 g 20 20 10 10 re f EMC")
|
||||
};
|
||||
let bytes = pdf_with_catalog(&[page], &[r"<< /Type /OCG /Name (Art\205final) >>", "<< /Type /OCG /Name (Notes) >>"], &catalog, None);
|
||||
let mut s = Session::new();
|
||||
s.execute("document.open", &json!({"name": "art.ai", "dataBase64": vectorcraft_format::base64_encode(&bytes)})).unwrap();
|
||||
let names: Vec<String> = s.active().unwrap().doc.layers.iter().map(|l| l.name.clone().unwrap_or_default()).collect();
|
||||
assert_eq!(names, ["Art\u{2013}final", "Notes"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn load_options_read_text_and_layers() {
|
||||
let o = LoadOptions::from_params("x", &json!({"textAs": "Outlines", "layers": false})).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user