refactor: add convenience methods to access settable properties

This commit is contained in:
Tobias Schmitz 2025-07-30 18:34:45 +02:00
parent 7ca8468b16
commit 95e0e76e9d
No known key found for this signature in database
3 changed files with 88 additions and 36 deletions

View File

@ -13,10 +13,7 @@ use krilla::tagging::{
TagGroup, TagKind, TagTree,
};
use typst_library::diag::{SourceResult, bail};
use typst_library::foundations::{
Content, LinkMarker, NativeElement, Packed, RefableProperty, Settable,
SettableProperty, StyleChain,
};
use typst_library::foundations::{Content, LinkMarker, Packed};
use typst_library::introspection::Location;
use typst_library::layout::{Abs, Point, Rect, RepeatElem};
use typst_library::math::EquationElem;
@ -34,11 +31,13 @@ use crate::link::LinkAnnotation;
use crate::tags::list::ListCtx;
use crate::tags::outline::OutlineCtx;
use crate::tags::table::TableCtx;
use crate::tags::util::{PropertyOptRef, PropertyValCopied};
use crate::util::AbsExt;
mod list;
mod outline;
mod table;
mod util;
pub(crate) fn handle_start(
gc: &mut GlobalContext,
@ -55,7 +54,7 @@ pub(crate) fn handle_start(
}
if let Some(artifact) = elem.to_packed::<ArtifactElem>() {
let kind = artifact.kind.get(StyleChain::default());
let kind = artifact.kind.val();
push_artifact(gc, surface, elem, kind);
return Ok(());
} else if let Some(_) = elem.to_packed::<RepeatElem>() {
@ -121,7 +120,7 @@ pub(crate) fn handle_start(
} else if let Some(_) = elem.to_packed::<FigureCaption>() {
Tag::Caption.into()
} else if let Some(image) = elem.to_packed::<ImageElem>() {
let alt = image.alt.get_as_ref().map(|s| s.to_string());
let alt = image.alt.opt_ref().map(|s| s.to_string());
if let Some(figure_ctx) = gc.tags.stack.parent_figure() {
// Set alt text of outer figure tag, if not present.
@ -134,12 +133,12 @@ pub(crate) fn handle_start(
return Ok(());
}
} else if let Some(equation) = elem.to_packed::<EquationElem>() {
let alt = equation.alt.get_as_ref().map(|s| s.to_string());
let alt = equation.alt.opt_ref().map(|s| s.to_string());
push_stack(gc, elem, StackEntryKind::Formula(FigureCtx::new(alt)))?;
return Ok(());
} else if let Some(table) = elem.to_packed::<TableElem>() {
let table_id = gc.tags.next_table_id();
let summary = table.summary.get_as_ref().map(|s| s.to_string());
let summary = table.summary.opt_ref().map(|s| s.to_string());
let ctx = TableCtx::new(table_id, summary);
push_stack(gc, elem, StackEntryKind::Table(ctx))?;
return Ok(());
@ -177,11 +176,7 @@ pub(crate) fn handle_start(
return Ok(());
} else if let Some(quote) = elem.to_packed::<QuoteElem>() {
// TODO: should the attribution be handled somehow?
if quote.block.get(StyleChain::default()) {
Tag::BlockQuote.into()
} else {
Tag::InlineQuote.into()
}
if quote.block.val() { Tag::BlockQuote.into() } else { Tag::InlineQuote.into() }
} else {
return Ok(());
};
@ -1047,18 +1042,3 @@ fn artifact_type(kind: ArtifactKind) -> ArtifactType {
ArtifactKind::Other => ArtifactType::Other,
}
}
trait PropertyGetAsRef<E, T, const I: u8> {
fn get_as_ref(&self) -> Option<&T>;
}
impl<E, T, const I: u8> PropertyGetAsRef<E, T, I> for Settable<E, I>
where
E: NativeElement,
E: SettableProperty<I, Type = Option<T>>,
E: RefableProperty<I>,
{
fn get_as_ref(&self) -> Option<&T> {
self.get_ref(StyleChain::default()).as_ref()
}
}

View File

@ -4,11 +4,12 @@ use std::num::NonZeroU32;
use az::SaturatingAs;
use krilla::tagging::{Tag, TagId, TagKind};
use smallvec::SmallVec;
use typst_library::foundations::{Packed, Smart, StyleChain};
use typst_library::foundations::{Packed, Smart};
use typst_library::model::TableCell;
use typst_library::pdf::{TableCellKind, TableHeaderScope};
use typst_syntax::Span;
use crate::tags::util::PropertyValCopied;
use crate::tags::{BBoxCtx, TableId, TagNode};
#[derive(Clone, Debug)]
@ -50,8 +51,8 @@ impl TableCtx {
}
pub(crate) fn contains(&self, cell: &Packed<TableCell>) -> bool {
let x = cell.x.get(StyleChain::default()).unwrap_or_else(|| unreachable!());
let y = cell.y.get(StyleChain::default()).unwrap_or_else(|| unreachable!());
let x = cell.x.val().unwrap_or_else(|| unreachable!());
let y = cell.y.val().unwrap_or_else(|| unreachable!());
self.get(x, y).is_some()
}
@ -64,11 +65,11 @@ impl TableCtx {
}
pub(crate) fn insert(&mut self, cell: &Packed<TableCell>, nodes: Vec<TagNode>) {
let x = cell.x.get(StyleChain::default()).unwrap_or_else(|| unreachable!());
let y = cell.y.get(StyleChain::default()).unwrap_or_else(|| unreachable!());
let rowspan = cell.rowspan.get(StyleChain::default());
let colspan = cell.colspan.get(StyleChain::default());
let kind = cell.kind.get(StyleChain::default());
let x = cell.x.val().unwrap_or_else(|| unreachable!());
let y = cell.y.val().unwrap_or_else(|| unreachable!());
let rowspan = cell.rowspan.val();
let colspan = cell.colspan.val();
let kind = cell.kind.val();
// Extend the table grid to fit this cell.
let required_height = y + rowspan.get();

View File

@ -0,0 +1,71 @@
//! Convenience method to retrieve a property value by passind the default
//! stylechain.
//! Since in the PDF export all elements are materialized, meaning all of their
//! fields have been copied from the stylechain, there is no point in providing
//! any other stylechain.
use typst_library::foundations::{
NativeElement, RefableProperty, Settable, SettableProperty, StyleChain,
};
pub trait PropertyValCopied<E, T, const I: u8> {
/// Get the copied value.
fn val(&self) -> T;
}
impl<E, T: Copy, const I: u8> PropertyValCopied<E, T, I> for Settable<E, I>
where
E: NativeElement,
E: SettableProperty<I, Type = T>,
{
fn val(&self) -> T {
self.get(StyleChain::default())
}
}
pub trait PropertyValCloned<E, T, const I: u8> {
/// Get the cloned value.
fn val_cloned(&self) -> T;
}
impl<E, T: Clone, const I: u8> PropertyValCloned<E, T, I> for Settable<E, I>
where
E: NativeElement,
E: SettableProperty<I, Type = T>,
{
fn val_cloned(&self) -> T {
self.get_cloned(StyleChain::default())
}
}
pub trait PropertyValRef<E, T, const I: u8> {
/// Get a reference to the value.
fn val_ref(&self) -> &T;
}
impl<E, T, const I: u8> PropertyValRef<E, T, I> for Settable<E, I>
where
E: NativeElement,
E: SettableProperty<I, Type = T>,
E: RefableProperty<I>,
{
fn val_ref(&self) -> &T {
self.get_ref(StyleChain::default())
}
}
pub trait PropertyOptRef<E, T, const I: u8> {
fn opt_ref(&self) -> Option<&T>;
}
impl<E, T, const I: u8> PropertyOptRef<E, T, I> for Settable<E, I>
where
E: NativeElement,
E: SettableProperty<I, Type = Option<T>>,
E: RefableProperty<I>,
{
/// Get an `Option` with a reference to the contained value.
fn opt_ref(&self) -> Option<&T> {
self.get_ref(StyleChain::default()).as_ref()
}
}