mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-08 19:42:05 +00:00
Merge pull request #1931 from storytold/fix/sec-pdf-link-bytes
fix(pdf): drop an oversized hyperlink before it is copied once per line
This commit is contained in:
2 files changed
+20
-1
No files matched your search
@@ -284,3 +284,20 @@ fn depth_samples() {
|
||||
std::fs::write(format!("{stem}-{name}.png"), figcraft_render::encode_png(&pix).unwrap()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_oversized_link_is_dropped_before_it_is_copied_per_line() {
|
||||
// One link far past MAX_URL on text that wraps onto many lines: no annotation, and the
|
||||
// destination is never copied once per line on the way to being refused.
|
||||
let mut d = Document::new("long link");
|
||||
let p = d.first_page().unwrap_or(NodeId(0));
|
||||
let f = d.create(p, NodeKind::Frame, "F", 0.0, 0.0, 300.0, 4000.0).unwrap();
|
||||
let words = "word ".repeat(2_000);
|
||||
let mut td = TextData::new(words.trim_end());
|
||||
td.style.font_size = 20.0;
|
||||
td.style.link = Some("https://example.com/".to_string() + &"a".repeat(1 << 20));
|
||||
let t = d.create(f, NodeKind::Text(td), "T", 10.0, 10.0, 280.0, 3980.0).unwrap();
|
||||
d.get_mut(t).unwrap().fills = vec![Paint::solid(Color::BLACK)];
|
||||
let pdf = export_pdf(&d, &[f], &PdfOptions::default()).unwrap();
|
||||
assert_eq!(text(&pdf).matches("/Subtype/Link").count(), 0);
|
||||
}
|
||||
@@ -121,7 +121,9 @@ fn record_links(ex: &mut Exporter, layout: &TextLayout, gxf: Affine) {
|
||||
let glyphs = layout.glyphs.get(line.glyph_start..line.glyph_end).unwrap_or(&[]);
|
||||
for g in glyphs.iter().map(Some).chain([None]) {
|
||||
let link = g.and_then(|g| {
|
||||
let url = layout.styles.get(g.style)?.link.as_deref().filter(|u| !u.trim().is_empty())?;
|
||||
// Checked here, not when the annotation is written: every linked line copies
|
||||
// the destination, so one oversized link must not be copied at all.
|
||||
let url = layout.styles.get(g.style)?.link.as_deref().map(str::trim).filter(|u| !u.is_empty() && u.len() <= crate::MAX_URL)?;
|
||||
let (a, b) = (g.x, g.x + g.advance);
|
||||
(a.is_finite() && b.is_finite()).then(|| (url, a.min(b), a.max(b)))
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user