mirror of
https://github.com/typst/typst
synced 2025-08-06 19:27:55 +08:00
fix: ignore any tags inside of tilings
This commit is contained in:
parent
b312b45b19
commit
7ea16f25b5
@ -16,6 +16,7 @@ use typst_library::visualize::{
|
|||||||
use typst_utils::Numeric;
|
use typst_utils::Numeric;
|
||||||
|
|
||||||
use crate::convert::{FrameContext, GlobalContext, State, handle_frame};
|
use crate::convert::{FrameContext, GlobalContext, State, handle_frame};
|
||||||
|
use crate::tags::{self, Disable};
|
||||||
use crate::util::{AbsExt, FillRuleExt, LineCapExt, LineJoinExt, TransformExt};
|
use crate::util::{AbsExt, FillRuleExt, LineCapExt, LineJoinExt, TransformExt};
|
||||||
|
|
||||||
pub(crate) fn convert_fill(
|
pub(crate) fn convert_fill(
|
||||||
@ -127,8 +128,12 @@ fn convert_pattern(
|
|||||||
|
|
||||||
let mut stream_builder = surface.stream_builder();
|
let mut stream_builder = surface.stream_builder();
|
||||||
let mut surface = stream_builder.surface();
|
let mut surface = stream_builder.surface();
|
||||||
let mut fc = FrameContext::new(None, pattern.frame().size());
|
{
|
||||||
handle_frame(&mut fc, pattern.frame(), None, &mut surface, gc)?;
|
let mut handle = tags::disable(gc, &mut surface, Disable::Tiling);
|
||||||
|
let (gc, surface) = handle.reborrow();
|
||||||
|
let mut fc = FrameContext::new(None, pattern.frame().size());
|
||||||
|
handle_frame(&mut fc, pattern.frame(), None, surface, gc)?;
|
||||||
|
}
|
||||||
surface.finish();
|
surface.finish();
|
||||||
let stream = stream_builder.finish();
|
let stream = stream_builder.finish();
|
||||||
let pattern = Pattern {
|
let pattern = Pattern {
|
||||||
|
@ -38,7 +38,7 @@ pub struct Tags {
|
|||||||
/// before the reference in the text, so we only resolve them once tags
|
/// before the reference in the text, so we only resolve them once tags
|
||||||
/// for the whole document are generated.
|
/// for the whole document are generated.
|
||||||
pub footnotes: HashMap<Location, FootnoteCtx>,
|
pub footnotes: HashMap<Location, FootnoteCtx>,
|
||||||
pub in_artifact: Option<(Location, ArtifactKind)>,
|
pub disable: Option<Disable>,
|
||||||
/// Used to group multiple link annotations using quad points.
|
/// Used to group multiple link annotations using quad points.
|
||||||
link_id: LinkId,
|
link_id: LinkId,
|
||||||
/// Used to generate IDs referenced in table `Headers` attributes.
|
/// Used to generate IDs referenced in table `Headers` attributes.
|
||||||
@ -57,7 +57,7 @@ impl Tags {
|
|||||||
stack: TagStack::new(),
|
stack: TagStack::new(),
|
||||||
placeholders: Placeholders(Vec::new()),
|
placeholders: Placeholders(Vec::new()),
|
||||||
footnotes: HashMap::new(),
|
footnotes: HashMap::new(),
|
||||||
in_artifact: None,
|
disable: None,
|
||||||
|
|
||||||
link_id: LinkId(0),
|
link_id: LinkId(0),
|
||||||
table_id: TableId(0),
|
table_id: TableId(0),
|
||||||
@ -187,6 +187,12 @@ impl Tags {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum Disable {
|
||||||
|
ArtifactTag(Location, ArtifactKind),
|
||||||
|
Tiling,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct TextAttrs {
|
pub struct TextAttrs {
|
||||||
lineheight: Option<LineHeight>,
|
lineheight: Option<LineHeight>,
|
||||||
|
@ -100,17 +100,17 @@ pub fn handle_start(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if gc.tags.in_artifact.is_some() {
|
if gc.tags.disable.is_some() {
|
||||||
// Don't nest artifacts
|
// Don't nest artifacts
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(artifact) = elem.to_packed::<ArtifactElem>() {
|
if let Some(artifact) = elem.to_packed::<ArtifactElem>() {
|
||||||
let kind = artifact.kind.val();
|
let kind = artifact.kind.val();
|
||||||
push_artifact(gc, surface, elem, kind);
|
push_artifact_tag(gc, surface, elem, kind);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else if let Some(_) = elem.to_packed::<RepeatElem>() {
|
} else if let Some(_) = elem.to_packed::<RepeatElem>() {
|
||||||
push_artifact(gc, surface, elem, ArtifactKind::Other);
|
push_artifact_tag(gc, surface, elem, ArtifactKind::Other);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ pub fn handle_start(
|
|||||||
// 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.
|
||||||
push_artifact(gc, surface, elem, ArtifactKind::Other);
|
push_artifact_tag(gc, surface, elem, ArtifactKind::Other);
|
||||||
} else {
|
} else {
|
||||||
push_stack(gc, elem, StackEntryKind::TableCell(cell.clone()))?;
|
push_stack(gc, elem, StackEntryKind::TableCell(cell.clone()))?;
|
||||||
}
|
}
|
||||||
@ -312,7 +312,7 @@ fn push_stack(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_artifact(
|
fn push_artifact_tag(
|
||||||
gc: &mut GlobalContext,
|
gc: &mut GlobalContext,
|
||||||
surface: &mut Surface,
|
surface: &mut Surface,
|
||||||
elem: &Content,
|
elem: &Content,
|
||||||
@ -321,7 +321,7 @@ fn push_artifact(
|
|||||||
let loc = elem.location().expect("elem to be locatable");
|
let loc = elem.location().expect("elem to be locatable");
|
||||||
let ty = artifact_type(kind);
|
let ty = artifact_type(kind);
|
||||||
surface.start_tagged(ContentTag::Artifact(ty));
|
surface.start_tagged(ContentTag::Artifact(ty));
|
||||||
gc.tags.in_artifact = Some((loc, kind));
|
gc.tags.disable = Some(Disable::ArtifactTag(loc, kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_end(
|
pub fn handle_end(
|
||||||
@ -333,10 +333,11 @@ pub fn handle_end(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((l, _)) = gc.tags.in_artifact
|
if let Some(Disable::ArtifactTag(l, _)) = gc.tags.disable
|
||||||
&& l == loc
|
&& l == loc
|
||||||
{
|
{
|
||||||
pop_artifact(gc, surface);
|
surface.end_tagged();
|
||||||
|
gc.tags.disable = None;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,17 +534,16 @@ fn pop_stack(gc: &mut GlobalContext, entry: StackEntry) {
|
|||||||
gc.tags.push(node);
|
gc.tags.push(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_artifact(gc: &mut GlobalContext, surface: &mut Surface) {
|
|
||||||
surface.end_tagged();
|
|
||||||
gc.tags.in_artifact = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn page_start(gc: &mut GlobalContext, surface: &mut Surface) {
|
pub fn page_start(gc: &mut GlobalContext, surface: &mut Surface) {
|
||||||
if gc.options.disable_tags {
|
if gc.options.disable_tags {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((_, kind)) = gc.tags.in_artifact {
|
if let Some(disable) = gc.tags.disable {
|
||||||
|
let kind = match disable {
|
||||||
|
Disable::ArtifactTag(_, kind) => kind,
|
||||||
|
Disable::Tiling => ArtifactKind::Other,
|
||||||
|
};
|
||||||
let ty = artifact_type(kind);
|
let ty = artifact_type(kind);
|
||||||
surface.start_tagged(ContentTag::Artifact(ty));
|
surface.start_tagged(ContentTag::Artifact(ty));
|
||||||
}
|
}
|
||||||
@ -554,7 +554,7 @@ pub fn page_end(gc: &mut GlobalContext, surface: &mut Surface) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if gc.tags.in_artifact.is_some() {
|
if gc.tags.disable.is_some() {
|
||||||
surface.end_tagged();
|
surface.end_tagged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -584,6 +584,43 @@ pub fn add_link_annotations(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct DisableHandle<'a, 'b, 'c, 'd> {
|
||||||
|
gc: &'b mut GlobalContext<'a>,
|
||||||
|
surface: &'d mut Surface<'c>,
|
||||||
|
/// Whether this handle started the disabled range.
|
||||||
|
started: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for DisableHandle<'_, '_, '_, '_> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.started {
|
||||||
|
self.gc.tags.disable = None;
|
||||||
|
self.surface.end_tagged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'c> DisableHandle<'a, '_, 'c, '_> {
|
||||||
|
pub fn reborrow<'s>(
|
||||||
|
&'s mut self,
|
||||||
|
) -> (&'s mut GlobalContext<'a>, &'s mut Surface<'c>) {
|
||||||
|
(self.gc, self.surface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disable<'a, 'b, 'c, 'd>(
|
||||||
|
gc: &'b mut GlobalContext<'a>,
|
||||||
|
surface: &'d mut Surface<'c>,
|
||||||
|
kind: Disable,
|
||||||
|
) -> DisableHandle<'a, 'b, 'c, 'd> {
|
||||||
|
let started = gc.tags.disable.is_none();
|
||||||
|
if started {
|
||||||
|
gc.tags.disable = Some(kind);
|
||||||
|
surface.start_tagged(ContentTag::Artifact(ArtifactType::Other));
|
||||||
|
}
|
||||||
|
DisableHandle { gc, surface, started }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn text<'a, 'b>(
|
pub fn text<'a, 'b>(
|
||||||
gc: &mut GlobalContext,
|
gc: &mut GlobalContext,
|
||||||
fc: &FrameContext,
|
fc: &FrameContext,
|
||||||
@ -596,7 +633,7 @@ pub fn text<'a, 'b>(
|
|||||||
|
|
||||||
update_bbox(gc, fc, || text.bbox());
|
update_bbox(gc, fc, || text.bbox());
|
||||||
|
|
||||||
if gc.tags.in_artifact.is_some() {
|
if gc.tags.disable.is_some() {
|
||||||
return TagHandle { surface, started: false };
|
return TagHandle { surface, started: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -682,25 +719,16 @@ 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> {
|
||||||
if gc.tags.in_artifact.is_some() {
|
if gc.tags.disable.is_some() {
|
||||||
return TagHandle { surface, started: false };
|
return TagHandle { surface, started: false };
|
||||||
} else if let Some(StackEntryKind::Table(_)) = gc.tags.stack.last().map(|e| &e.kind) {
|
|
||||||
// TODO: handle this more like other artifacts
|
|
||||||
// Mark any direct child of a table as an aritfact. Any real content
|
|
||||||
// will be wrapped inside a `TableCell`.
|
|
||||||
|
|
||||||
// Don't store artifact content ids, they will be omitted anyway when
|
|
||||||
// serializing the tag tree.
|
|
||||||
surface.start_tagged(ContentTag::Artifact(ArtifactType::Other));
|
|
||||||
TagHandle { surface, started: true }
|
|
||||||
} else {
|
|
||||||
let artifact = matches!(content, ContentTag::Artifact(_));
|
|
||||||
let id = surface.start_tagged(content);
|
|
||||||
if !artifact {
|
|
||||||
gc.tags.push(TagNode::Leaf(id));
|
|
||||||
}
|
|
||||||
TagHandle { surface, started: true }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let artifact = matches!(content, ContentTag::Artifact(_));
|
||||||
|
let id = surface.start_tagged(content);
|
||||||
|
if !artifact {
|
||||||
|
gc.tags.push(TagNode::Leaf(id));
|
||||||
|
}
|
||||||
|
TagHandle { surface, started: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn artifact_type(kind: ArtifactKind) -> ArtifactType {
|
fn artifact_type(kind: ArtifactKind) -> ArtifactType {
|
||||||
|
8
tests/ref/pdftags/disable-tags-artifact.yml
Normal file
8
tests/ref/pdftags/disable-tags-artifact.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
- Tag: H1
|
||||||
|
/T: "Heading 1"
|
||||||
|
/K:
|
||||||
|
- Content: page=0 mcid=0
|
||||||
|
- Tag: H1
|
||||||
|
/T: "Heading 2"
|
||||||
|
/K:
|
||||||
|
- Content: page=0 mcid=1
|
4
tests/ref/pdftags/disable-tags-tiling.yml
Normal file
4
tests/ref/pdftags/disable-tags-tiling.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Tag: H1
|
||||||
|
/T: "Rectangle"
|
||||||
|
/K:
|
||||||
|
- Content: page=0 mcid=0
|
21
tests/suite/pdftags/disable.typ
Normal file
21
tests/suite/pdftags/disable.typ
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
--- disable-tags-artifact pdftags ---
|
||||||
|
= Heading 1
|
||||||
|
#pdf.artifact[
|
||||||
|
#table(
|
||||||
|
columns: 2,
|
||||||
|
[a], [b],
|
||||||
|
[c], [d],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
= Heading 2
|
||||||
|
|
||||||
|
--- disable-tags-tiling pdftags ---
|
||||||
|
= Rectangle
|
||||||
|
|
||||||
|
#let pat = tiling(size: (20pt, 20pt))[
|
||||||
|
- a
|
||||||
|
- b
|
||||||
|
- c
|
||||||
|
]
|
||||||
|
#rect(fill: pat)
|
Loading…
x
Reference in New Issue
Block a user