mirror of
https://github.com/typst/typst
synced 2025-07-27 14:27:56 +08:00
fix: only use link annotation quadpoints when exporting a PDF/UA-1 document
This commit is contained in:
parent
d6307831dd
commit
76d09b5673
@ -171,14 +171,14 @@ impl State {
|
|||||||
/// Context needed for converting a single frame.
|
/// Context needed for converting a single frame.
|
||||||
pub(crate) struct FrameContext {
|
pub(crate) struct FrameContext {
|
||||||
states: Vec<State>,
|
states: Vec<State>,
|
||||||
pub(crate) link_annotations: HashMap<tags::LinkId, LinkAnnotation>,
|
link_annotations: Vec<LinkAnnotation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FrameContext {
|
impl FrameContext {
|
||||||
pub(crate) fn new(size: Size) -> Self {
|
pub(crate) fn new(size: Size) -> Self {
|
||||||
Self {
|
Self {
|
||||||
states: vec![State::new(size)],
|
states: vec![State::new(size)],
|
||||||
link_annotations: HashMap::new(),
|
link_annotations: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,6 +197,20 @@ impl FrameContext {
|
|||||||
pub(crate) fn state_mut(&mut self) -> &mut State {
|
pub(crate) fn state_mut(&mut self) -> &mut State {
|
||||||
self.states.last_mut().unwrap()
|
self.states.last_mut().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_link_annotation(
|
||||||
|
&mut self,
|
||||||
|
link_id: tags::LinkId,
|
||||||
|
) -> Option<&mut LinkAnnotation> {
|
||||||
|
self.link_annotations
|
||||||
|
.iter_mut()
|
||||||
|
.rev()
|
||||||
|
.find(|annot| annot.id == link_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn push_link_annotation(&mut self, annotation: LinkAnnotation) {
|
||||||
|
self.link_annotations.push(annotation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Globally needed context for converting a typst document.
|
/// Globally needed context for converting a typst document.
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
use std::collections::hash_map::Entry;
|
|
||||||
|
|
||||||
use ecow::EcoString;
|
use ecow::EcoString;
|
||||||
use krilla::action::{Action, LinkAction};
|
use krilla::action::{Action, LinkAction};
|
||||||
use krilla::annotation::Target;
|
use krilla::annotation::Target;
|
||||||
|
use krilla::configure::Validator;
|
||||||
use krilla::destination::XyzDestination;
|
use krilla::destination::XyzDestination;
|
||||||
use krilla::geom as kg;
|
use krilla::geom as kg;
|
||||||
use typst_library::layout::{Abs, Point, Position, Size};
|
use typst_library::layout::{Abs, Point, Position, Size};
|
||||||
use typst_library::model::Destination;
|
use typst_library::model::Destination;
|
||||||
|
|
||||||
use crate::convert::{FrameContext, GlobalContext};
|
use crate::convert::{FrameContext, GlobalContext};
|
||||||
use crate::tags::{Placeholder, StackEntryKind, TagNode};
|
use crate::tags::{self, Placeholder, StackEntryKind, TagNode};
|
||||||
use crate::util::{AbsExt, PointExt};
|
use crate::util::{AbsExt, PointExt};
|
||||||
|
|
||||||
pub(crate) struct LinkAnnotation {
|
pub(crate) struct LinkAnnotation {
|
||||||
|
pub(crate) id: tags::LinkId,
|
||||||
pub(crate) placeholder: Placeholder,
|
pub(crate) placeholder: Placeholder,
|
||||||
pub(crate) alt: Option<String>,
|
pub(crate) alt: Option<String>,
|
||||||
pub(crate) rect: kg::Rect,
|
pub(crate) rect: kg::Rect,
|
||||||
@ -50,7 +50,7 @@ pub(crate) fn handle_link(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let entry = gc.tags.stack.last_mut().expect("a link parent");
|
let entry = gc.tags.stack.last_mut().expect("a link parent");
|
||||||
let StackEntryKind::Link(link_id, link) = &entry.kind else {
|
let StackEntryKind::Link(link_id, ref link) = entry.kind else {
|
||||||
unreachable!("expected a link parent")
|
unreachable!("expected a link parent")
|
||||||
};
|
};
|
||||||
let alt = link.alt.as_ref().map(EcoString::to_string);
|
let alt = link.alt.as_ref().map(EcoString::to_string);
|
||||||
@ -58,18 +58,21 @@ pub(crate) fn handle_link(
|
|||||||
let rect = to_rect(fc, size);
|
let rect = to_rect(fc, size);
|
||||||
let quadpoints = quadpoints(rect);
|
let quadpoints = quadpoints(rect);
|
||||||
|
|
||||||
match fc.link_annotations.entry(*link_id) {
|
// Unfortunately quadpoints still aren't well supported by most PDF readers,
|
||||||
Entry::Occupied(occupied) => {
|
// even by acrobat. Which is understandable since they were only introduced
|
||||||
// Update the bounding box and add the quadpoints of an existing link annotation.
|
// in PDF 1.6 (2005) /s
|
||||||
let annotation = occupied.into_mut();
|
let should_use_quadpoints = gc.options.standards.config.validator() == Validator::UA1;
|
||||||
|
match fc.get_link_annotation(link_id) {
|
||||||
|
Some(annotation) if should_use_quadpoints => {
|
||||||
|
// Update the bounding box and add the quadpoints to an existing link annotation.
|
||||||
annotation.rect = bounding_rect(annotation.rect, rect);
|
annotation.rect = bounding_rect(annotation.rect, rect);
|
||||||
annotation.quad_points.extend_from_slice(&quadpoints);
|
annotation.quad_points.extend_from_slice(&quadpoints);
|
||||||
}
|
}
|
||||||
Entry::Vacant(vacant) => {
|
_ => {
|
||||||
let placeholder = gc.tags.reserve_placeholder();
|
let placeholder = gc.tags.reserve_placeholder();
|
||||||
gc.tags.push(TagNode::Placeholder(placeholder));
|
gc.tags.push(TagNode::Placeholder(placeholder));
|
||||||
|
fc.push_link_annotation(LinkAnnotation {
|
||||||
vacant.insert(LinkAnnotation {
|
id: link_id,
|
||||||
placeholder,
|
placeholder,
|
||||||
rect,
|
rect,
|
||||||
quad_points: quadpoints.to_vec(),
|
quad_points: quadpoints.to_vec(),
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use std::cell::OnceCell;
|
use std::cell::OnceCell;
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use ecow::EcoString;
|
use ecow::EcoString;
|
||||||
use krilla::page::Page;
|
use krilla::page::Page;
|
||||||
@ -335,10 +334,11 @@ fn start_content<'a, 'b>(
|
|||||||
pub(crate) fn add_annotations(
|
pub(crate) fn add_annotations(
|
||||||
gc: &mut GlobalContext,
|
gc: &mut GlobalContext,
|
||||||
page: &mut Page,
|
page: &mut Page,
|
||||||
annotations: HashMap<LinkId, LinkAnnotation>,
|
annotations: Vec<LinkAnnotation>,
|
||||||
) {
|
) {
|
||||||
for annotation in annotations.into_values() {
|
for annotation in annotations.into_iter() {
|
||||||
let LinkAnnotation { placeholder, alt, rect, quad_points, target } = annotation;
|
let LinkAnnotation { id: _, placeholder, alt, rect, quad_points, target } =
|
||||||
|
annotation;
|
||||||
let annot = krilla::annotation::Annotation::new_link(
|
let annot = krilla::annotation::Annotation::new_link(
|
||||||
krilla::annotation::LinkAnnotation::new(rect, Some(quad_points), target),
|
krilla::annotation::LinkAnnotation::new(rect, Some(quad_points), target),
|
||||||
alt,
|
alt,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user