mirror of
https://github.com/typst/typst
synced 2025-08-07 11:47:53 +08:00
Compare commits
4 Commits
66ca4dc9a0
...
79423f3033
Author | SHA1 | Date | |
---|---|---|---|
|
79423f3033 | ||
|
f8f900d40b | ||
|
0bd0dc6d92 | ||
|
8d2c8712d5 |
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -1373,7 +1373,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "krilla"
|
name = "krilla"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/LaurenzV/krilla?branch=main#c0a456829bb63212470a6fa29d604dd9e051a9bd"
|
source = "git+https://github.com/LaurenzV/krilla?branch=main#d40f81a01ca8f8654510a76effeef12518437800"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
@ -1402,7 +1402,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "krilla-svg"
|
name = "krilla-svg"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/LaurenzV/krilla?branch=main#c0a456829bb63212470a6fa29d604dd9e051a9bd"
|
source = "git+https://github.com/LaurenzV/krilla?branch=main#d40f81a01ca8f8654510a76effeef12518437800"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"flate2",
|
"flate2",
|
||||||
"fontdb",
|
"fontdb",
|
||||||
|
@ -93,7 +93,7 @@ impl Item<'_, '_> {
|
|||||||
Self::Frame(frame, _) => {
|
Self::Frame(frame, _) => {
|
||||||
frame.size().is_zero()
|
frame.size().is_zero()
|
||||||
&& frame.items().all(|(_, item)| {
|
&& frame.items().all(|(_, item)| {
|
||||||
matches!(item, FrameItem::Link(..) | FrameItem::Tag(_))
|
matches!(item, FrameItem::Link(_, _) | FrameItem::Tag(_))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Self::Placed(_, placed) => !placed.float,
|
Self::Placed(_, placed) => !placed.float,
|
||||||
|
@ -23,7 +23,7 @@ use typst_library::model::{
|
|||||||
LinkElem, ListElem, Outlinable, OutlineElem, OutlineEntry, ParElem, ParbreakElem,
|
LinkElem, ListElem, Outlinable, OutlineElem, OutlineEntry, ParElem, ParbreakElem,
|
||||||
QuoteElem, RefElem, StrongElem, TableCell, TableElem, TermsElem, Works,
|
QuoteElem, RefElem, StrongElem, TableCell, TableElem, TermsElem, Works,
|
||||||
};
|
};
|
||||||
use typst_library::pdf::{ArtifactElem, EmbedElem, PdfMarkerTag, PdfMarkerTagKind};
|
use typst_library::pdf::{ArtifactElem, EmbedElem, PdfMarkerTag};
|
||||||
use typst_library::text::{
|
use typst_library::text::{
|
||||||
DecoLine, Decoration, HighlightElem, ItalicToggle, LinebreakElem, LocalName,
|
DecoLine, Decoration, HighlightElem, ItalicToggle, LinebreakElem, LocalName,
|
||||||
OverlineElem, RawElem, RawLine, ScriptKind, ShiftSettings, Smallcaps, SmallcapsElem,
|
OverlineElem, RawElem, RawLine, ScriptKind, ShiftSettings, Smallcaps, SmallcapsElem,
|
||||||
@ -452,10 +452,7 @@ const OUTLINE_RULE: ShowFn<OutlineElem> = |elem, engine, styles| {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wrap the entries into a marker for pdf tagging.
|
// Wrap the entries into a marker for pdf tagging.
|
||||||
seq.push(
|
seq.push(PdfMarkerTag::OutlineBody(Content::sequence(entries)));
|
||||||
PdfMarkerTag::new(PdfMarkerTagKind::OutlineBody, Content::sequence(entries))
|
|
||||||
.pack(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(Content::sequence(seq))
|
Ok(Content::sequence(seq))
|
||||||
};
|
};
|
||||||
@ -543,25 +540,29 @@ const BIBLIOGRAPHY_RULE: ShowFn<BibliographyElem> = |elem, engine, styles| {
|
|||||||
|
|
||||||
let mut cells = vec![];
|
let mut cells = vec![];
|
||||||
for (prefix, reference) in references {
|
for (prefix, reference) in references {
|
||||||
|
let prefix = PdfMarkerTag::ListItemLabel(prefix.clone().unwrap_or_default());
|
||||||
cells.push(GridChild::Item(GridItem::Cell(
|
cells.push(GridChild::Item(GridItem::Cell(
|
||||||
Packed::new(GridCell::new(prefix.clone().unwrap_or_default()))
|
Packed::new(GridCell::new(prefix)).spanned(span),
|
||||||
.spanned(span),
|
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
let reference = PdfMarkerTag::BibEntry(reference.clone());
|
||||||
cells.push(GridChild::Item(GridItem::Cell(
|
cells.push(GridChild::Item(GridItem::Cell(
|
||||||
Packed::new(GridCell::new(reference.clone())).spanned(span),
|
Packed::new(GridCell::new(reference)).spanned(span),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
seq.push(
|
|
||||||
GridElem::new(cells)
|
let grid = GridElem::new(cells)
|
||||||
.with_columns(TrackSizings(smallvec![Sizing::Auto; 2]))
|
.with_columns(TrackSizings(smallvec![Sizing::Auto; 2]))
|
||||||
.with_column_gutter(TrackSizings(smallvec![COLUMN_GUTTER.into()]))
|
.with_column_gutter(TrackSizings(smallvec![COLUMN_GUTTER.into()]))
|
||||||
.with_row_gutter(TrackSizings(smallvec![row_gutter.into()]))
|
.with_row_gutter(TrackSizings(smallvec![row_gutter.into()]))
|
||||||
.pack()
|
.pack()
|
||||||
.spanned(span),
|
.spanned(span);
|
||||||
);
|
// TODO(accessibility): infer list numbering from style?
|
||||||
|
seq.push(PdfMarkerTag::Bibliography(true, grid));
|
||||||
} else {
|
} else {
|
||||||
|
let mut body = vec![];
|
||||||
for (_, reference) in references {
|
for (_, reference) in references {
|
||||||
let realized = reference.clone();
|
let realized = PdfMarkerTag::BibEntry(reference.clone());
|
||||||
let block = if works.hanging_indent {
|
let block = if works.hanging_indent {
|
||||||
let body = HElem::new((-INDENT).into()).pack() + realized;
|
let body = HElem::new((-INDENT).into()).pack() + realized;
|
||||||
let inset = Sides::default()
|
let inset = Sides::default()
|
||||||
@ -573,8 +574,9 @@ const BIBLIOGRAPHY_RULE: ShowFn<BibliographyElem> = |elem, engine, styles| {
|
|||||||
BlockElem::new().with_body(Some(BlockBody::Content(realized)))
|
BlockElem::new().with_body(Some(BlockBody::Content(realized)))
|
||||||
};
|
};
|
||||||
|
|
||||||
seq.push(block.pack().spanned(span));
|
body.push(block.pack().spanned(span));
|
||||||
}
|
}
|
||||||
|
seq.push(PdfMarkerTag::Bibliography(false, Content::sequence(body)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Content::sequence(seq))
|
Ok(Content::sequence(seq))
|
||||||
|
@ -3,7 +3,10 @@ use std::num::NonZeroU32;
|
|||||||
use typst_macros::{elem, func, Cast};
|
use typst_macros::{elem, func, Cast};
|
||||||
use typst_utils::NonZeroExt;
|
use typst_utils::NonZeroExt;
|
||||||
|
|
||||||
use crate::foundations::{Content, NativeElement, Smart};
|
use crate::diag::bail;
|
||||||
|
use crate::diag::SourceResult;
|
||||||
|
use crate::engine::Engine;
|
||||||
|
use crate::foundations::{Args, Construct, Content, NativeElement, Smart};
|
||||||
use crate::introspection::Locatable;
|
use crate::introspection::Locatable;
|
||||||
use crate::model::TableCell;
|
use crate::model::TableCell;
|
||||||
|
|
||||||
@ -99,21 +102,28 @@ impl TableHeaderScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Used to delimit content for tagged PDF.
|
// Used to delimit content for tagged PDF.
|
||||||
#[elem(Locatable)]
|
#[elem(Locatable, Construct)]
|
||||||
pub struct PdfMarkerTag {
|
pub struct PdfMarkerTag {
|
||||||
|
#[internal]
|
||||||
#[required]
|
#[required]
|
||||||
pub kind: PdfMarkerTagKind,
|
pub kind: PdfMarkerTagKind,
|
||||||
#[required]
|
#[required]
|
||||||
pub body: Content,
|
pub body: Content,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Construct for PdfMarkerTag {
|
||||||
|
fn construct(_: &mut Engine, args: &mut Args) -> SourceResult<Content> {
|
||||||
|
bail!(args.span, "cannot be constructed manually");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! pdf_marker_tag {
|
macro_rules! pdf_marker_tag {
|
||||||
($(#[doc = $doc:expr] $variant:ident,)+) => {
|
($(#[doc = $doc:expr] $variant:ident$(($($name:ident: $ty:ident)+))?,)+) => {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Cast)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum PdfMarkerTagKind {
|
pub enum PdfMarkerTagKind {
|
||||||
$(
|
$(
|
||||||
#[doc = $doc]
|
#[doc = $doc]
|
||||||
$variant
|
$variant $(($($ty),+))?
|
||||||
),+
|
),+
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,9 +131,12 @@ macro_rules! pdf_marker_tag {
|
|||||||
$(
|
$(
|
||||||
#[doc = $doc]
|
#[doc = $doc]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn $variant(body: Content) -> Content {
|
pub fn $variant($($($name: $ty,)+)? body: Content) -> Content {
|
||||||
let span = body.span();
|
let span = body.span();
|
||||||
Self::new(PdfMarkerTagKind::$variant, body).pack().spanned(span)
|
Self {
|
||||||
|
kind: PdfMarkerTagKind::$variant $(($($name),+))?,
|
||||||
|
body,
|
||||||
|
}.pack().spanned(span)
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
@ -135,6 +148,10 @@ pdf_marker_tag! {
|
|||||||
OutlineBody,
|
OutlineBody,
|
||||||
/// `Figure`
|
/// `Figure`
|
||||||
FigureBody,
|
FigureBody,
|
||||||
|
/// `L` bibliography list
|
||||||
|
Bibliography(numbered: bool),
|
||||||
|
/// `LBody` wrapping `BibEntry`
|
||||||
|
BibEntry,
|
||||||
/// `Lbl` (marker) of the list item
|
/// `Lbl` (marker) of the list item
|
||||||
ListItemLabel,
|
ListItemLabel,
|
||||||
/// `LBody` of the enum item
|
/// `LBody` of the enum item
|
||||||
|
@ -373,6 +373,12 @@ fn finish(
|
|||||||
.collect::<EcoVec<_>>();
|
.collect::<EcoVec<_>>();
|
||||||
Err(errors)
|
Err(errors)
|
||||||
}
|
}
|
||||||
|
KrillaError::DuplicateTagId(_, _) => {
|
||||||
|
unreachable!("duplicate IDs shouldn't be generated")
|
||||||
|
}
|
||||||
|
KrillaError::UnknownTagId(_, _) => {
|
||||||
|
unreachable!("all referenced IDs should be present in the tag tree")
|
||||||
|
}
|
||||||
KrillaError::Image(_, loc) => {
|
KrillaError::Image(_, loc) => {
|
||||||
let span = to_span(loc);
|
let span = to_span(loc);
|
||||||
bail!(span, "failed to process image");
|
bail!(span, "failed to process image");
|
||||||
@ -597,16 +603,6 @@ fn convert_error(
|
|||||||
"{prefix} missing document date";
|
"{prefix} missing document date";
|
||||||
hint: "set the date of the document"
|
hint: "set the date of the document"
|
||||||
),
|
),
|
||||||
ValidationError::DuplicateTagId(_id, loc) => {
|
|
||||||
// TODO: display the id and better error message
|
|
||||||
let span = to_span(*loc);
|
|
||||||
error!(span, "{prefix} duplicate tag id")
|
|
||||||
}
|
|
||||||
ValidationError::UnknownTagId(_id, loc) => {
|
|
||||||
// TODO: display the id and better error message
|
|
||||||
let span = to_span(*loc);
|
|
||||||
error!(span, "{prefix} unknown header tag id")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use krilla::annotation::Target;
|
|||||||
use krilla::configure::Validator;
|
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::{Point, Position, Size};
|
||||||
use typst_library::model::Destination;
|
use typst_library::model::Destination;
|
||||||
|
|
||||||
use crate::convert::{FrameContext, GlobalContext};
|
use crate::convert::{FrameContext, GlobalContext};
|
||||||
@ -15,8 +15,7 @@ pub(crate) struct LinkAnnotation {
|
|||||||
pub(crate) id: tags::LinkId,
|
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) quad_points: Vec<kg::Quadrilateral>,
|
||||||
pub(crate) quad_points: Vec<kg::Point>,
|
|
||||||
pub(crate) target: Target,
|
pub(crate) target: Target,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,27 +53,21 @@ pub(crate) fn handle_link(
|
|||||||
};
|
};
|
||||||
let alt = link.alt.as_ref().map(EcoString::to_string);
|
let alt = link.alt.as_ref().map(EcoString::to_string);
|
||||||
|
|
||||||
let rect = to_rect(fc, size);
|
let quad = to_quadrilateral(fc, size);
|
||||||
let quadpoints = quadpoints(rect);
|
|
||||||
|
|
||||||
// Unfortunately quadpoints still aren't well supported by most PDF readers,
|
// Unfortunately quadpoints still aren't well supported by most PDF readers,
|
||||||
// even by acrobat. Which is understandable since they were only introduced
|
// even by acrobat. Which is understandable since they were only introduced
|
||||||
// in PDF 1.6 (2005) /s
|
// in PDF 1.6 (2005) /s
|
||||||
let should_use_quadpoints = gc.options.standards.config.validator() == Validator::UA1;
|
let should_use_quadpoints = gc.options.standards.config.validator() == Validator::UA1;
|
||||||
match fc.get_link_annotation(link_id) {
|
match fc.get_link_annotation(link_id) {
|
||||||
Some(annotation) if should_use_quadpoints => {
|
Some(annotation) if should_use_quadpoints => annotation.quad_points.push(quad),
|
||||||
// Update the bounding box and add the quadpoints to an existing link annotation.
|
|
||||||
annotation.rect = bounding_rect(annotation.rect, rect);
|
|
||||||
annotation.quad_points.extend_from_slice(&quadpoints);
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
let placeholder = gc.tags.placeholders.reserve();
|
let placeholder = gc.tags.placeholders.reserve();
|
||||||
link_nodes.push(TagNode::Placeholder(placeholder));
|
link_nodes.push(TagNode::Placeholder(placeholder));
|
||||||
fc.push_link_annotation(LinkAnnotation {
|
fc.push_link_annotation(LinkAnnotation {
|
||||||
id: link_id,
|
id: link_id,
|
||||||
placeholder,
|
placeholder,
|
||||||
rect,
|
quad_points: vec![quad],
|
||||||
quad_points: quadpoints.to_vec(),
|
|
||||||
alt,
|
alt,
|
||||||
target,
|
target,
|
||||||
});
|
});
|
||||||
@ -82,53 +75,20 @@ pub(crate) fn handle_link(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the bounding box of the transformed link.
|
/// Compute the quadrilateral representing the transformed rectangle of this frame.
|
||||||
fn to_rect(fc: &FrameContext, size: Size) -> kg::Rect {
|
fn to_quadrilateral(fc: &FrameContext, size: Size) -> kg::Quadrilateral {
|
||||||
let mut min_x = Abs::inf();
|
|
||||||
let mut min_y = Abs::inf();
|
|
||||||
let mut max_x = -Abs::inf();
|
|
||||||
let mut max_y = -Abs::inf();
|
|
||||||
|
|
||||||
let pos = Point::zero();
|
let pos = Point::zero();
|
||||||
|
let points = [
|
||||||
for point in [
|
|
||||||
pos,
|
|
||||||
pos + Point::with_x(size.x),
|
|
||||||
pos + Point::with_y(size.y),
|
pos + Point::with_y(size.y),
|
||||||
pos + size.to_point(),
|
pos + size.to_point(),
|
||||||
] {
|
pos + Point::with_x(size.x),
|
||||||
let t = point.transform(fc.state().transform());
|
pos,
|
||||||
min_x.set_min(t.x);
|
];
|
||||||
min_y.set_min(t.y);
|
|
||||||
max_x.set_max(t.x);
|
|
||||||
max_y.set_max(t.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
let x1 = min_x.to_f32();
|
kg::Quadrilateral(points.map(|point| {
|
||||||
let x2 = max_x.to_f32();
|
let p = point.transform(fc.state().transform());
|
||||||
let y1 = min_y.to_f32();
|
kg::Point::from_xy(p.x.to_f32(), p.y.to_f32())
|
||||||
let y2 = max_y.to_f32();
|
}))
|
||||||
|
|
||||||
kg::Rect::from_ltrb(x1, y1, x2, y2).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bounding_rect(a: kg::Rect, b: kg::Rect) -> kg::Rect {
|
|
||||||
kg::Rect::from_ltrb(
|
|
||||||
a.left().min(b.left()),
|
|
||||||
a.top().min(b.top()),
|
|
||||||
a.right().max(b.right()),
|
|
||||||
a.bottom().max(b.bottom()),
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn quadpoints(rect: kg::Rect) -> [kg::Point; 4] {
|
|
||||||
[
|
|
||||||
kg::Point::from_xy(rect.left(), rect.bottom()),
|
|
||||||
kg::Point::from_xy(rect.right(), rect.bottom()),
|
|
||||||
kg::Point::from_xy(rect.right(), rect.top()),
|
|
||||||
kg::Point::from_xy(rect.left(), rect.top()),
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos_to_target(gc: &mut GlobalContext, pos: Position) -> Option<Target> {
|
fn pos_to_target(gc: &mut GlobalContext, pos: Position) -> Option<Target> {
|
||||||
|
@ -69,6 +69,20 @@ impl ListCtx {
|
|||||||
item.body = Some(nodes);
|
item.body = Some(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn push_bib_entry(&mut self, nodes: Vec<TagNode>) {
|
||||||
|
let nodes = vec![TagNode::Group(TagKind::BibEntry.into(), nodes)];
|
||||||
|
// Bibliography lists cannot be nested, but may be missing labels.
|
||||||
|
if let Some(item) = self.items.last_mut().filter(|item| item.body.is_none()) {
|
||||||
|
item.body = Some(nodes);
|
||||||
|
} else {
|
||||||
|
self.items.push(ListItem {
|
||||||
|
label: Vec::new(),
|
||||||
|
body: Some(nodes),
|
||||||
|
sub_list: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn build_list(self, mut nodes: Vec<TagNode>) -> TagNode {
|
pub(crate) fn build_list(self, mut nodes: Vec<TagNode>) -> TagNode {
|
||||||
for item in self.items.into_iter() {
|
for item in self.items.into_iter() {
|
||||||
nodes.push(TagNode::Group(
|
nodes.push(TagNode::Group(
|
||||||
|
@ -18,6 +18,7 @@ use typst_library::foundations::{
|
|||||||
};
|
};
|
||||||
use typst_library::introspection::Location;
|
use typst_library::introspection::Location;
|
||||||
use typst_library::layout::RepeatElem;
|
use typst_library::layout::RepeatElem;
|
||||||
|
use typst_library::math::EquationElem;
|
||||||
use typst_library::model::{
|
use typst_library::model::{
|
||||||
Destination, EnumElem, FigureCaption, FigureElem, FootnoteElem, FootnoteEntry,
|
Destination, EnumElem, FigureCaption, FigureElem, FootnoteElem, FootnoteEntry,
|
||||||
HeadingElem, ListElem, Outlinable, OutlineEntry, QuoteElem, TableCell, TableElem,
|
HeadingElem, ListElem, Outlinable, OutlineEntry, QuoteElem, TableCell, TableElem,
|
||||||
@ -64,6 +65,16 @@ pub(crate) fn handle_start(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
PdfMarkerTagKind::FigureBody => TagKind::Figure.into(),
|
PdfMarkerTagKind::FigureBody => TagKind::Figure.into(),
|
||||||
|
PdfMarkerTagKind::Bibliography(numbered) => {
|
||||||
|
let numbering =
|
||||||
|
if numbered { ListNumbering::Decimal } else { ListNumbering::None };
|
||||||
|
push_stack(gc, loc, StackEntryKind::List(ListCtx::new(numbering)))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
PdfMarkerTagKind::BibEntry => {
|
||||||
|
push_stack(gc, loc, StackEntryKind::BibEntry)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
PdfMarkerTagKind::ListItemLabel => {
|
PdfMarkerTagKind::ListItemLabel => {
|
||||||
push_stack(gc, loc, StackEntryKind::ListItemLabel)?;
|
push_stack(gc, loc, StackEntryKind::ListItemLabel)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -112,6 +123,9 @@ pub(crate) fn handle_start(
|
|||||||
} else {
|
} else {
|
||||||
TagKind::Figure.with_alt_text(alt)
|
TagKind::Figure.with_alt_text(alt)
|
||||||
}
|
}
|
||||||
|
} else if let Some(_) = elem.to_packed::<EquationElem>() {
|
||||||
|
// TODO: alt text
|
||||||
|
TagKind::Formula.into()
|
||||||
} else if let Some(table) = elem.to_packed::<TableElem>() {
|
} else if let Some(table) = elem.to_packed::<TableElem>() {
|
||||||
let table_id = gc.tags.next_table_id();
|
let table_id = gc.tags.next_table_id();
|
||||||
let summary = table.summary.get_as_ref().map(|s| s.to_string());
|
let summary = table.summary.get_as_ref().map(|s| s.to_string());
|
||||||
@ -221,6 +235,11 @@ pub(crate) fn handle_end(gc: &mut GlobalContext, surface: &mut Surface, loc: Loc
|
|||||||
list_ctx.push_body(entry.nodes);
|
list_ctx.push_body(entry.nodes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
StackEntryKind::BibEntry => {
|
||||||
|
let list_ctx = gc.tags.stack.parent_list().expect("parent list");
|
||||||
|
list_ctx.push_bib_entry(entry.nodes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
StackEntryKind::Link(_, link) => {
|
StackEntryKind::Link(_, link) => {
|
||||||
let alt = link.alt.as_ref().map(EcoString::to_string);
|
let alt = link.alt.as_ref().map(EcoString::to_string);
|
||||||
let tag = TagKind::Link.with_alt_text(alt);
|
let tag = TagKind::Link.with_alt_text(alt);
|
||||||
@ -305,10 +324,9 @@ pub(crate) fn add_annotations(
|
|||||||
annotations: Vec<LinkAnnotation>,
|
annotations: Vec<LinkAnnotation>,
|
||||||
) {
|
) {
|
||||||
for annotation in annotations.into_iter() {
|
for annotation in annotations.into_iter() {
|
||||||
let LinkAnnotation { id: _, placeholder, alt, rect, quad_points, target } =
|
let LinkAnnotation { id: _, placeholder, alt, quad_points, target } = annotation;
|
||||||
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_with_quad_points(quad_points, target),
|
||||||
alt,
|
alt,
|
||||||
);
|
);
|
||||||
let annot_id = page.add_tagged_annotation(annot);
|
let annot_id = page.add_tagged_annotation(annot);
|
||||||
@ -503,6 +521,7 @@ pub(crate) enum StackEntryKind {
|
|||||||
List(ListCtx),
|
List(ListCtx),
|
||||||
ListItemLabel,
|
ListItemLabel,
|
||||||
ListItemBody,
|
ListItemBody,
|
||||||
|
BibEntry,
|
||||||
Link(LinkId, Packed<LinkMarker>),
|
Link(LinkId, Packed<LinkMarker>),
|
||||||
/// The footnote reference in the text.
|
/// The footnote reference in the text.
|
||||||
FootNoteRef,
|
FootNoteRef,
|
||||||
|
@ -167,7 +167,7 @@ fn render_frame(canvas: &mut sk::Pixmap, state: State, frame: &Frame) {
|
|||||||
FrameItem::Image(image, size, _) => {
|
FrameItem::Image(image, size, _) => {
|
||||||
image::render_image(canvas, state.pre_translate(*pos), image, *size);
|
image::render_image(canvas, state.pre_translate(*pos), image, *size);
|
||||||
}
|
}
|
||||||
FrameItem::Link(..) => {}
|
FrameItem::Link(_, _) => {}
|
||||||
FrameItem::Tag(_) => {}
|
FrameItem::Tag(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user