mirror of
https://github.com/typst/typst
synced 2025-07-27 14:27:56 +08:00
feat: group artifacts
span one artifact tag across all content inside an artifact
This commit is contained in:
parent
0c09c7d666
commit
8998676acb
@ -107,6 +107,8 @@ fn convert_pages(gc: &mut GlobalContext, document: &mut Document) -> SourceResul
|
|||||||
let mut surface = page.surface();
|
let mut surface = page.surface();
|
||||||
let mut fc = FrameContext::new(typst_page.frame.size());
|
let mut fc = FrameContext::new(typst_page.frame.size());
|
||||||
|
|
||||||
|
tags::page_start(gc, &mut surface);
|
||||||
|
|
||||||
handle_frame(
|
handle_frame(
|
||||||
&mut fc,
|
&mut fc,
|
||||||
&typst_page.frame,
|
&typst_page.frame,
|
||||||
@ -115,6 +117,8 @@ fn convert_pages(gc: &mut GlobalContext, document: &mut Document) -> SourceResul
|
|||||||
gc,
|
gc,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
tags::page_end(gc, &mut surface);
|
||||||
|
|
||||||
surface.finish();
|
surface.finish();
|
||||||
|
|
||||||
tags::add_annotations(gc, &mut page, fc.link_annotations);
|
tags::add_annotations(gc, &mut page, fc.link_annotations);
|
||||||
@ -293,8 +297,8 @@ pub(crate) fn handle_frame(
|
|||||||
handle_image(gc, fc, image, *size, surface, *span)?
|
handle_image(gc, fc, image, *size, surface, *span)?
|
||||||
}
|
}
|
||||||
FrameItem::Link(dest, size) => handle_link(fc, gc, dest, *size),
|
FrameItem::Link(dest, size) => handle_link(fc, gc, dest, *size),
|
||||||
FrameItem::Tag(Tag::Start(elem)) => tags::handle_start(gc, elem)?,
|
FrameItem::Tag(Tag::Start(elem)) => tags::handle_start(gc, surface, elem)?,
|
||||||
FrameItem::Tag(Tag::End(loc, _)) => tags::handle_end(gc, *loc),
|
FrameItem::Tag(Tag::End(loc, _)) => tags::handle_end(gc, surface, *loc),
|
||||||
}
|
}
|
||||||
|
|
||||||
fc.pop();
|
fc.pop();
|
||||||
|
@ -31,7 +31,11 @@ use crate::tags::table::TableCtx;
|
|||||||
mod outline;
|
mod outline;
|
||||||
mod table;
|
mod table;
|
||||||
|
|
||||||
pub(crate) fn handle_start(gc: &mut GlobalContext, elem: &Content) -> SourceResult<()> {
|
pub(crate) fn handle_start(
|
||||||
|
gc: &mut GlobalContext,
|
||||||
|
surface: &mut Surface,
|
||||||
|
elem: &Content,
|
||||||
|
) -> SourceResult<()> {
|
||||||
if gc.tags.in_artifact.is_some() {
|
if gc.tags.in_artifact.is_some() {
|
||||||
// Don't nest artifacts
|
// Don't nest artifacts
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -41,10 +45,10 @@ pub(crate) fn handle_start(gc: &mut GlobalContext, elem: &Content) -> SourceResu
|
|||||||
|
|
||||||
if let Some(artifact) = elem.to_packed::<ArtifactElem>() {
|
if let Some(artifact) = elem.to_packed::<ArtifactElem>() {
|
||||||
let kind = artifact.kind.get(StyleChain::default());
|
let kind = artifact.kind.get(StyleChain::default());
|
||||||
start_artifact(gc, loc, kind);
|
start_artifact(gc, surface, loc, kind);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else if let Some(_) = elem.to_packed::<RepeatElem>() {
|
} else if let Some(_) = elem.to_packed::<RepeatElem>() {
|
||||||
start_artifact(gc, loc, ArtifactKind::Other);
|
start_artifact(gc, surface, loc, ArtifactKind::Other);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +107,7 @@ pub(crate) fn handle_start(gc: &mut GlobalContext, elem: &Content) -> SourceResu
|
|||||||
// first page. Maybe it should be the cell on the last page, but that
|
// first page. Maybe it should be the cell on the last page, but that
|
||||||
// would require more changes in the layouting code, or a pre-pass
|
// would require more changes in the layouting code, or a pre-pass
|
||||||
// on the frames to figure out if there are other footers following.
|
// on the frames to figure out if there are other footers following.
|
||||||
start_artifact(gc, loc, ArtifactKind::Other);
|
start_artifact(gc, surface, loc, ArtifactKind::Other);
|
||||||
} else {
|
} else {
|
||||||
push_stack(gc, loc, StackEntryKind::TableCell(cell.clone()))?;
|
push_stack(gc, loc, StackEntryKind::TableCell(cell.clone()))?;
|
||||||
}
|
}
|
||||||
@ -141,9 +145,10 @@ fn push_stack(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn handle_end(gc: &mut GlobalContext, loc: Location) {
|
pub(crate) fn handle_end(gc: &mut GlobalContext, surface: &mut Surface, loc: Location) {
|
||||||
if let Some((l, _)) = gc.tags.in_artifact {
|
if let Some((l, _)) = gc.tags.in_artifact {
|
||||||
if l == loc {
|
if l == loc {
|
||||||
|
surface.end_tagged();
|
||||||
gc.tags.in_artifact = None;
|
gc.tags.in_artifact = None;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -202,6 +207,20 @@ pub(crate) fn handle_end(gc: &mut GlobalContext, loc: Location) {
|
|||||||
gc.tags.push(node);
|
gc.tags.push(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn page_start(gc: &mut GlobalContext, surface: &mut Surface) {
|
||||||
|
if let Some((_, kind)) = gc.tags.in_artifact {
|
||||||
|
let ty = artifact_type(kind);
|
||||||
|
let id = surface.start_tagged(ContentTag::Artifact(ty));
|
||||||
|
gc.tags.push(TagNode::Leaf(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn page_end(gc: &mut GlobalContext, surface: &mut Surface) {
|
||||||
|
if gc.tags.in_artifact.is_some() {
|
||||||
|
surface.end_tagged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Add all annotations that were found in the page frame.
|
/// Add all annotations that were found in the page frame.
|
||||||
pub(crate) fn add_annotations(
|
pub(crate) fn add_annotations(
|
||||||
gc: &mut GlobalContext,
|
gc: &mut GlobalContext,
|
||||||
@ -397,11 +416,16 @@ pub(crate) struct Placeholder(usize);
|
|||||||
/// Automatically calls [`Surface::end_tagged`] when dropped.
|
/// Automatically calls [`Surface::end_tagged`] when dropped.
|
||||||
pub(crate) struct TagHandle<'a, 'b> {
|
pub(crate) struct TagHandle<'a, 'b> {
|
||||||
surface: &'b mut Surface<'a>,
|
surface: &'b mut Surface<'a>,
|
||||||
|
/// Whether this tag handle started the marked content sequence, and should
|
||||||
|
/// thus end it when it is dropped.
|
||||||
|
started: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for TagHandle<'_, '_> {
|
impl Drop for TagHandle<'_, '_> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.surface.end_tagged();
|
if self.started {
|
||||||
|
self.surface.end_tagged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,9 +459,8 @@ fn start_content<'a, 'b>(
|
|||||||
surface: &'b mut Surface<'a>,
|
surface: &'b mut Surface<'a>,
|
||||||
content: ContentTag,
|
content: ContentTag,
|
||||||
) -> TagHandle<'a, 'b> {
|
) -> TagHandle<'a, 'b> {
|
||||||
let content = if let Some((_, kind)) = gc.tags.in_artifact {
|
let content = if gc.tags.in_artifact.is_some() {
|
||||||
let ty = artifact_type(kind);
|
return TagHandle { surface, started: false };
|
||||||
ContentTag::Artifact(ty)
|
|
||||||
} else if let Some(StackEntryKind::Table(_)) = gc.tags.stack.last().map(|e| &e.kind) {
|
} else if let Some(StackEntryKind::Table(_)) = gc.tags.stack.last().map(|e| &e.kind) {
|
||||||
// Mark any direct child of a table as an aritfact. Any real content
|
// Mark any direct child of a table as an aritfact. Any real content
|
||||||
// will be wrapped inside a `TableCell`.
|
// will be wrapped inside a `TableCell`.
|
||||||
@ -447,10 +470,18 @@ fn start_content<'a, 'b>(
|
|||||||
};
|
};
|
||||||
let id = surface.start_tagged(content);
|
let id = surface.start_tagged(content);
|
||||||
gc.tags.push(TagNode::Leaf(id));
|
gc.tags.push(TagNode::Leaf(id));
|
||||||
TagHandle { surface }
|
TagHandle { surface, started: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_artifact(gc: &mut GlobalContext, loc: Location, kind: ArtifactKind) {
|
fn start_artifact(
|
||||||
|
gc: &mut GlobalContext,
|
||||||
|
surface: &mut Surface,
|
||||||
|
loc: Location,
|
||||||
|
kind: ArtifactKind,
|
||||||
|
) {
|
||||||
|
let ty = artifact_type(kind);
|
||||||
|
let id = surface.start_tagged(ContentTag::Artifact(ty));
|
||||||
|
gc.tags.push(TagNode::Leaf(id));
|
||||||
gc.tags.in_artifact = Some((loc, kind));
|
gc.tags.in_artifact = Some((loc, kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user