feat: avoid doing extra work when --disable-pdf-tags is passed

This commit is contained in:
Tobias Schmitz 2025-07-24 18:03:10 +02:00
parent 820ea27a41
commit 50a280b6c2
No known key found for this signature in database
3 changed files with 47 additions and 13 deletions

View File

@ -124,7 +124,7 @@ fn convert_pages(gc: &mut GlobalContext, document: &mut Document) -> SourceResul
surface.finish();
tags::add_annotations(gc, &mut page, fc.link_annotations);
tags::add_link_annotations(gc, &mut page, fc.link_annotations);
}
}

View File

@ -50,11 +50,14 @@ pub(crate) fn handle_link(
}
};
let Some((link_id, link, link_nodes)) = gc.tags.stack.find_parent_link() else {
unreachable!("expected a link parent")
let (link_id, tagging_ctx) = match gc.tags.stack.find_parent_link() {
Some((link_id, link, nodes)) => (link_id, Some((link, nodes))),
None if gc.options.disable_tags => {
let link_id = gc.tags.next_link_id();
(link_id, None)
}
None => unreachable!("expected a link parent"),
};
let alt = link.alt.as_ref().map(EcoString::to_string);
let quad = to_quadrilateral(fc, size);
// Unfortunately quadpoints still aren't well supported by most PDF readers,
@ -65,14 +68,20 @@ pub(crate) fn handle_link(
Some(annotation) if should_use_quadpoints => annotation.quad_points.push(quad),
_ => {
let placeholder = gc.tags.placeholders.reserve();
link_nodes.push(TagNode::Placeholder(placeholder));
let (alt, span) = if let Some((link, nodes)) = tagging_ctx {
nodes.push(TagNode::Placeholder(placeholder));
let alt = link.alt.as_ref().map(EcoString::to_string);
(alt, link.span)
} else {
(None, Span::detached())
};
fc.push_link_annotation(LinkAnnotation {
id: link_id,
placeholder,
quad_points: vec![quad],
alt,
target,
span: link.span,
span,
});
}
}

View File

@ -43,6 +43,10 @@ pub(crate) fn handle_start(
surface: &mut Surface,
elem: &Content,
) -> SourceResult<()> {
if gc.options.disable_tags {
return Ok(());
}
if gc.tags.in_artifact.is_some() {
// Don't nest artifacts
return Ok(());
@ -187,6 +191,10 @@ pub(crate) fn handle_start(
}
pub(crate) fn handle_end(gc: &mut GlobalContext, surface: &mut Surface, loc: Location) {
if gc.options.disable_tags {
return;
}
if let Some((l, _)) = gc.tags.in_artifact {
if l == loc {
pop_artifact(gc, surface);
@ -316,6 +324,10 @@ fn pop_artifact(gc: &mut GlobalContext, surface: &mut Surface) {
}
pub(crate) fn page_start(gc: &mut GlobalContext, surface: &mut Surface) {
if gc.options.disable_tags {
return;
}
if let Some((_, kind)) = gc.tags.in_artifact {
let ty = artifact_type(kind);
let id = surface.start_tagged(ContentTag::Artifact(ty));
@ -324,13 +336,17 @@ pub(crate) fn page_start(gc: &mut GlobalContext, surface: &mut Surface) {
}
pub(crate) fn page_end(gc: &mut GlobalContext, surface: &mut Surface) {
if gc.options.disable_tags {
return;
}
if gc.tags.in_artifact.is_some() {
surface.end_tagged();
}
}
/// Add all annotations that were found in the page frame.
pub(crate) fn add_annotations(
pub(crate) fn add_link_annotations(
gc: &mut GlobalContext,
page: &mut Page,
annotations: Vec<LinkAnnotation>,
@ -343,9 +359,14 @@ pub(crate) fn add_annotations(
alt,
)
.with_location(Some(span.into_raw().get()));
if gc.options.disable_tags {
page.add_annotation(annot);
} else {
let annot_id = page.add_tagged_annotation(annot);
gc.tags.placeholders.init(placeholder, Node::Leaf(annot_id));
}
}
}
pub(crate) fn update_bbox(
@ -372,10 +393,10 @@ pub(crate) struct Tags {
pub(crate) footnotes: HashMap<Location, TagNode>,
pub(crate) in_artifact: Option<(Location, ArtifactKind)>,
/// Used to group multiple link annotations using quad points.
pub(crate) link_id: LinkId,
link_id: LinkId,
/// Used to generate IDs referenced in table `Headers` attributes.
/// The IDs must be document wide unique.
pub(crate) table_id: TableId,
table_id: TableId,
/// The output.
pub(crate) tree: Vec<TagNode>,
@ -444,7 +465,7 @@ impl Tags {
true
}
fn next_link_id(&mut self) -> LinkId {
pub(crate) fn next_link_id(&mut self) -> LinkId {
self.link_id.0 += 1;
self.link_id
}
@ -770,6 +791,10 @@ fn start_content<'a, 'b>(
surface: &'b mut Surface<'a>,
content: ContentTag,
) -> TagHandle<'a, 'b> {
if gc.options.disable_tags {
return TagHandle { surface, started: false };
}
let content = if gc.tags.in_artifact.is_some() {
return TagHandle { surface, started: false };
} else if let Some(StackEntryKind::Table(_)) = gc.tags.stack.last().map(|e| &e.kind) {