mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Migrate metadata fields out of individual elements (#3200)
This commit is contained in:
parent
ad901c2cdb
commit
c2dfbd39a0
@ -311,6 +311,8 @@ fn create(element: &Elem) -> Result<TokenStream> {
|
||||
settable.clone().map(|field| create_set_field_method(element, field));
|
||||
|
||||
// Trait implementations.
|
||||
let fields_impl = create_fields_impl(element);
|
||||
let capable_impl = create_capable_impl(element);
|
||||
let native_element_impl = create_native_elem_impl(element);
|
||||
let construct_impl =
|
||||
element.unless_capability("Construct", || create_construct_impl(element));
|
||||
@ -321,23 +323,11 @@ fn create(element: &Elem) -> Result<TokenStream> {
|
||||
element.unless_capability("PartialEq", || create_partial_eq_impl(element));
|
||||
let repr_impl = element.unless_capability("Repr", || create_repr_impl(element));
|
||||
|
||||
let label_and_location = element.unless_capability("Unlabellable", || {
|
||||
quote! {
|
||||
location: Option<::typst::introspection::Location>,
|
||||
label: Option<#foundations::Label>,
|
||||
prepared: bool,
|
||||
}
|
||||
});
|
||||
|
||||
Ok(quote! {
|
||||
#[doc = #docs]
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
#vis struct #ident {
|
||||
span: ::typst::syntax::Span,
|
||||
#label_and_location
|
||||
guards: ::std::vec::Vec<#foundations::Guard>,
|
||||
|
||||
#(#fields,)*
|
||||
}
|
||||
|
||||
@ -353,6 +343,8 @@ fn create(element: &Elem) -> Result<TokenStream> {
|
||||
}
|
||||
|
||||
#native_element_impl
|
||||
#fields_impl
|
||||
#capable_impl
|
||||
#construct_impl
|
||||
#set_impl
|
||||
#locatable_impl
|
||||
@ -406,6 +398,8 @@ fn create_fields_enum(element: &Elem) -> TokenStream {
|
||||
quote! { #enum_ident }
|
||||
});
|
||||
|
||||
let enum_repr = (!fields.is_empty()).then(|| quote! { #[repr(u8)] });
|
||||
|
||||
quote! {
|
||||
// To hide the private type
|
||||
const _: () = {
|
||||
@ -414,10 +408,9 @@ fn create_fields_enum(element: &Elem) -> TokenStream {
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[repr(u8)]
|
||||
#enum_repr
|
||||
pub enum #enum_ident {
|
||||
#(#definitions,)*
|
||||
Label = 255,
|
||||
}
|
||||
|
||||
impl #enum_ident {
|
||||
@ -425,7 +418,6 @@ fn create_fields_enum(element: &Elem) -> TokenStream {
|
||||
pub fn to_str(self) -> &'static str {
|
||||
match self {
|
||||
#(Self::#field_variants => #field_names,)*
|
||||
Self::Label => "label",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -437,7 +429,6 @@ fn create_fields_enum(element: &Elem) -> TokenStream {
|
||||
#(const #field_consts: u8 = #enum_ident::#field_variants as u8;)*
|
||||
match value {
|
||||
#(#field_consts => Ok(Self::#field_variants),)*
|
||||
255 => Ok(Self::Label),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
@ -455,7 +446,6 @@ fn create_fields_enum(element: &Elem) -> TokenStream {
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
#(#field_names => Ok(Self::#field_variants),)*
|
||||
"label" => Ok(Self::Label),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
@ -495,21 +485,10 @@ fn create_new_func(element: &Elem) -> TokenStream {
|
||||
}
|
||||
});
|
||||
|
||||
let label_and_location = element.unless_capability("Unlabellable", || {
|
||||
quote! {
|
||||
location: None,
|
||||
label: None,
|
||||
prepared: false,
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
/// Create a new element.
|
||||
pub fn new(#(#params),*) -> Self {
|
||||
Self {
|
||||
span: ::typst::syntax::Span::detached(),
|
||||
#label_and_location
|
||||
guards: ::std::vec::Vec::with_capacity(0),
|
||||
#(#required,)*
|
||||
#(#defaults,)*
|
||||
#(#default_synthesized,)*
|
||||
@ -700,7 +679,6 @@ fn create_style_chain_access(
|
||||
fn create_native_elem_impl(element: &Elem) -> TokenStream {
|
||||
let Elem { name, ident, title, scope, keywords, docs, .. } = element;
|
||||
|
||||
let vtable_func = create_vtable_func(element);
|
||||
let params = element
|
||||
.fields
|
||||
.iter()
|
||||
@ -713,30 +691,48 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
|
||||
quote! { #foundations::Scope::new() }
|
||||
};
|
||||
|
||||
// Fields that can be accessed using the `field` method.
|
||||
let field_matches = element.visible_fields().map(|field| {
|
||||
let elem = &element.ident;
|
||||
let name = &field.enum_ident;
|
||||
let field_ident = &field.ident;
|
||||
let local_name = element
|
||||
.if_capability(
|
||||
"LocalName",
|
||||
|| quote! { Some(<#foundations::Packed<#ident> as ::typst::text::LocalName>::local_name) },
|
||||
)
|
||||
.unwrap_or_else(|| quote! { None });
|
||||
|
||||
if field.ghost {
|
||||
quote! {
|
||||
<#elem as #foundations::ElementFields>::Fields::#name => None,
|
||||
}
|
||||
} else if field.inherent() || (field.synthesized && field.default.is_some()) {
|
||||
quote! {
|
||||
<#elem as #foundations::ElementFields>::Fields::#name => Some(
|
||||
#foundations::IntoValue::into_value(self.#field_ident.clone())
|
||||
),
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
<#elem as #foundations::ElementFields>::Fields::#name => {
|
||||
self.#field_ident.clone().map(#foundations::IntoValue::into_value)
|
||||
}
|
||||
let data = quote! {
|
||||
#foundations::NativeElementData {
|
||||
name: #name,
|
||||
title: #title,
|
||||
docs: #docs,
|
||||
keywords: &[#(#keywords),*],
|
||||
construct: <#ident as #foundations::Construct>::construct,
|
||||
set: <#ident as #foundations::Set>::set,
|
||||
vtable: <#ident as #foundations::Capable>::vtable,
|
||||
field_id: |name|
|
||||
<
|
||||
<#ident as #foundations::ElementFields>::Fields as ::std::str::FromStr
|
||||
>::from_str(name).ok().map(|id| id as u8),
|
||||
field_name: |id|
|
||||
<
|
||||
<#ident as #foundations::ElementFields>::Fields as ::std::convert::TryFrom<u8>
|
||||
>::try_from(id).ok().map(<#ident as #foundations::ElementFields>::Fields::to_str),
|
||||
local_name: #local_name,
|
||||
scope: #foundations::Lazy::new(|| #scope),
|
||||
params: #foundations::Lazy::new(|| ::std::vec![#(#params),*])
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl #foundations::NativeElement for #ident {
|
||||
fn data() -> &'static #foundations::NativeElementData {
|
||||
static DATA: #foundations::NativeElementData = #data;
|
||||
&DATA
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn create_fields_impl(element: &Elem) -> TokenStream {
|
||||
let Elem { ident, .. } = element;
|
||||
|
||||
// Fields that can be checked using the `has` method.
|
||||
let field_has_matches = element.visible_fields().map(|field| {
|
||||
@ -759,80 +755,6 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
|
||||
}
|
||||
});
|
||||
|
||||
// Fields that can be set using the `set_field` method.
|
||||
let field_set_matches = element
|
||||
.visible_fields()
|
||||
.filter(|field| field.settable() && !field.synthesized && !field.ghost)
|
||||
.map(|field| {
|
||||
let elem = &element.ident;
|
||||
let name = &field.enum_ident;
|
||||
let field_ident = &field.ident;
|
||||
|
||||
quote! {
|
||||
<#elem as #foundations::ElementFields>::Fields::#name => {
|
||||
self.#field_ident = Some(#foundations::FromValue::from_value(value)?);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Fields that are inherent.
|
||||
let field_inherent_matches = element
|
||||
.visible_fields()
|
||||
.filter(|field| field.inherent() && !field.ghost)
|
||||
.map(|field| {
|
||||
let elem = &element.ident;
|
||||
let name = &field.enum_ident;
|
||||
let field_ident = &field.ident;
|
||||
|
||||
quote! {
|
||||
<#elem as #foundations::ElementFields>::Fields::#name => {
|
||||
self.#field_ident = #foundations::FromValue::from_value(value)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Fields that cannot be set or are internal create an error.
|
||||
let field_not_set_matches = element
|
||||
.real_fields()
|
||||
.filter(|field| field.internal || field.synthesized || field.ghost)
|
||||
.map(|field| {
|
||||
let elem = &element.ident;
|
||||
let ident = &field.enum_ident;
|
||||
let field_name = &field.name;
|
||||
if field.internal {
|
||||
// Internal fields create an error that they are unknown.
|
||||
let unknown_field = format!("unknown field `{field_name}` on `{name}`");
|
||||
quote! {
|
||||
<#elem as #foundations::ElementFields>::Fields::#ident => ::typst::diag::bail!(#unknown_field),
|
||||
}
|
||||
} else {
|
||||
// Fields that cannot be set create an error that they are not settable.
|
||||
let not_settable = format!("cannot set `{field_name}` on `{name}`");
|
||||
quote! {
|
||||
<#elem as #foundations::ElementFields>::Fields::#ident => ::typst::diag::bail!(#not_settable),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Statistically compute whether we need preparation or not.
|
||||
let needs_preparation = element
|
||||
.unless_capability("Unlabellable", || {
|
||||
element
|
||||
.capabilities
|
||||
.iter()
|
||||
.any(|capability| capability == "Locatable" || capability == "Synthesize")
|
||||
.then(|| quote! { !self.prepared })
|
||||
.unwrap_or_else(|| quote! { self.label().is_some() && !self.prepared })
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
assert!(element.capabilities.iter().all(|capability| capability
|
||||
!= "Locatable"
|
||||
&& capability != "Synthesize"));
|
||||
quote! { false }
|
||||
});
|
||||
|
||||
// Creation of the fields dictionary for inherent fields.
|
||||
let field_dict = element
|
||||
.inherent_fields()
|
||||
@ -878,226 +800,58 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
|
||||
}
|
||||
});
|
||||
|
||||
let location = element
|
||||
.unless_capability("Unlabellable", || quote! { self.location })
|
||||
.unwrap_or_else(|| quote! { None });
|
||||
// Fields that can be accessed using the `field` method.
|
||||
let field_matches = element.visible_fields().map(|field| {
|
||||
let elem = &element.ident;
|
||||
let name = &field.enum_ident;
|
||||
let field_ident = &field.ident;
|
||||
|
||||
let set_location = element
|
||||
.unless_capability("Unlabellable", || {
|
||||
if field.ghost {
|
||||
quote! {
|
||||
self.location = Some(location);
|
||||
<#elem as #foundations::ElementFields>::Fields::#name => None,
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| quote! { drop(location) });
|
||||
|
||||
let label = element
|
||||
.unless_capability("Unlabellable", || quote! { self.label })
|
||||
.unwrap_or_else(|| quote! { None });
|
||||
|
||||
let set_label = element
|
||||
.unless_capability("Unlabellable", || {
|
||||
} else if field.inherent() || (field.synthesized && field.default.is_some()) {
|
||||
quote! {
|
||||
self.label = Some(label);
|
||||
<#elem as #foundations::ElementFields>::Fields::#name => Some(
|
||||
#foundations::IntoValue::into_value(self.#field_ident.clone())
|
||||
),
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| quote! { drop(label) });
|
||||
|
||||
let label_field = element
|
||||
.unless_capability("Unlabellable", || {
|
||||
} else {
|
||||
quote! {
|
||||
self.label().map(#foundations::Value::Label)
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| quote! { None });
|
||||
|
||||
let label_has_field = element
|
||||
.unless_capability("Unlabellable", || quote! { self.label().is_some() })
|
||||
.unwrap_or_else(|| quote! { false });
|
||||
|
||||
let label_field_dict = element.unless_capability("Unlabellable", || {
|
||||
quote! {
|
||||
if let Some(label) = self.label() {
|
||||
fields.insert(
|
||||
"label".into(),
|
||||
#foundations::IntoValue::into_value(label)
|
||||
);
|
||||
<#elem as #foundations::ElementFields>::Fields::#name => {
|
||||
self.#field_ident.clone().map(#foundations::IntoValue::into_value)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let mark_prepared = element
|
||||
.unless_capability("Unlabellable", || quote! { self.prepared = true; })
|
||||
.unwrap_or_else(|| quote! {});
|
||||
|
||||
let prepared = element
|
||||
.unless_capability("Unlabellable", || quote! { self.prepared })
|
||||
.unwrap_or_else(|| quote! { true });
|
||||
|
||||
let local_name = element
|
||||
.if_capability(
|
||||
"LocalName",
|
||||
|| quote! { Some(<#ident as ::typst::text::LocalName>::local_name) },
|
||||
)
|
||||
.unwrap_or_else(|| quote! { None });
|
||||
|
||||
let unknown_field = format!("unknown field {{}} on {name}");
|
||||
let label_error = format!("cannot set label on {name}");
|
||||
let data = quote! {
|
||||
#foundations::NativeElementData {
|
||||
name: #name,
|
||||
title: #title,
|
||||
docs: #docs,
|
||||
keywords: &[#(#keywords),*],
|
||||
construct: <#ident as #foundations::Construct>::construct,
|
||||
set: <#ident as #foundations::Set>::set,
|
||||
vtable: #vtable_func,
|
||||
field_id: |name|
|
||||
<
|
||||
<#ident as #foundations::ElementFields>::Fields as ::std::str::FromStr
|
||||
>::from_str(name).ok().map(|id| id as u8),
|
||||
field_name: |id|
|
||||
<
|
||||
<#ident as #foundations::ElementFields>::Fields as ::std::convert::TryFrom<u8>
|
||||
>::try_from(id).ok().map(<#ident as #foundations::ElementFields>::Fields::to_str),
|
||||
local_name: #local_name,
|
||||
scope: #foundations::Lazy::new(|| #scope),
|
||||
params: #foundations::Lazy::new(|| ::std::vec![#(#params),*])
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl #foundations::NativeElement for #ident {
|
||||
fn data() -> &'static #foundations::NativeElementData {
|
||||
static DATA: #foundations::NativeElementData = #data;
|
||||
&DATA
|
||||
}
|
||||
|
||||
fn dyn_elem(&self) -> #foundations::Element {
|
||||
#foundations::Element::of::<Self>()
|
||||
}
|
||||
|
||||
fn dyn_hash(&self, mut state: &mut dyn ::std::hash::Hasher) {
|
||||
// Also hash the TypeId since values with different types but
|
||||
// equal data should be different.
|
||||
::std::hash::Hash::hash(&::std::any::TypeId::of::<Self>(), &mut state);
|
||||
::std::hash::Hash::hash(self, &mut state);
|
||||
}
|
||||
|
||||
fn dyn_eq(&self, other: &#foundations::Content) -> bool {
|
||||
if let Some(other) = other.to::<Self>() {
|
||||
<Self as ::std::cmp::PartialEq>::eq(self, other)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn dyn_clone(&self) -> ::std::sync::Arc<dyn #foundations::NativeElement> {
|
||||
::std::sync::Arc::new(Clone::clone(self))
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_any(self: ::std::sync::Arc<Self>) -> ::std::sync::Arc<dyn ::std::any::Any + Send + Sync> {
|
||||
self
|
||||
}
|
||||
|
||||
fn span(&self) -> ::typst::syntax::Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
fn set_span(&mut self, span: ::typst::syntax::Span) {
|
||||
if self.span().is_detached() {
|
||||
self.span = span;
|
||||
}
|
||||
}
|
||||
|
||||
fn label(&self) -> Option<#foundations::Label> {
|
||||
#label
|
||||
}
|
||||
|
||||
fn set_label(&mut self, label: #foundations::Label) {
|
||||
#set_label
|
||||
}
|
||||
|
||||
fn location(&self) -> Option<::typst::introspection::Location> {
|
||||
#location
|
||||
}
|
||||
|
||||
fn set_location(&mut self, location: ::typst::introspection::Location) {
|
||||
#set_location
|
||||
}
|
||||
|
||||
fn push_guard(&mut self, guard: #foundations::Guard) {
|
||||
self.guards.push(guard);
|
||||
}
|
||||
|
||||
fn is_guarded(&self, guard: #foundations::Guard) -> bool {
|
||||
self.guards.contains(&guard)
|
||||
}
|
||||
|
||||
fn is_pristine(&self) -> bool {
|
||||
self.guards.is_empty()
|
||||
}
|
||||
|
||||
fn mark_prepared(&mut self) {
|
||||
#mark_prepared
|
||||
}
|
||||
|
||||
fn needs_preparation(&self) -> bool {
|
||||
#needs_preparation
|
||||
}
|
||||
|
||||
fn is_prepared(&self) -> bool {
|
||||
#prepared
|
||||
}
|
||||
|
||||
fn field(&self, id: u8) -> Option<#foundations::Value> {
|
||||
let id = <#ident as #foundations::ElementFields>::Fields::try_from(id).ok()?;
|
||||
match id {
|
||||
<#ident as #foundations::ElementFields>::Fields::Label => #label_field,
|
||||
#(#field_matches)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
impl #foundations::Fields for #ident {
|
||||
fn has(&self, id: u8) -> bool {
|
||||
let Ok(id) = <#ident as #foundations::ElementFields>::Fields::try_from(id) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
match id {
|
||||
<#ident as #foundations::ElementFields>::Fields::Label => #label_has_field,
|
||||
#(#field_has_matches)*
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn field(&self, id: u8) -> Option<#foundations::Value> {
|
||||
let id = <#ident as #foundations::ElementFields>::Fields::try_from(id).ok()?;
|
||||
match id {
|
||||
#(#field_matches)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn fields(&self) -> #foundations::Dict {
|
||||
let mut fields = #foundations::Dict::new();
|
||||
#label_field_dict
|
||||
#(#field_dict)*
|
||||
#(#field_opt_dict)*
|
||||
fields
|
||||
}
|
||||
|
||||
fn set_field(&mut self, id: u8, value: #foundations::Value) -> ::typst::diag::StrResult<()> {
|
||||
let id = <#ident as #foundations::ElementFields>::Fields::try_from(id)
|
||||
.map_err(|_| ::ecow::eco_format!(#unknown_field, id))?;
|
||||
match id {
|
||||
#(#field_set_matches)*
|
||||
#(#field_inherent_matches)*
|
||||
#(#field_not_set_matches)*
|
||||
<#ident as #foundations::ElementFields>::Fields::Label => {
|
||||
::typst::diag::bail!(#label_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1182,7 +936,7 @@ fn create_set_impl(element: &Elem) -> TokenStream {
|
||||
/// Creates the element's `Locatable` implementation.
|
||||
fn create_locatable_impl(element: &Elem) -> TokenStream {
|
||||
let ident = &element.ident;
|
||||
quote! { impl ::typst::introspection::Locatable for #ident {} }
|
||||
quote! { impl ::typst::introspection::Locatable for #foundations::Packed<#ident> {} }
|
||||
}
|
||||
|
||||
/// Creates the element's `PartialEq` implementation.
|
||||
@ -1208,7 +962,7 @@ fn create_repr_impl(element: &Elem) -> TokenStream {
|
||||
quote! {
|
||||
impl #foundations::Repr for #ident {
|
||||
fn repr(&self) -> ::ecow::EcoString {
|
||||
let fields = #foundations::NativeElement::fields(self).into_iter()
|
||||
let fields = #foundations::Fields::fields(self).into_iter()
|
||||
.map(|(name, value)| ::ecow::eco_format!("{}: {}", name, value.repr()))
|
||||
.collect::<Vec<_>>();
|
||||
::ecow::eco_format!(#repr_format, #foundations::repr::pretty_array_like(&fields, false))
|
||||
@ -1218,9 +972,9 @@ fn create_repr_impl(element: &Elem) -> TokenStream {
|
||||
}
|
||||
|
||||
/// Creates the element's casting vtable.
|
||||
fn create_vtable_func(element: &Elem) -> TokenStream {
|
||||
fn create_capable_impl(element: &Elem) -> TokenStream {
|
||||
// Forbidden capabilities (i.e capabilities that are not object safe).
|
||||
const FORBIDDEN: &[&str] = &["Construct", "PartialEq", "Hash", "LocalName"];
|
||||
const FORBIDDEN: &[&str] = &["Construct", "PartialEq", "Hash", "LocalName", "Repr"];
|
||||
|
||||
let ident = &element.ident;
|
||||
let relevant = element
|
||||
@ -1229,20 +983,23 @@ fn create_vtable_func(element: &Elem) -> TokenStream {
|
||||
.filter(|&ident| !FORBIDDEN.contains(&(&ident.to_string() as &str)));
|
||||
let checks = relevant.map(|capability| {
|
||||
quote! {
|
||||
if id == ::std::any::TypeId::of::<dyn #capability>() {
|
||||
let vtable = unsafe {
|
||||
let dangling = ::std::ptr::NonNull::<#ident>::dangling().as_ptr() as *const dyn #capability;
|
||||
::typst::util::fat::vtable(dangling)
|
||||
};
|
||||
return Some(vtable);
|
||||
if capability == ::std::any::TypeId::of::<dyn #capability>() {
|
||||
// Safety: The vtable function doesn't require initialized
|
||||
// data, so it's fine to use a dangling pointer.
|
||||
return Some(unsafe {
|
||||
::typst::util::fat::vtable(dangling as *const dyn #capability)
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
|id| {
|
||||
#(#checks)*
|
||||
None
|
||||
unsafe impl #foundations::Capable for #ident {
|
||||
fn vtable(capability: ::std::any::TypeId) -> ::std::option::Option<*const ()> {
|
||||
let dangling = ::std::ptr::NonNull::<#foundations::Packed<#ident>>::dangling().as_ptr();
|
||||
#(#checks)*
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use pdf_writer::{Finish, Ref, TextStr};
|
||||
use typst::foundations::{Content, NativeElement, Smart};
|
||||
use typst::foundations::{NativeElement, Packed, StyleChain};
|
||||
use typst::layout::Abs;
|
||||
use typst::model::HeadingElem;
|
||||
|
||||
@ -17,8 +17,10 @@ pub(crate) fn write_outline(ctx: &mut PdfContext) -> Option<Ref> {
|
||||
// Therefore, its next descendant must be added at its level, which is
|
||||
// enforced in the manner shown below.
|
||||
let mut last_skipped_level = None;
|
||||
for heading in ctx.document.introspector.query(&HeadingElem::elem().select()).iter() {
|
||||
let leaf = HeadingNode::leaf((**heading).clone());
|
||||
let elements = ctx.document.introspector.query(&HeadingElem::elem().select());
|
||||
for elem in elements.iter() {
|
||||
let heading = elem.to::<HeadingElem>().unwrap();
|
||||
let leaf = HeadingNode::leaf(heading);
|
||||
|
||||
if leaf.bookmarked {
|
||||
let mut children = &mut tree;
|
||||
@ -103,21 +105,21 @@ pub(crate) fn write_outline(ctx: &mut PdfContext) -> Option<Ref> {
|
||||
|
||||
/// A heading in the outline panel.
|
||||
#[derive(Debug, Clone)]
|
||||
struct HeadingNode {
|
||||
element: Content,
|
||||
struct HeadingNode<'a> {
|
||||
element: &'a Packed<HeadingElem>,
|
||||
level: NonZeroUsize,
|
||||
bookmarked: bool,
|
||||
children: Vec<HeadingNode>,
|
||||
children: Vec<HeadingNode<'a>>,
|
||||
}
|
||||
|
||||
impl HeadingNode {
|
||||
fn leaf(element: Content) -> Self {
|
||||
impl<'a> HeadingNode<'a> {
|
||||
fn leaf(element: &'a Packed<HeadingElem>) -> Self {
|
||||
HeadingNode {
|
||||
level: element.expect_field_by_name::<NonZeroUsize>("level"),
|
||||
level: element.level(StyleChain::default()),
|
||||
// 'bookmarked' set to 'auto' falls back to the value of 'outlined'.
|
||||
bookmarked: element
|
||||
.expect_field_by_name::<Smart<bool>>("bookmarked")
|
||||
.unwrap_or_else(|| element.expect_field_by_name::<bool>("outlined")),
|
||||
.bookmarked(StyleChain::default())
|
||||
.unwrap_or_else(|| element.outlined(StyleChain::default())),
|
||||
element,
|
||||
children: Vec::new(),
|
||||
}
|
||||
@ -157,7 +159,7 @@ fn write_outline_item(
|
||||
outline.count(-(node.children.len() as i32));
|
||||
}
|
||||
|
||||
let body = node.element.expect_field_by_name::<Content>("body");
|
||||
let body = node.element.body();
|
||||
outline.title(TextStr(body.plain_text().trim()));
|
||||
|
||||
let loc = node.element.location().unwrap();
|
||||
|
@ -9,7 +9,7 @@ use smallvec::SmallVec;
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use crate::diag::{At, SourceResult, StrResult};
|
||||
use crate::foundations::{repr, Repr, Type, Value};
|
||||
use crate::foundations::{repr, NativeElement, Packed, Repr, Type, Value};
|
||||
use crate::syntax::{Span, Spanned};
|
||||
|
||||
#[rustfmt::skip]
|
||||
@ -84,6 +84,20 @@ impl<T: Reflect> Reflect for Spanned<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NativeElement + Reflect> Reflect for Packed<T> {
|
||||
fn input() -> CastInfo {
|
||||
T::input()
|
||||
}
|
||||
|
||||
fn output() -> CastInfo {
|
||||
T::output()
|
||||
}
|
||||
|
||||
fn castable(value: &Value) -> bool {
|
||||
T::castable(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Reflect> Reflect for Prehashed<T> {
|
||||
fn input() -> CastInfo {
|
||||
T::input()
|
||||
@ -174,6 +188,12 @@ impl<T: IntoValue + Clone> IntoValue for Cow<'_, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NativeElement + IntoValue> IntoValue for Packed<T> {
|
||||
fn into_value(self) -> Value {
|
||||
Value::Content(self.pack())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IntoValue> IntoValue for Spanned<T> {
|
||||
fn into_value(self) -> Value {
|
||||
self.v.into_value()
|
||||
@ -233,6 +253,19 @@ impl FromValue for Value {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NativeElement + FromValue> FromValue for Packed<T> {
|
||||
fn from_value(mut value: Value) -> StrResult<Self> {
|
||||
if let Value::Content(content) = value {
|
||||
match content.to_packed::<T>() {
|
||||
Ok(packed) => return Ok(packed),
|
||||
Err(content) => value = Value::Content(content),
|
||||
}
|
||||
}
|
||||
let val = T::from_value(value)?;
|
||||
Ok(Packed::new(val))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FromValue + Hash + 'static> FromValue for Prehashed<T> {
|
||||
fn from_value(value: Value) -> StrResult<Self> {
|
||||
Ok(Self::new(T::from_value(value)?))
|
||||
|
@ -1,7 +1,9 @@
|
||||
use std::any::TypeId;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter::{self, Sum};
|
||||
use std::ops::{Add, AddAssign};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Add, AddAssign, Deref, DerefMut};
|
||||
use std::sync::Arc;
|
||||
|
||||
use comemo::Prehashed;
|
||||
@ -12,10 +14,10 @@ use smallvec::smallvec;
|
||||
use crate::diag::{SourceResult, StrResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
elem, func, scope, ty, Dict, Element, FromValue, Guard, IntoValue, Label,
|
||||
NativeElement, Recipe, Repr, Selector, Str, Style, Styles, Value,
|
||||
elem, func, scope, ty, Dict, Element, Fields, Guard, IntoValue, Label, NativeElement,
|
||||
Recipe, Repr, Selector, Str, Style, Styles, Synthesize, Value,
|
||||
};
|
||||
use crate::introspection::{Location, Meta, MetaElem};
|
||||
use crate::introspection::{Locatable, Location, Meta, MetaElem};
|
||||
use crate::layout::{AlignElem, Alignment, Axes, Length, MoveElem, PadElem, Rel, Sides};
|
||||
use crate::model::{Destination, EmphElem, StrongElem};
|
||||
use crate::syntax::Span;
|
||||
@ -68,12 +70,34 @@ use crate::util::fat;
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Content(Arc<dyn NativeElement>);
|
||||
pub struct Content {
|
||||
inner: Arc<Inner<dyn Bounds>>,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
/// The inner representation behind the `Arc`.
|
||||
#[derive(Hash)]
|
||||
struct Inner<T: ?Sized> {
|
||||
label: Option<Label>,
|
||||
location: Option<Location>,
|
||||
prepared: bool,
|
||||
guards: Vec<Guard>,
|
||||
elem: T,
|
||||
}
|
||||
|
||||
impl Content {
|
||||
/// Creates a new content from an element.
|
||||
pub fn new<E: NativeElement>(elem: E) -> Self {
|
||||
Self(Arc::new(elem))
|
||||
pub fn new<T: NativeElement>(elem: T) -> Self {
|
||||
Self {
|
||||
inner: Arc::new(Inner {
|
||||
label: None,
|
||||
location: None,
|
||||
prepared: false,
|
||||
guards: vec![],
|
||||
elem,
|
||||
}),
|
||||
span: Span::detached(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new empty sequence content.
|
||||
@ -83,65 +107,70 @@ impl Content {
|
||||
|
||||
/// Get the element of this content.
|
||||
pub fn elem(&self) -> Element {
|
||||
self.0.dyn_elem()
|
||||
self.inner.elem.dyn_elem()
|
||||
}
|
||||
|
||||
/// Get the span of the content.
|
||||
pub fn span(&self) -> Span {
|
||||
self.0.span()
|
||||
self.span
|
||||
}
|
||||
|
||||
/// Set the span of the content.
|
||||
pub fn spanned(mut self, span: Span) -> Self {
|
||||
self.make_mut().set_span(span);
|
||||
if self.span.is_detached() {
|
||||
self.span = span;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Get the label of the content.
|
||||
pub fn label(&self) -> Option<Label> {
|
||||
self.0.label()
|
||||
self.inner.label
|
||||
}
|
||||
|
||||
/// Set the label of the content.
|
||||
pub fn labelled(mut self, label: Label) -> Self {
|
||||
self.make_mut().set_label(label);
|
||||
self.make_mut().label = Some(label);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the location of the content.
|
||||
pub fn set_location(&mut self, location: Location) {
|
||||
self.make_mut().set_location(location);
|
||||
self.make_mut().location = Some(location);
|
||||
}
|
||||
|
||||
/// Disable a show rule recipe.
|
||||
pub fn guarded(mut self, guard: Guard) -> Self {
|
||||
self.make_mut().push_guard(guard);
|
||||
self.0.into()
|
||||
self.make_mut().guards.push(guard);
|
||||
self
|
||||
}
|
||||
|
||||
/// Whether the content needs to be realized specially.
|
||||
pub fn needs_preparation(&self) -> bool {
|
||||
self.0.needs_preparation()
|
||||
(self.can::<dyn Locatable>()
|
||||
|| self.can::<dyn Synthesize>()
|
||||
|| self.label().is_some())
|
||||
&& !self.inner.prepared
|
||||
}
|
||||
|
||||
/// Check whether a show rule recipe is disabled.
|
||||
pub fn is_guarded(&self, guard: Guard) -> bool {
|
||||
self.0.is_guarded(guard)
|
||||
self.inner.guards.contains(&guard)
|
||||
}
|
||||
|
||||
/// Whether no show rule was executed for this content so far.
|
||||
pub fn is_pristine(&self) -> bool {
|
||||
self.0.is_pristine()
|
||||
self.inner.guards.is_empty()
|
||||
}
|
||||
|
||||
/// Whether this content has already been prepared.
|
||||
pub fn is_prepared(&self) -> bool {
|
||||
self.0.is_prepared()
|
||||
self.inner.prepared
|
||||
}
|
||||
|
||||
/// Mark this content as prepared.
|
||||
pub fn mark_prepared(&mut self) {
|
||||
self.make_mut().mark_prepared();
|
||||
self.make_mut().prepared = true;
|
||||
}
|
||||
|
||||
/// Get a field by ID.
|
||||
@ -150,7 +179,12 @@ impl Content {
|
||||
/// if you have set the field IDs yourself or are using the field IDs
|
||||
/// generated by the `#[elem]` macro.
|
||||
pub fn get(&self, id: u8) -> Option<Value> {
|
||||
self.0.field(id)
|
||||
if id == 255 {
|
||||
if let Some(label) = self.label() {
|
||||
return Some(label.into_value());
|
||||
}
|
||||
}
|
||||
self.inner.elem.field(id)
|
||||
}
|
||||
|
||||
/// Get a field by name.
|
||||
@ -158,6 +192,11 @@ impl Content {
|
||||
/// If you have access to the field IDs of the element, use [`Self::get`]
|
||||
/// instead.
|
||||
pub fn get_by_name(&self, name: &str) -> Option<Value> {
|
||||
if name == "label" {
|
||||
if let Some(label) = self.label() {
|
||||
return Some(label.into_value());
|
||||
}
|
||||
}
|
||||
let id = self.elem().field_id(name)?;
|
||||
self.get(id)
|
||||
}
|
||||
@ -178,26 +217,7 @@ impl Content {
|
||||
/// If you have access to the field IDs of the element, use [`Self::field`]
|
||||
/// instead.
|
||||
pub fn field_by_name(&self, name: &str) -> StrResult<Value> {
|
||||
let id = self.elem().field_id(name).ok_or_else(|| missing_field(name))?;
|
||||
self.field(id)
|
||||
}
|
||||
|
||||
/// Expect a field on the content to exist as a specified type.
|
||||
#[track_caller]
|
||||
pub fn expect_field<T: FromValue>(&self, id: u8) -> T {
|
||||
self.field(id).unwrap().cast().unwrap()
|
||||
}
|
||||
|
||||
/// Expect a field on the content to exist as a specified type.
|
||||
#[track_caller]
|
||||
pub fn expect_field_by_name<T: FromValue>(&self, name: &str) -> T {
|
||||
self.field_by_name(name).unwrap().cast().unwrap()
|
||||
}
|
||||
|
||||
/// Set a field to the content.
|
||||
pub fn with_field(mut self, id: u8, value: impl IntoValue) -> Self {
|
||||
self.make_mut().set_field(id, value.into_value()).unwrap();
|
||||
self
|
||||
self.get_by_name(name).ok_or_else(|| missing_field(name))
|
||||
}
|
||||
|
||||
/// Create a new sequence element from multiples elements.
|
||||
@ -214,18 +234,34 @@ impl Content {
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Access the children if this is a sequence.
|
||||
pub fn to_sequence(&self) -> Option<impl Iterator<Item = &Prehashed<Content>>> {
|
||||
let Some(sequence) = self.to::<SequenceElem>() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(sequence.children.iter())
|
||||
}
|
||||
|
||||
/// Whether the contained element is of type `T`.
|
||||
pub fn is<T: NativeElement>(&self) -> bool {
|
||||
self.elem() == T::elem()
|
||||
self.inner.elem.dyn_type_id() == TypeId::of::<T>()
|
||||
}
|
||||
|
||||
/// Downcasts the element to a packed value.
|
||||
pub fn to<T: NativeElement>(&self) -> Option<&Packed<T>> {
|
||||
Packed::from_ref(self)
|
||||
}
|
||||
|
||||
/// Downcasts the element to a mutable packed value.
|
||||
pub fn to_mut<T: NativeElement>(&mut self) -> Option<&mut Packed<T>> {
|
||||
Packed::from_mut(self)
|
||||
}
|
||||
|
||||
/// Downcasts the element into an owned packed value.
|
||||
pub fn to_packed<T: NativeElement>(self) -> Result<Packed<T>, Self> {
|
||||
Packed::from_owned(self)
|
||||
}
|
||||
|
||||
/// Makes sure the content is not shared and returns a mutable reference to
|
||||
/// the inner data.
|
||||
fn make_mut(&mut self) -> &mut Inner<dyn Bounds> {
|
||||
let arc = &mut self.inner;
|
||||
if Arc::strong_count(arc) > 1 || Arc::weak_count(arc) > 0 {
|
||||
*self = arc.elem.dyn_clone(arc, self.span);
|
||||
}
|
||||
Arc::get_mut(&mut self.inner).unwrap()
|
||||
}
|
||||
|
||||
/// Whether the contained element has the given capability.
|
||||
@ -236,20 +272,18 @@ impl Content {
|
||||
self.elem().can::<C>()
|
||||
}
|
||||
|
||||
/// Whether the contained element has the given capability where the
|
||||
/// capability is given by a `TypeId`.
|
||||
pub fn can_type_id(&self, type_id: TypeId) -> bool {
|
||||
self.elem().can_type_id(type_id)
|
||||
}
|
||||
|
||||
/// Cast to a trait object if the contained element has the given
|
||||
/// capability.
|
||||
pub fn with<C>(&self) -> Option<&C>
|
||||
where
|
||||
C: ?Sized + 'static,
|
||||
{
|
||||
// Safety: The vtable comes from the `Capable` implementation which
|
||||
// guarantees to return a matching vtable for `Packed<T>` and `C`.
|
||||
// Since any `Packed<T>` is a repr(transparent) `Content`, we can also
|
||||
// use a `*const Content` pointer.
|
||||
let vtable = self.elem().vtable()(TypeId::of::<C>())?;
|
||||
let data = Arc::as_ptr(&self.0) as *const ();
|
||||
let data = self as *const Content as *const ();
|
||||
Some(unsafe { &*fat::from_raw_parts(data, vtable) })
|
||||
}
|
||||
|
||||
@ -259,17 +293,20 @@ impl Content {
|
||||
where
|
||||
C: ?Sized + 'static,
|
||||
{
|
||||
// Safety: We ensure the element is not shared.
|
||||
// Safety: The vtable comes from the `Capable` implementation which
|
||||
// guarantees to return a matching vtable for `Packed<T>` and `C`.
|
||||
// Since any `Packed<T>` is a repr(transparent) `Content`, we can also
|
||||
// use a `*const Content` pointer.
|
||||
//
|
||||
// The resulting trait object contains an `&mut Packed<T>`. We do _not_
|
||||
// need to ensure that we hold the only reference to the `Arc` here
|
||||
// because `Packed<T>`'s DerefMut impl will take care of that if
|
||||
// mutable access is required.
|
||||
let vtable = self.elem().vtable()(TypeId::of::<C>())?;
|
||||
let data = self.make_mut() as *mut dyn NativeElement as *mut ();
|
||||
let data = self as *mut Content as *mut ();
|
||||
Some(unsafe { &mut *fat::from_raw_parts_mut(data, vtable) })
|
||||
}
|
||||
|
||||
/// Whether the content is a sequence.
|
||||
pub fn is_sequence(&self) -> bool {
|
||||
self.is::<SequenceElem>()
|
||||
}
|
||||
|
||||
/// Whether the content is an empty sequence.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
let Some(sequence) = self.to::<SequenceElem>() else {
|
||||
@ -279,6 +316,17 @@ impl Content {
|
||||
sequence.children.is_empty()
|
||||
}
|
||||
|
||||
/// Whether the content is a sequence.
|
||||
pub fn is_sequence(&self) -> bool {
|
||||
self.is::<SequenceElem>()
|
||||
}
|
||||
|
||||
/// Access the children if this is a sequence.
|
||||
pub fn to_sequence(&self) -> Option<impl Iterator<Item = &Prehashed<Content>>> {
|
||||
let sequence = self.to::<SequenceElem>()?;
|
||||
Some(sequence.children.iter())
|
||||
}
|
||||
|
||||
/// Also auto expands sequence of sequences into flat sequence
|
||||
pub fn sequence_recursive_for_each(&self, f: &mut impl FnMut(&Self)) {
|
||||
if let Some(children) = self.to_sequence() {
|
||||
@ -383,7 +431,8 @@ impl Content {
|
||||
{
|
||||
f(self.clone());
|
||||
|
||||
self.0
|
||||
self.inner
|
||||
.elem
|
||||
.fields()
|
||||
.into_iter()
|
||||
.for_each(|(_, value)| walk_value(value, f));
|
||||
@ -404,47 +453,6 @@ impl Content {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Downcasts the element to the specified type.
|
||||
pub fn to<T: NativeElement>(&self) -> Option<&T> {
|
||||
// Early check for performance.
|
||||
if !self.is::<T>() {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.0.as_any().downcast_ref()
|
||||
}
|
||||
|
||||
/// Downcasts mutably the element to the specified type.
|
||||
pub fn to_mut<T: NativeElement>(&mut self) -> Option<&mut T> {
|
||||
// Early check for performance.
|
||||
if !self.is::<T>() {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.make_mut().as_any_mut().downcast_mut()
|
||||
}
|
||||
|
||||
/// Downcast the element into an owned value.
|
||||
pub fn unpack<T: NativeElement>(self) -> Option<Arc<T>> {
|
||||
// Early check for performance.
|
||||
if !self.is::<T>() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Arc::downcast(self.0.into_any()).ok()
|
||||
}
|
||||
|
||||
/// Makes sure the content is not shared and returns a mutable reference to
|
||||
/// the inner element.
|
||||
fn make_mut(&mut self) -> &mut dyn NativeElement {
|
||||
let arc = &mut self.0;
|
||||
if Arc::strong_count(arc) > 1 || Arc::weak_count(arc) > 0 {
|
||||
*arc = arc.dyn_clone();
|
||||
}
|
||||
|
||||
Arc::get_mut(arc).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Content {
|
||||
@ -517,11 +525,15 @@ impl Content {
|
||||
/// The field to look for.
|
||||
field: Str,
|
||||
) -> bool {
|
||||
if field.as_str() == "label" {
|
||||
return self.label().is_some();
|
||||
}
|
||||
|
||||
let Some(id) = self.elem().field_id(&field) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
self.0.has(id)
|
||||
self.inner.elem.has(id)
|
||||
}
|
||||
|
||||
/// Access the specified field on the content. Returns the default value if
|
||||
@ -536,11 +548,7 @@ impl Content {
|
||||
#[named]
|
||||
default: Option<Value>,
|
||||
) -> StrResult<Value> {
|
||||
let Some(id) = self.elem().field_id(&field) else {
|
||||
return default.ok_or_else(|| missing_field_no_default(&field));
|
||||
};
|
||||
|
||||
self.get(id)
|
||||
self.get_by_name(&field)
|
||||
.or(default)
|
||||
.ok_or_else(|| missing_field_no_default(&field))
|
||||
}
|
||||
@ -555,7 +563,11 @@ impl Content {
|
||||
/// ```
|
||||
#[func]
|
||||
pub fn fields(&self) -> Dict {
|
||||
self.0.fields()
|
||||
let mut dict = self.inner.elem.fields();
|
||||
if let Some(label) = self.label() {
|
||||
dict.insert("label".into(), label.into_value());
|
||||
}
|
||||
dict
|
||||
}
|
||||
|
||||
/// The location of the content. This is only available on content returned
|
||||
@ -565,7 +577,7 @@ impl Content {
|
||||
/// [counters]($counter), [state]($state) and [queries]($query).
|
||||
#[func]
|
||||
pub fn location(&self) -> Option<Location> {
|
||||
self.0.location()
|
||||
self.inner.location
|
||||
}
|
||||
}
|
||||
|
||||
@ -577,7 +589,7 @@ impl Default for Content {
|
||||
|
||||
impl Debug for Content {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
self.inner.elem.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
@ -587,22 +599,16 @@ impl<T: NativeElement> From<T> for Content {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Arc<dyn NativeElement>> for Content {
|
||||
fn from(value: Arc<dyn NativeElement>) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Content {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
// Additional short circuit for different elements.
|
||||
self.elem() == other.elem() && self.0.dyn_eq(other)
|
||||
self.elem() == other.elem() && self.inner.elem.dyn_eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for Content {
|
||||
fn repr(&self) -> EcoString {
|
||||
self.0.repr()
|
||||
self.inner.elem.repr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -686,23 +692,199 @@ impl Serialize for Content {
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines the `ElemFunc` for sequences.
|
||||
/// The trait that combines all the other traits into a trait object.
|
||||
trait Bounds: Debug + Repr + Fields + Send + Sync + 'static {
|
||||
fn dyn_type_id(&self) -> TypeId;
|
||||
fn dyn_elem(&self) -> Element;
|
||||
fn dyn_clone(&self, inner: &Inner<dyn Bounds>, span: Span) -> Content;
|
||||
fn dyn_hash(&self, hasher: &mut dyn Hasher);
|
||||
fn dyn_eq(&self, other: &Content) -> bool;
|
||||
}
|
||||
|
||||
impl<T: NativeElement> Bounds for T {
|
||||
fn dyn_type_id(&self) -> TypeId {
|
||||
TypeId::of::<Self>()
|
||||
}
|
||||
|
||||
fn dyn_elem(&self) -> Element {
|
||||
Self::elem()
|
||||
}
|
||||
|
||||
fn dyn_clone(&self, inner: &Inner<dyn Bounds>, span: Span) -> Content {
|
||||
Content {
|
||||
inner: Arc::new(Inner {
|
||||
label: inner.label,
|
||||
location: inner.location,
|
||||
prepared: inner.prepared,
|
||||
guards: inner.guards.clone(),
|
||||
elem: self.clone(),
|
||||
}),
|
||||
span,
|
||||
}
|
||||
}
|
||||
|
||||
fn dyn_hash(&self, mut state: &mut dyn Hasher) {
|
||||
TypeId::of::<Self>().hash(&mut state);
|
||||
self.hash(&mut state);
|
||||
}
|
||||
|
||||
fn dyn_eq(&self, other: &Content) -> bool {
|
||||
let Some(other) = other.to::<Self>() else {
|
||||
return false;
|
||||
};
|
||||
*self == **other
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for dyn Bounds {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.dyn_hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// A packed element of a static type.
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct Packed<T: NativeElement>(
|
||||
/// Invariant: Must be of type `T`.
|
||||
Content,
|
||||
PhantomData<T>,
|
||||
);
|
||||
|
||||
impl<T: NativeElement> Packed<T> {
|
||||
/// Pack element while retaining its static type.
|
||||
pub fn new(element: T) -> Self {
|
||||
// Safety: The element is known to be of type `T`.
|
||||
Packed(element.pack(), PhantomData)
|
||||
}
|
||||
|
||||
/// Try to cast type-erased content into a statically known packed element.
|
||||
pub fn from_ref(content: &Content) -> Option<&Self> {
|
||||
if content.is::<T>() {
|
||||
// Safety:
|
||||
// - We have checked the type.
|
||||
// - Packed<T> is repr(transparent).
|
||||
return Some(unsafe { std::mem::transmute(content) });
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Try to cast type-erased content into a statically known packed element.
|
||||
pub fn from_mut(content: &mut Content) -> Option<&mut Self> {
|
||||
if content.is::<T>() {
|
||||
// Safety:
|
||||
// - We have checked the type.
|
||||
// - Packed<T> is repr(transparent).
|
||||
return Some(unsafe { std::mem::transmute(content) });
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Try to cast type-erased content into a statically known packed element.
|
||||
pub fn from_owned(content: Content) -> Result<Self, Content> {
|
||||
if content.is::<T>() {
|
||||
// Safety:
|
||||
// - We have checked the type.
|
||||
// - Packed<T> is repr(transparent).
|
||||
return Ok(unsafe { std::mem::transmute(content) });
|
||||
}
|
||||
Err(content)
|
||||
}
|
||||
|
||||
/// Pack back into content.
|
||||
pub fn pack(self) -> Content {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Extract the raw underlying element.
|
||||
pub fn unpack(self) -> T {
|
||||
// This function doesn't yet need owned self, but might in the future.
|
||||
(*self).clone()
|
||||
}
|
||||
|
||||
/// The element's span.
|
||||
pub fn span(&self) -> Span {
|
||||
self.0.span()
|
||||
}
|
||||
|
||||
/// Set the span of the element.
|
||||
pub fn spanned(self, span: Span) -> Self {
|
||||
Self(self.0.spanned(span), PhantomData)
|
||||
}
|
||||
|
||||
/// Accesses the label of the element.
|
||||
pub fn label(&self) -> Option<Label> {
|
||||
self.0.label()
|
||||
}
|
||||
|
||||
/// Accesses the location of the element.
|
||||
pub fn location(&self) -> Option<Location> {
|
||||
self.0.location()
|
||||
}
|
||||
|
||||
/// Sets the location of the element.
|
||||
pub fn set_location(&mut self, location: Location) {
|
||||
self.0.set_location(location);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NativeElement> AsRef<T> for Packed<T> {
|
||||
fn as_ref(&self) -> &T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NativeElement> AsMut<T> for Packed<T> {
|
||||
fn as_mut(&mut self) -> &mut T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NativeElement> Deref for Packed<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// Safety:
|
||||
// - Packed<T> guarantees that the content trait object wraps
|
||||
// an element of type `T`.
|
||||
// - This downcast works the same way as dyn Any's does. We can't reuse
|
||||
// that one because we don't want to pay the cost for every deref.
|
||||
let elem = &self.0.inner.elem;
|
||||
unsafe { &*(elem as *const dyn Bounds as *const T) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NativeElement> DerefMut for Packed<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
// Safety:
|
||||
// - Packed<T> guarantees that the content trait object wraps
|
||||
// an element of type `T`.
|
||||
// - We have guaranteed unique access thanks to `make_mut`.
|
||||
// - This downcast works the same way as dyn Any's does. We can't reuse
|
||||
// that one because we don't want to pay the cost for every deref.
|
||||
let elem = &mut self.0.make_mut().elem;
|
||||
unsafe { &mut *(elem as *mut dyn Bounds as *mut T) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NativeElement + Debug> Debug for Packed<T> {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines the element for sequences.
|
||||
#[elem(Repr, PartialEq)]
|
||||
struct SequenceElem {
|
||||
#[required]
|
||||
children: Vec<Prehashed<Content>>,
|
||||
}
|
||||
|
||||
// Derive is currently incompatible with `elem` macro.
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for SequenceElem {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
span: Span::detached(),
|
||||
location: Default::default(),
|
||||
label: Default::default(),
|
||||
prepared: Default::default(),
|
||||
guards: Default::default(),
|
||||
children: Default::default(),
|
||||
}
|
||||
Self { children: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -723,7 +905,11 @@ impl Repr for SequenceElem {
|
||||
eco_format!(
|
||||
"[{}]",
|
||||
crate::foundations::repr::pretty_array_like(
|
||||
&self.children.iter().map(|c| c.0.repr()).collect::<Vec<_>>(),
|
||||
&self
|
||||
.children
|
||||
.iter()
|
||||
.map(|c| c.inner.elem.repr())
|
||||
.collect::<Vec<_>>(),
|
||||
false
|
||||
)
|
||||
)
|
||||
@ -748,7 +934,7 @@ impl PartialEq for StyledElem {
|
||||
|
||||
impl Repr for StyledElem {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("styled(child: {}, ..)", self.child.0.repr())
|
||||
eco_format!("styled(child: {}, ..)", self.child.repr())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,19 @@
|
||||
use std::any::{Any, TypeId};
|
||||
use std::any::TypeId;
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::sync::Arc;
|
||||
use std::hash::Hash;
|
||||
|
||||
use ecow::EcoString;
|
||||
use once_cell::sync::Lazy;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::diag::{SourceResult, StrResult};
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, Args, Content, Dict, Func, Label, ParamInfo, Repr, Scope, Selector, StyleChain,
|
||||
cast, Args, Content, Dict, Func, ParamInfo, Repr, Scope, Selector, StyleChain,
|
||||
Styles, Value,
|
||||
};
|
||||
use crate::introspection::Location;
|
||||
use crate::syntax::Span;
|
||||
use crate::text::{Lang, Region};
|
||||
use crate::util::Static;
|
||||
|
||||
@ -35,11 +32,17 @@ impl Element {
|
||||
|
||||
/// Extract the field ID for the given field name.
|
||||
pub fn field_id(&self, name: &str) -> Option<u8> {
|
||||
if name == "label" {
|
||||
return Some(255);
|
||||
}
|
||||
(self.0.field_id)(name)
|
||||
}
|
||||
|
||||
/// Extract the field name for the given field ID.
|
||||
pub fn field_name(&self, id: u8) -> Option<&'static str> {
|
||||
if id == 255 {
|
||||
return Some("label");
|
||||
}
|
||||
(self.0.field_name)(id)
|
||||
}
|
||||
|
||||
@ -163,7 +166,20 @@ pub trait ElementFields {
|
||||
}
|
||||
|
||||
/// A Typst element that is defined by a native Rust type.
|
||||
pub trait NativeElement: Debug + Repr + Construct + Set + Send + Sync + 'static {
|
||||
pub trait NativeElement:
|
||||
Debug
|
||||
+ Clone
|
||||
+ PartialEq
|
||||
+ Hash
|
||||
+ Construct
|
||||
+ Set
|
||||
+ Capable
|
||||
+ Fields
|
||||
+ Repr
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static
|
||||
{
|
||||
/// Get the element for the native Rust element.
|
||||
fn elem() -> Element
|
||||
where
|
||||
@ -184,103 +200,31 @@ pub trait NativeElement: Debug + Repr + Construct + Set + Send + Sync + 'static
|
||||
fn data() -> &'static NativeElementData
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
/// Get the element data for the native Rust element.
|
||||
fn dyn_elem(&self) -> Element;
|
||||
/// Used to cast an element to a trait object for a trait it implements.
|
||||
///
|
||||
/// # Safety
|
||||
/// If the `vtable` function returns `Some(p)`, then `p` must be a valid pointer
|
||||
/// to a vtable of `Packed<Self>` w.r.t to the trait `C` where `capability` is
|
||||
/// `TypeId::of::<dyn C>()`.
|
||||
pub unsafe trait Capable {
|
||||
/// Get the pointer to the vtable for the given capability / trait.
|
||||
fn vtable(capability: TypeId) -> Option<*const ()>;
|
||||
}
|
||||
|
||||
/// Dynamically hash the element.
|
||||
fn dyn_hash(&self, hasher: &mut dyn Hasher);
|
||||
|
||||
/// Dynamically compare the element.
|
||||
fn dyn_eq(&self, other: &Content) -> bool;
|
||||
|
||||
/// Dynamically clone the element.
|
||||
fn dyn_clone(&self) -> Arc<dyn NativeElement>;
|
||||
|
||||
/// Get the element as a dynamic value.
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
|
||||
/// Get the element as a mutable dynamic value.
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
|
||||
/// Get the element as a dynamic value.
|
||||
fn into_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
|
||||
|
||||
/// Get the element's span.
|
||||
///
|
||||
/// May be detached if it has not been set.
|
||||
fn span(&self) -> Span;
|
||||
|
||||
/// Sets the span of this element.
|
||||
fn set_span(&mut self, span: Span);
|
||||
|
||||
/// Set the element's span.
|
||||
fn spanned(mut self, span: Span) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.set_span(span);
|
||||
self
|
||||
}
|
||||
|
||||
/// Get the element's label.
|
||||
fn label(&self) -> Option<Label>;
|
||||
|
||||
/// Sets the label of this element.
|
||||
fn set_label(&mut self, label: Label);
|
||||
|
||||
/// Set the element's label.
|
||||
fn labelled(mut self, label: Label) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.set_label(label);
|
||||
self
|
||||
}
|
||||
|
||||
/// Get the element's location.
|
||||
fn location(&self) -> Option<Location>;
|
||||
|
||||
/// Sets the location of this element.
|
||||
fn set_location(&mut self, location: Location);
|
||||
|
||||
/// Checks whether the element is guarded by the given guard.
|
||||
fn is_guarded(&self, guard: Guard) -> bool;
|
||||
|
||||
/// Pushes a guard onto the element.
|
||||
fn push_guard(&mut self, guard: Guard);
|
||||
|
||||
/// Whether the element is pristine.
|
||||
fn is_pristine(&self) -> bool;
|
||||
|
||||
/// Mark the element as having been prepared.
|
||||
fn mark_prepared(&mut self);
|
||||
|
||||
/// Whether this element needs preparations.
|
||||
fn needs_preparation(&self) -> bool;
|
||||
|
||||
/// Whether this element has been prepared.
|
||||
fn is_prepared(&self) -> bool;
|
||||
/// Defines how fields of an element are accessed.
|
||||
pub trait Fields {
|
||||
/// Whether the element has the given field set.
|
||||
fn has(&self, id: u8) -> bool;
|
||||
|
||||
/// Get the field with the given field ID.
|
||||
fn field(&self, id: u8) -> Option<Value>;
|
||||
|
||||
/// Whether the element has the given field set.
|
||||
fn has(&self, id: u8) -> bool;
|
||||
|
||||
/// Set the field with the given ID.
|
||||
fn set_field(&mut self, id: u8, value: Value) -> StrResult<()>;
|
||||
|
||||
/// Get the fields of the element.
|
||||
fn fields(&self) -> Dict;
|
||||
}
|
||||
|
||||
impl Hash for dyn NativeElement {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.dyn_hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// An element's constructor function.
|
||||
pub trait Construct {
|
||||
/// Construct an element from the arguments.
|
||||
@ -309,7 +253,7 @@ pub struct NativeElementData {
|
||||
pub keywords: &'static [&'static str],
|
||||
pub construct: fn(&mut Engine, &mut Args) -> SourceResult<Content>,
|
||||
pub set: fn(&mut Engine, &mut Args) -> SourceResult<Styles>,
|
||||
pub vtable: fn(of: TypeId) -> Option<*const ()>,
|
||||
pub vtable: fn(capability: TypeId) -> Option<*const ()>,
|
||||
pub field_id: fn(name: &str) -> Option<u8>,
|
||||
pub field_name: fn(u8) -> Option<&'static str>,
|
||||
pub local_name: Option<fn(Lang, Option<Region>) -> &'static str>,
|
||||
|
@ -12,7 +12,8 @@ use smallvec::SmallVec;
|
||||
use crate::diag::{SourceResult, Trace, Tracepoint};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, func, ty, Content, Element, Func, NativeElement, Repr, Selector, Show,
|
||||
cast, elem, func, ty, Content, Element, Func, NativeElement, Packed, Repr, Selector,
|
||||
Show,
|
||||
};
|
||||
use crate::syntax::Span;
|
||||
use crate::text::{FontFamily, FontList, TextElem};
|
||||
@ -45,7 +46,7 @@ pub fn style(
|
||||
/// content that depends on the style context it appears in.
|
||||
func: Func,
|
||||
) -> Content {
|
||||
StyleElem::new(func).spanned(span).pack()
|
||||
StyleElem::new(func).pack().spanned(span)
|
||||
}
|
||||
|
||||
/// Executes a style access.
|
||||
@ -56,7 +57,7 @@ struct StyleElem {
|
||||
func: Func,
|
||||
}
|
||||
|
||||
impl Show for StyleElem {
|
||||
impl Show for Packed<StyleElem> {
|
||||
#[typst_macros::time(name = "style", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(self.func().call(engine, [styles.to_map()])?.display())
|
||||
|
@ -10,8 +10,8 @@ use crate::engine::{Engine, Route};
|
||||
use crate::eval::Tracer;
|
||||
use crate::foundations::{
|
||||
cast, elem, func, scope, select_where, ty, Array, Content, Element, Func, IntoValue,
|
||||
Label, LocatableSelector, NativeElement, Repr, Selector, Show, Str, StyleChain,
|
||||
Value,
|
||||
Label, LocatableSelector, NativeElement, Packed, Repr, Selector, Show, Str,
|
||||
StyleChain, Value,
|
||||
};
|
||||
use crate::introspection::{Introspector, Locatable, Location, Locator, Meta};
|
||||
use crate::layout::{Frame, FrameItem, PageElem};
|
||||
@ -372,7 +372,7 @@ impl Counter {
|
||||
#[default(false)]
|
||||
both: bool,
|
||||
) -> Content {
|
||||
DisplayElem::new(self, numbering, both).spanned(span).pack()
|
||||
DisplayElem::new(self, numbering, both).pack().spanned(span)
|
||||
}
|
||||
|
||||
/// Increases the value of the counter by one.
|
||||
@ -411,7 +411,7 @@ impl Counter {
|
||||
/// return the new value (integer or array).
|
||||
update: CounterUpdate,
|
||||
) -> Content {
|
||||
UpdateElem::new(self.0, update).spanned(span).pack()
|
||||
UpdateElem::new(self.0, update).pack().spanned(span)
|
||||
}
|
||||
|
||||
/// Gets the value of the counter at the given location. Always returns an
|
||||
@ -632,7 +632,7 @@ struct DisplayElem {
|
||||
both: bool,
|
||||
}
|
||||
|
||||
impl Show for DisplayElem {
|
||||
impl Show for Packed<DisplayElem> {
|
||||
#[typst_macros::time(name = "counter.display", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(engine.delayed(|engine| {
|
||||
@ -681,13 +681,13 @@ struct UpdateElem {
|
||||
update: CounterUpdate,
|
||||
}
|
||||
|
||||
impl Show for UpdateElem {
|
||||
impl Show for Packed<UpdateElem> {
|
||||
fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> {
|
||||
Ok(Content::empty())
|
||||
}
|
||||
}
|
||||
|
||||
impl Count for UpdateElem {
|
||||
impl Count for Packed<UpdateElem> {
|
||||
fn update(&self) -> Option<CounterUpdate> {
|
||||
Some(self.update.clone())
|
||||
}
|
||||
@ -726,7 +726,7 @@ impl ManualPageCounter {
|
||||
let Some(elem) = elem.to::<UpdateElem>() else { continue };
|
||||
if *elem.key() == CounterKey::Page {
|
||||
let mut state = CounterState(smallvec![self.logical]);
|
||||
state.update(engine, elem.update().clone())?;
|
||||
state.update(engine, elem.update.clone())?;
|
||||
self.logical = state.first();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, func, Content, Func, NativeElement, Show, StyleChain};
|
||||
use crate::foundations::{
|
||||
elem, func, Content, Func, NativeElement, Packed, Show, StyleChain,
|
||||
};
|
||||
use crate::introspection::Locatable;
|
||||
use crate::syntax::Span;
|
||||
|
||||
@ -28,7 +30,7 @@ pub fn locate(
|
||||
/// content that depends on its own location in the document.
|
||||
func: Func,
|
||||
) -> Content {
|
||||
LocateElem::new(func).spanned(span).pack()
|
||||
LocateElem::new(func).pack().spanned(span)
|
||||
}
|
||||
|
||||
/// Executes a `locate` call.
|
||||
@ -39,7 +41,7 @@ struct LocateElem {
|
||||
func: Func,
|
||||
}
|
||||
|
||||
impl Show for LocateElem {
|
||||
impl Show for Packed<LocateElem> {
|
||||
#[typst_macros::time(name = "locate", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, _: StyleChain) -> SourceResult<Content> {
|
||||
Ok(engine.delayed(|engine| {
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, Behave, Behaviour, Content, Show, StyleChain, Value};
|
||||
use crate::foundations::{
|
||||
elem, Behave, Behaviour, Content, Packed, Show, StyleChain, Value,
|
||||
};
|
||||
use crate::introspection::Locatable;
|
||||
|
||||
/// Exposes a value to the query system without producing visible content.
|
||||
@ -30,13 +32,13 @@ pub struct MetadataElem {
|
||||
pub value: Value,
|
||||
}
|
||||
|
||||
impl Show for MetadataElem {
|
||||
impl Show for Packed<MetadataElem> {
|
||||
fn show(&self, _: &mut Engine, _styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(Content::empty())
|
||||
}
|
||||
}
|
||||
|
||||
impl Behave for MetadataElem {
|
||||
impl Behave for Packed<MetadataElem> {
|
||||
fn behaviour(&self) -> Behaviour {
|
||||
Behaviour::Invisible
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ use std::fmt::{self, Debug, Formatter};
|
||||
use ecow::{eco_format, EcoString};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::foundations::Packed;
|
||||
use crate::foundations::{
|
||||
category, elem, ty, Behave, Behaviour, Category, Content, Repr, Scope, Unlabellable,
|
||||
};
|
||||
@ -61,9 +62,9 @@ pub struct MetaElem {
|
||||
pub data: SmallVec<[Meta; 1]>,
|
||||
}
|
||||
|
||||
impl Unlabellable for MetaElem {}
|
||||
impl Unlabellable for Packed<MetaElem> {}
|
||||
|
||||
impl Behave for MetaElem {
|
||||
impl Behave for Packed<MetaElem> {
|
||||
fn behaviour(&self) -> Behaviour {
|
||||
Behaviour::Invisible
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ use crate::diag::SourceResult;
|
||||
use crate::engine::{Engine, Route};
|
||||
use crate::eval::Tracer;
|
||||
use crate::foundations::{
|
||||
cast, elem, func, scope, select_where, ty, Content, Func, NativeElement, Repr,
|
||||
Selector, Show, Str, StyleChain, Value,
|
||||
cast, elem, func, scope, select_where, ty, Content, Func, NativeElement, Packed,
|
||||
Repr, Selector, Show, Str, StyleChain, Value,
|
||||
};
|
||||
use crate::introspection::{Introspector, Locatable, Location, Locator};
|
||||
use crate::syntax::Span;
|
||||
@ -280,7 +280,7 @@ impl State {
|
||||
#[default]
|
||||
func: Option<Func>,
|
||||
) -> Content {
|
||||
DisplayElem::new(self, func).spanned(span).pack()
|
||||
DisplayElem::new(self, func).pack().spanned(span)
|
||||
}
|
||||
|
||||
/// Update the value of the state.
|
||||
@ -301,7 +301,7 @@ impl State {
|
||||
/// to return the new state.
|
||||
update: StateUpdate,
|
||||
) -> Content {
|
||||
UpdateElem::new(self.key, update).spanned(span).pack()
|
||||
UpdateElem::new(self.key, update).pack().spanned(span)
|
||||
}
|
||||
|
||||
/// Get the value of the state at the given location.
|
||||
@ -385,7 +385,7 @@ struct DisplayElem {
|
||||
func: Option<Func>,
|
||||
}
|
||||
|
||||
impl Show for DisplayElem {
|
||||
impl Show for Packed<DisplayElem> {
|
||||
#[typst_macros::time(name = "state.display", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, _: StyleChain) -> SourceResult<Content> {
|
||||
Ok(engine.delayed(|engine| {
|
||||
@ -411,7 +411,7 @@ struct UpdateElem {
|
||||
update: StateUpdate,
|
||||
}
|
||||
|
||||
impl Show for UpdateElem {
|
||||
impl Show for Packed<UpdateElem> {
|
||||
fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> {
|
||||
Ok(Content::empty())
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use ecow::{eco_format, EcoString};
|
||||
use crate::diag::{bail, SourceResult, StrResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, func, scope, ty, Content, Fold, Repr, Resolve, Show, StyleChain,
|
||||
cast, elem, func, scope, ty, Content, Fold, Packed, Repr, Resolve, Show, StyleChain,
|
||||
};
|
||||
use crate::layout::{Abs, Axes, Axis, Dir, Side};
|
||||
use crate::text::TextElem;
|
||||
@ -45,13 +45,13 @@ pub struct AlignElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Show for AlignElem {
|
||||
impl Show for Packed<AlignElem> {
|
||||
#[typst_macros::time(name = "align", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(self
|
||||
.body()
|
||||
.clone()
|
||||
.styled(Self::set_alignment(self.alignment(styles))))
|
||||
.styled(AlignElem::set_alignment(self.alignment(styles))))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ use std::num::NonZeroUsize;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, Behave, Behaviour, Content, StyleChain};
|
||||
use crate::foundations::{elem, Behave, Behaviour, Content, Packed, StyleChain};
|
||||
use crate::layout::{
|
||||
Abs, Axes, Dir, Fragment, Frame, Layout, Length, Point, Ratio, Regions, Rel, Size,
|
||||
};
|
||||
@ -57,7 +57,7 @@ pub struct ColumnsElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Layout for ColumnsElem {
|
||||
impl Layout for Packed<ColumnsElem> {
|
||||
#[typst_macros::time(name = "columns", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -166,7 +166,7 @@ pub struct ColbreakElem {
|
||||
pub weak: bool,
|
||||
}
|
||||
|
||||
impl Behave for ColbreakElem {
|
||||
impl Behave for Packed<ColbreakElem> {
|
||||
fn behaviour(&self) -> Behaviour {
|
||||
if self.weak(StyleChain::default()) {
|
||||
Behaviour::Weak(1)
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, AutoValue, Content, NativeElement, Resolve, Smart, StyleChain, Value,
|
||||
cast, elem, AutoValue, Content, Packed, Resolve, Smart, StyleChain, Value,
|
||||
};
|
||||
use crate::layout::{
|
||||
Abs, Axes, Corners, Em, Fr, Fragment, FrameKind, Layout, Length, Ratio, Regions, Rel,
|
||||
@ -109,7 +109,7 @@ pub struct BoxElem {
|
||||
pub body: Option<Content>,
|
||||
}
|
||||
|
||||
impl Layout for BoxElem {
|
||||
impl Layout for Packed<BoxElem> {
|
||||
#[typst_macros::time(name = "box", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -341,7 +341,7 @@ pub struct BlockElem {
|
||||
pub sticky: bool,
|
||||
}
|
||||
|
||||
impl Layout for BlockElem {
|
||||
impl Layout for Packed<BlockElem> {
|
||||
#[typst_macros::time(name = "block", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
|
@ -2,7 +2,9 @@ use comemo::Prehashed;
|
||||
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, Content, NativeElement, Resolve, Smart, StyleChain};
|
||||
use crate::foundations::{
|
||||
elem, Content, NativeElement, Packed, Resolve, Smart, StyleChain,
|
||||
};
|
||||
use crate::introspection::{Meta, MetaElem};
|
||||
use crate::layout::{
|
||||
Abs, AlignElem, Axes, BlockElem, ColbreakElem, ColumnsElem, FixedAlign, Fr, Fragment,
|
||||
@ -27,7 +29,7 @@ pub struct FlowElem {
|
||||
pub children: Vec<Prehashed<Content>>,
|
||||
}
|
||||
|
||||
impl Layout for FlowElem {
|
||||
impl Layout for Packed<FlowElem> {
|
||||
#[typst_macros::time(name = "flow", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -207,7 +209,7 @@ impl<'a> FlowLayouter<'a> {
|
||||
fn layout_spacing(
|
||||
&mut self,
|
||||
engine: &mut Engine,
|
||||
v: &VElem,
|
||||
v: &Packed<VElem>,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<()> {
|
||||
self.layout_item(
|
||||
@ -226,7 +228,7 @@ impl<'a> FlowLayouter<'a> {
|
||||
fn layout_par(
|
||||
&mut self,
|
||||
engine: &mut Engine,
|
||||
par: &ParElem,
|
||||
par: &Packed<ParElem>,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<()> {
|
||||
let align = AlignElem::alignment_in(styles).resolve(styles);
|
||||
@ -299,7 +301,7 @@ impl<'a> FlowLayouter<'a> {
|
||||
fn layout_placed(
|
||||
&mut self,
|
||||
engine: &mut Engine,
|
||||
placed: &PlaceElem,
|
||||
placed: &Packed<PlaceElem>,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<()> {
|
||||
let float = placed.float(styles);
|
||||
@ -631,7 +633,7 @@ impl FlowLayouter<'_> {
|
||||
fn try_handle_footnotes(
|
||||
&mut self,
|
||||
engine: &mut Engine,
|
||||
mut notes: Vec<FootnoteElem>,
|
||||
mut notes: Vec<Packed<FootnoteElem>>,
|
||||
) -> SourceResult<()> {
|
||||
if self.root && !self.handle_footnotes(engine, &mut notes, false, false)? {
|
||||
self.finish_region(engine, false)?;
|
||||
@ -644,7 +646,7 @@ impl FlowLayouter<'_> {
|
||||
fn handle_footnotes(
|
||||
&mut self,
|
||||
engine: &mut Engine,
|
||||
notes: &mut Vec<FootnoteElem>,
|
||||
notes: &mut Vec<Packed<FootnoteElem>>,
|
||||
movable: bool,
|
||||
force: bool,
|
||||
) -> SourceResult<bool> {
|
||||
@ -735,7 +737,7 @@ impl FlowLayouter<'_> {
|
||||
}
|
||||
|
||||
/// Finds all footnotes in the frame.
|
||||
fn find_footnotes(notes: &mut Vec<FootnoteElem>, frame: &Frame) {
|
||||
fn find_footnotes(notes: &mut Vec<Packed<FootnoteElem>>, frame: &Frame) {
|
||||
for (_, item) in frame.items() {
|
||||
match item {
|
||||
FrameItem::Group(group) => find_footnotes(notes, &group.frame),
|
||||
|
@ -9,8 +9,8 @@ use smallvec::{smallvec, SmallVec};
|
||||
use crate::diag::{SourceResult, StrResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, scope, Array, Content, Fold, NativeElement, Show, Smart, StyleChain,
|
||||
Value,
|
||||
cast, elem, scope, Array, Content, Fold, NativeElement, Packed, Show, Smart,
|
||||
StyleChain, Value,
|
||||
};
|
||||
use crate::layout::{
|
||||
Abs, AlignElem, Alignment, Axes, Fragment, Layout, Length, Regions, Rel, Sides,
|
||||
@ -222,7 +222,7 @@ impl GridElem {
|
||||
type GridCell;
|
||||
}
|
||||
|
||||
impl Layout for GridElem {
|
||||
impl Layout for Packed<GridElem> {
|
||||
#[typst_macros::time(name = "grid", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -346,7 +346,7 @@ impl ResolvableCell for GridCell {
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for GridCell {
|
||||
impl Show for Packed<GridCell> {
|
||||
fn show(&self, _engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
show_grid_cell(self.body().clone(), self.inset(styles), self.align(styles))
|
||||
}
|
||||
@ -354,10 +354,10 @@ impl Show for GridCell {
|
||||
|
||||
impl From<Content> for GridCell {
|
||||
fn from(value: Content) -> Self {
|
||||
value
|
||||
.to::<Self>()
|
||||
.cloned()
|
||||
.unwrap_or_else(|| Self::new(value.clone()))
|
||||
match value.to_packed::<Self>() {
|
||||
Ok(packed) => packed.unpack(),
|
||||
Err(v) => Self::new(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ use smallvec::smallvec;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, Content, Show, StyleChain};
|
||||
use crate::foundations::{elem, Content, Packed, Show, StyleChain};
|
||||
use crate::introspection::{Meta, MetaElem};
|
||||
|
||||
/// Hides content without affecting layout.
|
||||
@ -24,7 +24,7 @@ pub struct HideElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Show for HideElem {
|
||||
impl Show for Packed<HideElem> {
|
||||
#[typst_macros::time(name = "hide", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> {
|
||||
Ok(self.body().clone().styled(MetaElem::set_data(smallvec![Meta::Hide])))
|
||||
|
@ -13,7 +13,7 @@ use self::shaping::{
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::{Engine, Route};
|
||||
use crate::eval::Tracer;
|
||||
use crate::foundations::{Content, Resolve, Smart, StyleChain};
|
||||
use crate::foundations::{Content, Packed, Resolve, Smart, StyleChain};
|
||||
use crate::introspection::{Introspector, Locator, MetaElem};
|
||||
use crate::layout::{
|
||||
Abs, AlignElem, Axes, BoxElem, Dir, Em, FixedAlign, Fr, Fragment, Frame, HElem,
|
||||
@ -189,9 +189,9 @@ enum Segment<'a> {
|
||||
/// Horizontal spacing between other segments.
|
||||
Spacing(Spacing),
|
||||
/// A mathematical equation.
|
||||
Equation(&'a EquationElem, Vec<MathParItem>),
|
||||
Equation(&'a Packed<EquationElem>, Vec<MathParItem>),
|
||||
/// A box with arbitrary content.
|
||||
Box(&'a BoxElem, bool),
|
||||
Box(&'a Packed<BoxElem>, bool),
|
||||
/// Metadata.
|
||||
Meta,
|
||||
}
|
||||
@ -221,7 +221,7 @@ enum Item<'a> {
|
||||
/// Absolute spacing between other items.
|
||||
Absolute(Abs),
|
||||
/// Fractional spacing between other items.
|
||||
Fractional(Fr, Option<(&'a BoxElem, StyleChain<'a>)>),
|
||||
Fractional(Fr, Option<(&'a Packed<BoxElem>, StyleChain<'a>)>),
|
||||
/// Layouted inline-level content.
|
||||
Frame(Frame),
|
||||
/// Metadata.
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{dict, elem, func, Content, Func, NativeElement, StyleChain};
|
||||
use crate::foundations::{
|
||||
dict, elem, func, Content, Func, NativeElement, Packed, StyleChain,
|
||||
};
|
||||
use crate::layout::{Fragment, Layout, Regions, Size};
|
||||
use crate::syntax::Span;
|
||||
|
||||
@ -57,7 +59,7 @@ pub fn layout(
|
||||
/// content that depends on the size of the container it is inside of.
|
||||
func: Func,
|
||||
) -> Content {
|
||||
LayoutElem::new(func).spanned(span).pack()
|
||||
LayoutElem::new(func).pack().spanned(span)
|
||||
}
|
||||
|
||||
/// Executes a `layout` call.
|
||||
@ -68,7 +70,7 @@ struct LayoutElem {
|
||||
func: Func,
|
||||
}
|
||||
|
||||
impl Layout for LayoutElem {
|
||||
impl Layout for Packed<LayoutElem> {
|
||||
#[typst_macros::time(name = "layout", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, Content, Resolve, StyleChain};
|
||||
use crate::foundations::{elem, Content, Packed, Resolve, StyleChain};
|
||||
use crate::layout::{Abs, Fragment, Layout, Length, Point, Regions, Rel, Sides, Size};
|
||||
|
||||
/// Adds spacing around content.
|
||||
@ -58,7 +58,7 @@ pub struct PadElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Layout for PadElem {
|
||||
impl Layout for Packed<PadElem> {
|
||||
#[typst_macros::time(name = "pad", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
|
@ -6,8 +6,8 @@ use std::str::FromStr;
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, AutoValue, Cast, Content, Dict, Fold, Func, NativeElement, Resolve,
|
||||
Smart, StyleChain, Value,
|
||||
cast, elem, AutoValue, Cast, Content, Dict, Fold, Func, NativeElement, Packed,
|
||||
Resolve, Smart, StyleChain, Value,
|
||||
};
|
||||
use crate::introspection::{Counter, CounterKey, ManualPageCounter, Meta};
|
||||
use crate::layout::{
|
||||
@ -333,7 +333,7 @@ pub struct PageElem {
|
||||
pub clear_to: Option<Parity>,
|
||||
}
|
||||
|
||||
impl PageElem {
|
||||
impl Packed<PageElem> {
|
||||
/// A document can consist of multiple `PageElem`s, one per run of pages
|
||||
/// with equal properties (not one per actual output page!). The `number` is
|
||||
/// the physical page number of the first page of this run. It is mutated
|
||||
@ -385,9 +385,9 @@ impl PageElem {
|
||||
let columns = self.columns(styles);
|
||||
if columns.get() > 1 {
|
||||
child = ColumnsElem::new(child)
|
||||
.spanned(self.span())
|
||||
.with_count(columns)
|
||||
.pack();
|
||||
.pack()
|
||||
.spanned(self.span());
|
||||
}
|
||||
|
||||
let area = size - margin.sum_by_axis();
|
||||
|
@ -1,8 +1,6 @@
|
||||
use crate::diag::{bail, At, Hint, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
elem, Behave, Behaviour, Content, NativeElement, Smart, StyleChain,
|
||||
};
|
||||
use crate::foundations::{elem, Behave, Behaviour, Content, Packed, Smart, StyleChain};
|
||||
use crate::layout::{
|
||||
Alignment, Axes, Em, Fragment, Layout, Length, Regions, Rel, VAlignment,
|
||||
};
|
||||
@ -88,7 +86,7 @@ pub struct PlaceElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Layout for PlaceElem {
|
||||
impl Layout for Packed<PlaceElem> {
|
||||
#[typst_macros::time(name = "place", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -125,7 +123,7 @@ impl Layout for PlaceElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Behave for PlaceElem {
|
||||
impl Behave for Packed<PlaceElem> {
|
||||
fn behaviour(&self) -> Behaviour {
|
||||
Behaviour::Ignorant
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, Content, NativeElement, Resolve, StyleChain};
|
||||
use crate::foundations::{elem, Content, Packed, Resolve, StyleChain};
|
||||
use crate::layout::{
|
||||
Abs, AlignElem, Axes, Fragment, Frame, Layout, Point, Regions, Size,
|
||||
};
|
||||
@ -34,7 +34,7 @@ pub struct RepeatElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Layout for RepeatElem {
|
||||
impl Layout for Packed<RepeatElem> {
|
||||
#[typst_macros::time(name = "repeat", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
|
@ -1,6 +1,8 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::foundations::{cast, elem, Behave, Behaviour, Content, Resolve, StyleChain};
|
||||
use crate::foundations::{
|
||||
cast, elem, Behave, Behaviour, Content, Packed, Resolve, StyleChain,
|
||||
};
|
||||
use crate::layout::{Abs, Em, Fr, Length, Ratio, Rel};
|
||||
use crate::util::Numeric;
|
||||
|
||||
@ -62,7 +64,7 @@ impl HElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Behave for HElem {
|
||||
impl Behave for Packed<HElem> {
|
||||
fn behaviour(&self) -> Behaviour {
|
||||
if self.amount().is_fractional() {
|
||||
Behaviour::Destructive
|
||||
@ -78,7 +80,7 @@ impl Behave for HElem {
|
||||
prev: &(Cow<Content>, Behaviour, StyleChain),
|
||||
styles: StyleChain,
|
||||
) -> bool {
|
||||
let Some(other) = prev.0.to::<Self>() else { return false };
|
||||
let Some(other) = prev.0.to::<HElem>() else { return false };
|
||||
match (self.amount(), other.amount()) {
|
||||
(Spacing::Fr(this), Spacing::Fr(other)) => this > other,
|
||||
(Spacing::Rel(this), Spacing::Rel(other)) => {
|
||||
@ -164,7 +166,7 @@ impl VElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Behave for VElem {
|
||||
impl Behave for Packed<VElem> {
|
||||
fn behaviour(&self) -> Behaviour {
|
||||
if self.amount().is_fractional() {
|
||||
Behaviour::Destructive
|
||||
@ -180,7 +182,7 @@ impl Behave for VElem {
|
||||
prev: &(Cow<Content>, Behaviour, StyleChain),
|
||||
styles: StyleChain,
|
||||
) -> bool {
|
||||
let Some(other) = prev.0.to::<Self>() else { return false };
|
||||
let Some(other) = prev.0.to::<VElem>() else { return false };
|
||||
match (self.amount(), other.amount()) {
|
||||
(Spacing::Fr(this), Spacing::Fr(other)) => this > other,
|
||||
(Spacing::Rel(this), Spacing::Rel(other)) => {
|
||||
@ -193,7 +195,7 @@ impl Behave for VElem {
|
||||
|
||||
cast! {
|
||||
VElem,
|
||||
v: Content => v.to::<Self>().cloned().ok_or("expected `v` element")?,
|
||||
v: Content => v.to_packed::<Self>().map_err(|_| "expected `v` element")?.unpack(),
|
||||
}
|
||||
|
||||
/// Kinds of spacing.
|
||||
|
@ -2,7 +2,7 @@ use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{cast, elem, Content, Resolve, StyleChain};
|
||||
use crate::foundations::{cast, elem, Content, Packed, Resolve, StyleChain};
|
||||
use crate::layout::{
|
||||
Abs, AlignElem, Axes, Axis, Dir, FixedAlign, Fr, Fragment, Frame, Layout, Point,
|
||||
Regions, Size, Spacing,
|
||||
@ -51,7 +51,7 @@ pub struct StackElem {
|
||||
pub children: Vec<StackChild>,
|
||||
}
|
||||
|
||||
impl Layout for StackElem {
|
||||
impl Layout for Packed<StackElem> {
|
||||
#[typst_macros::time(name = "stack", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, Content, Resolve, StyleChain};
|
||||
use crate::foundations::{elem, Content, Packed, Resolve, StyleChain};
|
||||
use crate::layout::{
|
||||
Abs, Alignment, Angle, Axes, FixedAlign, Fragment, Frame, HAlignment, Layout, Length,
|
||||
Point, Ratio, Regions, Rel, Size, VAlignment,
|
||||
@ -37,7 +37,7 @@ pub struct MoveElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Layout for MoveElem {
|
||||
impl Layout for Packed<MoveElem> {
|
||||
#[typst_macros::time(name = "move", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -115,7 +115,7 @@ pub struct RotateElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Layout for RotateElem {
|
||||
impl Layout for Packed<RotateElem> {
|
||||
#[typst_macros::time(name = "rotate", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -203,7 +203,7 @@ pub struct ScaleElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Layout for ScaleElem {
|
||||
impl Layout for Packed<ScaleElem> {
|
||||
#[typst_macros::time(name = "scale", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::foundations::{cast, elem, Content, NativeElement, Resolve, Smart, Value};
|
||||
use crate::foundations::{cast, elem, Content, Packed, Resolve, Smart, Value};
|
||||
use crate::layout::{Em, Frame, Length, Point, Rel, Size};
|
||||
use crate::math::{
|
||||
FrameFragment, GlyphFragment, LayoutMath, MathContext, MathFragment, Scaled,
|
||||
@ -62,7 +62,7 @@ pub struct AccentElem {
|
||||
pub size: Smart<Rel<Length>>,
|
||||
}
|
||||
|
||||
impl LayoutMath for AccentElem {
|
||||
impl LayoutMath for Packed<AccentElem> {
|
||||
#[typst_macros::time(name = "math.accent", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
ctx.style(ctx.style.with_cramped(true));
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::foundations::elem;
|
||||
use crate::foundations::{elem, Packed};
|
||||
use crate::layout::Abs;
|
||||
use crate::math::{LayoutMath, MathContext, MathFragment, MathRow};
|
||||
|
||||
@ -7,7 +7,7 @@ use crate::math::{LayoutMath, MathContext, MathFragment, MathRow};
|
||||
#[elem(title = "Alignment Point", LayoutMath)]
|
||||
pub struct AlignPointElem {}
|
||||
|
||||
impl LayoutMath for AlignPointElem {
|
||||
impl LayoutMath for Packed<AlignPointElem> {
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
ctx.push(MathFragment::Align);
|
||||
Ok(())
|
||||
|
@ -1,7 +1,7 @@
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::foundations::{elem, Content, StyleChain};
|
||||
use crate::foundations::{elem, Content, Packed, StyleChain};
|
||||
use crate::layout::{Abs, Frame, Point, Size};
|
||||
use crate::math::{
|
||||
FrameFragment, LayoutMath, MathContext, MathFragment, MathSize, Scaled,
|
||||
@ -48,7 +48,7 @@ pub struct AttachElem {
|
||||
pub br: Option<Content>,
|
||||
}
|
||||
|
||||
impl LayoutMath for AttachElem {
|
||||
impl LayoutMath for Packed<AttachElem> {
|
||||
#[typst_macros::time(name = "math.attach", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
type GetAttachment = fn(&AttachElem, styles: StyleChain) -> Option<Content>;
|
||||
@ -61,15 +61,15 @@ impl LayoutMath for AttachElem {
|
||||
let base = ctx.layout_fragment(self.base())?;
|
||||
|
||||
ctx.style(ctx.style.for_superscript());
|
||||
let tl = layout_attachment(ctx, Self::tl)?;
|
||||
let tr = layout_attachment(ctx, Self::tr)?;
|
||||
let t = layout_attachment(ctx, Self::t)?;
|
||||
let tl = layout_attachment(ctx, AttachElem::tl)?;
|
||||
let tr = layout_attachment(ctx, AttachElem::tr)?;
|
||||
let t = layout_attachment(ctx, AttachElem::t)?;
|
||||
ctx.unstyle();
|
||||
|
||||
ctx.style(ctx.style.for_subscript());
|
||||
let bl = layout_attachment(ctx, Self::bl)?;
|
||||
let br = layout_attachment(ctx, Self::br)?;
|
||||
let b = layout_attachment(ctx, Self::b)?;
|
||||
let bl = layout_attachment(ctx, AttachElem::bl)?;
|
||||
let br = layout_attachment(ctx, AttachElem::br)?;
|
||||
let b = layout_attachment(ctx, AttachElem::b)?;
|
||||
ctx.unstyle();
|
||||
|
||||
let limits = base.limits().active(ctx);
|
||||
@ -96,7 +96,7 @@ pub struct PrimesElem {
|
||||
pub count: usize,
|
||||
}
|
||||
|
||||
impl LayoutMath for PrimesElem {
|
||||
impl LayoutMath for Packed<PrimesElem> {
|
||||
#[typst_macros::time(name = "math.primes", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
match *self.count() {
|
||||
@ -142,7 +142,7 @@ pub struct ScriptsElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl LayoutMath for ScriptsElem {
|
||||
impl LayoutMath for Packed<ScriptsElem> {
|
||||
#[typst_macros::time(name = "math.scripts", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
let mut fragment = ctx.layout_fragment(self.body())?;
|
||||
@ -171,7 +171,7 @@ pub struct LimitsElem {
|
||||
pub inline: bool,
|
||||
}
|
||||
|
||||
impl LayoutMath for LimitsElem {
|
||||
impl LayoutMath for Packed<LimitsElem> {
|
||||
#[typst_macros::time(name = "math.limits", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
let mut fragment = ctx.layout_fragment(self.body())?;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use crate::diag::{At, SourceResult};
|
||||
use crate::foundations::{cast, elem, Content, Func, NativeElement, Resolve, Smart};
|
||||
use crate::foundations::{cast, elem, Content, Func, Packed, Resolve, Smart};
|
||||
use crate::layout::{
|
||||
Abs, Angle, Frame, FrameItem, Length, Point, Ratio, Rel, Size, Transform,
|
||||
};
|
||||
@ -105,7 +105,7 @@ pub struct CancelElem {
|
||||
pub stroke: Stroke,
|
||||
}
|
||||
|
||||
impl LayoutMath for CancelElem {
|
||||
impl LayoutMath for Packed<CancelElem> {
|
||||
#[typst_macros::time(name = "math.cancel", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
let body = ctx.layout_fragment(self.body())?;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::foundations::{elem, Content};
|
||||
use crate::foundations::{elem, Content, Packed};
|
||||
use crate::math::{LayoutMath, MathContext};
|
||||
|
||||
/// Forced use of a certain math class.
|
||||
@ -29,7 +29,7 @@ pub struct ClassElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl LayoutMath for ClassElem {
|
||||
impl LayoutMath for Packed<ClassElem> {
|
||||
#[typst_macros::time(name = "math.class", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
ctx.style(ctx.style.with_class(*self.class()));
|
||||
|
@ -12,7 +12,7 @@ use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{Content, NativeElement, Smart, StyleChain, Styles};
|
||||
use crate::foundations::{Content, Packed, Smart, StyleChain, Styles};
|
||||
use crate::layout::{Abs, Axes, BoxElem, Em, Frame, Layout, Regions, Size};
|
||||
use crate::math::{
|
||||
FrameFragment, GlyphFragment, LayoutMath, MathFragment, MathRow, MathSize, MathStyle,
|
||||
@ -173,7 +173,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
|
||||
Ok(self.layout_fragment(elem)?.into_frame())
|
||||
}
|
||||
|
||||
pub fn layout_box(&mut self, boxed: &BoxElem) -> SourceResult<Frame> {
|
||||
pub fn layout_box(&mut self, boxed: &Packed<BoxElem>) -> SourceResult<Frame> {
|
||||
Ok(boxed
|
||||
.layout(self.engine, self.outer.chain(&self.local), self.regions)?
|
||||
.into_frame())
|
||||
@ -185,7 +185,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
|
||||
.into_frame())
|
||||
}
|
||||
|
||||
pub fn layout_text(&mut self, elem: &TextElem) -> SourceResult<MathFragment> {
|
||||
pub fn layout_text(&mut self, elem: &Packed<TextElem>) -> SourceResult<MathFragment> {
|
||||
let text = elem.text();
|
||||
let span = elem.span();
|
||||
let mut chars = text.chars();
|
||||
@ -276,7 +276,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
|
||||
// it will overflow. So emulate an `hbox` instead and allow the paragraph
|
||||
// to extend as far as needed.
|
||||
let span = elem.span();
|
||||
let frame = ParElem::new(vec![Prehashed::new(elem)])
|
||||
let frame = Packed::new(ParElem::new(vec![Prehashed::new(elem)]))
|
||||
.spanned(span)
|
||||
.layout(
|
||||
self.engine,
|
||||
|
@ -3,8 +3,8 @@ use std::num::NonZeroUsize;
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
elem, Content, Finalize, Guard, NativeElement, Resolve, Show, Smart, StyleChain,
|
||||
Synthesize,
|
||||
elem, Content, Finalize, Guard, NativeElement, Packed, Resolve, Show, Smart,
|
||||
StyleChain, Synthesize,
|
||||
};
|
||||
use crate::introspection::{Count, Counter, CounterUpdate, Locatable};
|
||||
use crate::layout::{
|
||||
@ -89,41 +89,41 @@ pub struct EquationElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Synthesize for EquationElem {
|
||||
impl Synthesize for Packed<EquationElem> {
|
||||
fn synthesize(
|
||||
&mut self,
|
||||
engine: &mut Engine,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<()> {
|
||||
// Resolve the supplement.
|
||||
let supplement = match self.supplement(styles) {
|
||||
let supplement = match self.as_ref().supplement(styles) {
|
||||
Smart::Auto => TextElem::packed(Self::local_name_in(styles)),
|
||||
Smart::Custom(None) => Content::empty(),
|
||||
Smart::Custom(Some(supplement)) => {
|
||||
supplement.resolve(engine, [self.clone()])?
|
||||
supplement.resolve(engine, [self.clone().pack()])?
|
||||
}
|
||||
};
|
||||
|
||||
self.push_block(self.block(styles));
|
||||
self.push_numbering(self.numbering(styles));
|
||||
self.push_supplement(Smart::Custom(Some(Supplement::Content(supplement))));
|
||||
let elem = self.as_mut();
|
||||
elem.push_block(elem.block(styles));
|
||||
elem.push_numbering(elem.numbering(styles));
|
||||
elem.push_supplement(Smart::Custom(Some(Supplement::Content(supplement))));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for EquationElem {
|
||||
impl Show for Packed<EquationElem> {
|
||||
#[typst_macros::time(name = "math.equation", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
let mut realized = self.clone().pack().guarded(Guard::Base(Self::elem()));
|
||||
let mut realized = self.clone().pack().guarded(Guard::Base(EquationElem::elem()));
|
||||
if self.block(styles) {
|
||||
realized = AlignElem::new(realized).spanned(self.span()).pack();
|
||||
realized = AlignElem::new(realized).pack().spanned(self.span());
|
||||
}
|
||||
Ok(realized)
|
||||
}
|
||||
}
|
||||
|
||||
impl Finalize for EquationElem {
|
||||
impl Finalize for Packed<EquationElem> {
|
||||
fn finalize(&self, realized: Content, style: StyleChain) -> Content {
|
||||
let mut realized = realized;
|
||||
if self.block(style) {
|
||||
@ -154,7 +154,7 @@ impl MathParItem {
|
||||
}
|
||||
}
|
||||
|
||||
impl EquationElem {
|
||||
impl Packed<EquationElem> {
|
||||
pub fn layout_inline(
|
||||
&self,
|
||||
engine: &mut Engine<'_>,
|
||||
@ -197,7 +197,7 @@ impl EquationElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for EquationElem {
|
||||
impl Layout for Packed<EquationElem> {
|
||||
#[typst_macros::time(name = "math.equation", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -215,9 +215,9 @@ impl Layout for EquationElem {
|
||||
let mut ctx = MathContext::new(engine, styles, regions, &font, true);
|
||||
let mut frame = ctx.layout_frame(self)?;
|
||||
|
||||
if let Some(numbering) = self.numbering(styles) {
|
||||
if let Some(numbering) = (**self).numbering(styles) {
|
||||
let pod = Regions::one(regions.base(), Axes::splat(false));
|
||||
let counter = Counter::of(Self::elem())
|
||||
let counter = Counter::of(EquationElem::elem())
|
||||
.display(self.span(), Some(numbering), false)
|
||||
.layout(engine, styles, pod)?
|
||||
.into_frame();
|
||||
@ -258,15 +258,14 @@ impl Layout for EquationElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Count for EquationElem {
|
||||
impl Count for Packed<EquationElem> {
|
||||
fn update(&self) -> Option<CounterUpdate> {
|
||||
(self.block(StyleChain::default())
|
||||
&& self.numbering(StyleChain::default()).is_some())
|
||||
.then(|| CounterUpdate::Step(NonZeroUsize::ONE))
|
||||
(self.block(StyleChain::default()) && self.numbering().is_some())
|
||||
.then(|| CounterUpdate::Step(NonZeroUsize::ONE))
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalName for EquationElem {
|
||||
impl LocalName for Packed<EquationElem> {
|
||||
fn local_name(lang: Lang, region: Option<Region>) -> &'static str {
|
||||
match lang {
|
||||
Lang::ALBANIAN => "Ekuacion",
|
||||
@ -304,35 +303,35 @@ impl LocalName for EquationElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Refable for EquationElem {
|
||||
impl Refable for Packed<EquationElem> {
|
||||
fn supplement(&self) -> Content {
|
||||
// After synthesis, this should always be custom content.
|
||||
match self.supplement(StyleChain::default()) {
|
||||
match (**self).supplement(StyleChain::default()) {
|
||||
Smart::Custom(Some(Supplement::Content(content))) => content,
|
||||
_ => Content::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
fn counter(&self) -> Counter {
|
||||
Counter::of(Self::elem())
|
||||
Counter::of(EquationElem::elem())
|
||||
}
|
||||
|
||||
fn numbering(&self) -> Option<Numbering> {
|
||||
self.numbering(StyleChain::default())
|
||||
(**self).numbering(StyleChain::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Outlinable for EquationElem {
|
||||
impl Outlinable for Packed<EquationElem> {
|
||||
fn outline(&self, engine: &mut Engine) -> SourceResult<Option<Content>> {
|
||||
if !self.block(StyleChain::default()) {
|
||||
return Ok(None);
|
||||
}
|
||||
let Some(numbering) = self.numbering(StyleChain::default()) else {
|
||||
let Some(numbering) = self.numbering() else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
// After synthesis, this should always be custom content.
|
||||
let mut supplement = match self.supplement(StyleChain::default()) {
|
||||
let mut supplement = match (**self).supplement(StyleChain::default()) {
|
||||
Smart::Custom(Some(Supplement::Content(content))) => content,
|
||||
_ => Content::empty(),
|
||||
};
|
||||
@ -350,7 +349,7 @@ impl Outlinable for EquationElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutMath for EquationElem {
|
||||
impl LayoutMath for Packed<EquationElem> {
|
||||
#[typst_macros::time(name = "math.equation", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
self.body().layout_math(ctx)
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::foundations::{elem, Content, NativeElement, Value};
|
||||
use crate::foundations::{elem, Content, Packed, Value};
|
||||
use crate::layout::{Em, Frame, FrameItem, Point, Size};
|
||||
use crate::math::{
|
||||
FrameFragment, GlyphFragment, LayoutMath, MathContext, MathSize, Scaled,
|
||||
@ -35,7 +35,7 @@ pub struct FracElem {
|
||||
pub denom: Content,
|
||||
}
|
||||
|
||||
impl LayoutMath for FracElem {
|
||||
impl LayoutMath for Packed<FracElem> {
|
||||
#[typst_macros::time(name = "math.frac", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout(ctx, self.num(), std::slice::from_ref(self.denom()), false, self.span())
|
||||
@ -69,7 +69,7 @@ pub struct BinomElem {
|
||||
pub lower: Vec<Content>,
|
||||
}
|
||||
|
||||
impl LayoutMath for BinomElem {
|
||||
impl LayoutMath for Packed<BinomElem> {
|
||||
#[typst_macros::time(name = "math.binom", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout(ctx, self.upper(), self.lower(), true, self.span())
|
||||
|
@ -1,7 +1,7 @@
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::foundations::{elem, func, Content, NativeElement, Resolve, Smart};
|
||||
use crate::foundations::{elem, func, Content, NativeElement, Packed, Resolve, Smart};
|
||||
use crate::layout::{Abs, Em, Length, Rel};
|
||||
use crate::math::{
|
||||
GlyphFragment, LayoutMath, MathContext, MathFragment, Scaled, SpacingFragment,
|
||||
@ -35,7 +35,7 @@ pub struct LrElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl LayoutMath for LrElem {
|
||||
impl LayoutMath for Packed<LrElem> {
|
||||
#[typst_macros::time(name = "math.lr", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
let mut body = self.body();
|
||||
@ -110,7 +110,7 @@ pub struct MidElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl LayoutMath for MidElem {
|
||||
impl LayoutMath for Packed<MidElem> {
|
||||
#[typst_macros::time(name = "math.mid", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
let mut fragments = ctx.layout_fragments(self.body())?;
|
||||
@ -255,11 +255,10 @@ fn delimited(
|
||||
TextElem::packed(left),
|
||||
body,
|
||||
TextElem::packed(right),
|
||||
]))
|
||||
.spanned(span);
|
||||
]));
|
||||
// Push size only if size is provided
|
||||
if let Some(size) = size {
|
||||
elem.push_size(size);
|
||||
}
|
||||
elem.pack()
|
||||
elem.pack().spanned(span)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use crate::diag::{bail, At, SourceResult, StrResult};
|
||||
use crate::foundations::{
|
||||
cast, dict, elem, Array, Cast, Content, Dict, Fold, NativeElement, Resolve, Smart,
|
||||
cast, dict, elem, Array, Cast, Content, Dict, Fold, Packed, Resolve, Smart,
|
||||
StyleChain, Value,
|
||||
};
|
||||
use crate::layout::{
|
||||
@ -57,7 +57,7 @@ pub struct VecElem {
|
||||
pub children: Vec<Content>,
|
||||
}
|
||||
|
||||
impl LayoutMath for VecElem {
|
||||
impl LayoutMath for Packed<VecElem> {
|
||||
#[typst_macros::time(name = "math.vec", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
let delim = self.delim(ctx.styles());
|
||||
@ -210,11 +210,9 @@ pub struct MatElem {
|
||||
pub rows: Vec<Vec<Content>>,
|
||||
}
|
||||
|
||||
impl LayoutMath for MatElem {
|
||||
impl LayoutMath for Packed<MatElem> {
|
||||
#[typst_macros::time(name = "math.mat", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
// validate inputs
|
||||
|
||||
let augment = self.augment(ctx.styles());
|
||||
let rows = self.rows();
|
||||
|
||||
@ -311,7 +309,7 @@ pub struct CasesElem {
|
||||
pub children: Vec<Content>,
|
||||
}
|
||||
|
||||
impl LayoutMath for CasesElem {
|
||||
impl LayoutMath for Packed<CasesElem> {
|
||||
#[typst_macros::time(name = "math.cases", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
let delim = self.delim(ctx.styles());
|
||||
|
@ -2,7 +2,7 @@ use ecow::EcoString;
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::foundations::{elem, Content, NativeElement, Scope};
|
||||
use crate::foundations::{elem, Content, NativeElement, Packed, Scope};
|
||||
use crate::layout::HElem;
|
||||
use crate::math::{FrameFragment, LayoutMath, Limits, MathContext, MathStyleElem, THIN};
|
||||
use crate::text::TextElem;
|
||||
@ -33,7 +33,7 @@ pub struct OpElem {
|
||||
pub limits: bool,
|
||||
}
|
||||
|
||||
impl LayoutMath for OpElem {
|
||||
impl LayoutMath for Packed<OpElem> {
|
||||
#[typst_macros::time(name = "math.op", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
let fragment = ctx.layout_fragment(self.text())?;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::foundations::{elem, func, Content, NativeElement};
|
||||
use crate::foundations::{elem, func, Content, NativeElement, Packed};
|
||||
use crate::layout::{Abs, Frame, FrameItem, Point, Size};
|
||||
use crate::math::{
|
||||
FrameFragment, GlyphFragment, LayoutMath, MathContext, MathSize, Scaled,
|
||||
@ -20,7 +20,7 @@ pub fn sqrt(
|
||||
/// The expression to take the square root of.
|
||||
radicand: Content,
|
||||
) -> Content {
|
||||
RootElem::new(radicand).spanned(span).pack()
|
||||
RootElem::new(radicand).pack().spanned(span)
|
||||
}
|
||||
|
||||
/// A general root.
|
||||
@ -39,7 +39,7 @@ pub struct RootElem {
|
||||
pub radicand: Content,
|
||||
}
|
||||
|
||||
impl LayoutMath for RootElem {
|
||||
impl LayoutMath for Packed<RootElem> {
|
||||
#[typst_macros::time(name = "math.root", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout(ctx, self.index(ctx.styles()).as_ref(), self.radicand(), self.span())
|
||||
|
@ -1,7 +1,9 @@
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::foundations::{elem, func, Cast, Content, NativeElement, Smart, StyleChain};
|
||||
use crate::foundations::{
|
||||
elem, func, Cast, Content, NativeElement, Packed, Smart, StyleChain,
|
||||
};
|
||||
use crate::math::{LayoutMath, MathContext};
|
||||
use crate::syntax::Span;
|
||||
|
||||
@ -17,7 +19,7 @@ pub fn bold(
|
||||
/// The content to style.
|
||||
body: Content,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body).spanned(span).with_bold(Some(true)).pack()
|
||||
MathStyleElem::new(body).with_bold(Some(true)).pack().spanned(span)
|
||||
}
|
||||
|
||||
/// Upright (non-italic) font style in math.
|
||||
@ -32,7 +34,7 @@ pub fn upright(
|
||||
/// The content to style.
|
||||
body: Content,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body).spanned(span).with_italic(Some(false)).pack()
|
||||
MathStyleElem::new(body).with_italic(Some(false)).pack().spanned(span)
|
||||
}
|
||||
|
||||
/// Italic font style in math.
|
||||
@ -45,7 +47,7 @@ pub fn italic(
|
||||
/// The content to style.
|
||||
body: Content,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body).spanned(span).with_italic(Some(true)).pack()
|
||||
MathStyleElem::new(body).with_italic(Some(true)).pack().spanned(span)
|
||||
}
|
||||
/// Serif (roman) font style in math.
|
||||
///
|
||||
@ -58,9 +60,9 @@ pub fn serif(
|
||||
body: Content,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body)
|
||||
.spanned(span)
|
||||
.with_variant(Some(MathVariant::Serif))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
}
|
||||
|
||||
/// Sans-serif font style in math.
|
||||
@ -76,9 +78,9 @@ pub fn sans(
|
||||
body: Content,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body)
|
||||
.spanned(span)
|
||||
.with_variant(Some(MathVariant::Sans))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
}
|
||||
|
||||
/// Calligraphic font style in math.
|
||||
@ -94,9 +96,9 @@ pub fn cal(
|
||||
body: Content,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body)
|
||||
.spanned(span)
|
||||
.with_variant(Some(MathVariant::Cal))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
}
|
||||
|
||||
/// Fraktur font style in math.
|
||||
@ -112,9 +114,9 @@ pub fn frak(
|
||||
body: Content,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body)
|
||||
.spanned(span)
|
||||
.with_variant(Some(MathVariant::Frak))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
}
|
||||
|
||||
/// Monospace font style in math.
|
||||
@ -130,9 +132,9 @@ pub fn mono(
|
||||
body: Content,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body)
|
||||
.spanned(span)
|
||||
.with_variant(Some(MathVariant::Mono))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
}
|
||||
|
||||
/// Blackboard bold (double-struck) font style in math.
|
||||
@ -153,9 +155,9 @@ pub fn bb(
|
||||
body: Content,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body)
|
||||
.spanned(span)
|
||||
.with_variant(Some(MathVariant::Bb))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
}
|
||||
|
||||
/// Forced display style in math.
|
||||
@ -178,10 +180,10 @@ pub fn display(
|
||||
cramped: bool,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body)
|
||||
.spanned(span)
|
||||
.with_size(Some(MathSize::Display))
|
||||
.with_cramped(Some(cramped))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
}
|
||||
|
||||
/// Forced inline (text) style in math.
|
||||
@ -205,10 +207,10 @@ pub fn inline(
|
||||
cramped: bool,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body)
|
||||
.spanned(span)
|
||||
.with_size(Some(MathSize::Text))
|
||||
.with_cramped(Some(cramped))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
}
|
||||
|
||||
/// Forced script style in math.
|
||||
@ -231,10 +233,10 @@ pub fn script(
|
||||
cramped: bool,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body)
|
||||
.spanned(span)
|
||||
.with_size(Some(MathSize::Script))
|
||||
.with_cramped(Some(cramped))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
}
|
||||
|
||||
/// Forced second script style in math.
|
||||
@ -258,10 +260,10 @@ pub fn sscript(
|
||||
cramped: bool,
|
||||
) -> Content {
|
||||
MathStyleElem::new(body)
|
||||
.spanned(span)
|
||||
.with_size(Some(MathSize::ScriptScript))
|
||||
.with_cramped(Some(cramped))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
}
|
||||
|
||||
/// A font variant in math.
|
||||
@ -287,7 +289,7 @@ pub struct MathStyleElem {
|
||||
pub cramped: Option<bool>,
|
||||
}
|
||||
|
||||
impl LayoutMath for MathStyleElem {
|
||||
impl LayoutMath for Packed<MathStyleElem> {
|
||||
#[typst_macros::time(name = "math.style", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
let mut style = ctx.style;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::foundations::{elem, Content, NativeElement};
|
||||
use crate::foundations::{elem, Content, Packed};
|
||||
use crate::layout::{Abs, Em, FixedAlign, Frame, FrameItem, Point, Size};
|
||||
use crate::math::{
|
||||
alignments, AlignmentResult, FrameFragment, GlyphFragment, LayoutMath, MathContext,
|
||||
@ -32,7 +32,7 @@ pub struct UnderlineElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl LayoutMath for UnderlineElem {
|
||||
impl LayoutMath for Packed<UnderlineElem> {
|
||||
#[typst_macros::time(name = "math.underline", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout_underoverline(ctx, self.body(), self.span(), LineKind::Under)
|
||||
@ -51,7 +51,7 @@ pub struct OverlineElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl LayoutMath for OverlineElem {
|
||||
impl LayoutMath for Packed<OverlineElem> {
|
||||
#[typst_macros::time(name = "math.overline", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout_underoverline(ctx, self.body(), self.span(), LineKind::Over)
|
||||
@ -136,7 +136,7 @@ pub struct UnderbraceElem {
|
||||
pub annotation: Option<Content>,
|
||||
}
|
||||
|
||||
impl LayoutMath for UnderbraceElem {
|
||||
impl LayoutMath for Packed<UnderbraceElem> {
|
||||
#[typst_macros::time(name = "math.underbrace", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout_underoverspreader(
|
||||
@ -167,7 +167,7 @@ pub struct OverbraceElem {
|
||||
pub annotation: Option<Content>,
|
||||
}
|
||||
|
||||
impl LayoutMath for OverbraceElem {
|
||||
impl LayoutMath for Packed<OverbraceElem> {
|
||||
#[typst_macros::time(name = "math.overbrace", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout_underoverspreader(
|
||||
@ -198,7 +198,7 @@ pub struct UnderbracketElem {
|
||||
pub annotation: Option<Content>,
|
||||
}
|
||||
|
||||
impl LayoutMath for UnderbracketElem {
|
||||
impl LayoutMath for Packed<UnderbracketElem> {
|
||||
#[typst_macros::time(name = "math.underbrace", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout_underoverspreader(
|
||||
@ -229,7 +229,7 @@ pub struct OverbracketElem {
|
||||
pub annotation: Option<Content>,
|
||||
}
|
||||
|
||||
impl LayoutMath for OverbracketElem {
|
||||
impl LayoutMath for Packed<OverbracketElem> {
|
||||
#[typst_macros::time(name = "math.overbracket", span = self.span())]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
layout_underoverspreader(
|
||||
|
@ -24,8 +24,8 @@ use crate::engine::Engine;
|
||||
use crate::eval::{eval_string, EvalMode};
|
||||
use crate::foundations::{
|
||||
cast, elem, ty, Args, Array, Bytes, CastInfo, Content, Finalize, FromValue,
|
||||
IntoValue, Label, NativeElement, Reflect, Repr, Scope, Show, Smart, Str, StyleChain,
|
||||
Synthesize, Type, Value,
|
||||
IntoValue, Label, NativeElement, Packed, Reflect, Repr, Scope, Show, Smart, Str,
|
||||
StyleChain, Synthesize, Type, Value,
|
||||
};
|
||||
use crate::introspection::{Introspector, Locatable, Location};
|
||||
use crate::layout::{
|
||||
@ -155,7 +155,7 @@ cast! {
|
||||
|
||||
impl BibliographyElem {
|
||||
/// Find the document's bibliography.
|
||||
pub fn find(introspector: Tracked<Introspector>) -> StrResult<Self> {
|
||||
pub fn find(introspector: Tracked<Introspector>) -> StrResult<Packed<Self>> {
|
||||
let query = introspector.query(&Self::elem().select());
|
||||
let mut iter = query.iter();
|
||||
let Some(elem) = iter.next() else {
|
||||
@ -166,7 +166,7 @@ impl BibliographyElem {
|
||||
bail!("multiple bibliographies are not yet supported");
|
||||
}
|
||||
|
||||
Ok(elem.to::<Self>().cloned().unwrap())
|
||||
Ok(elem.to::<Self>().unwrap().clone())
|
||||
}
|
||||
|
||||
/// Whether the bibliography contains the given key.
|
||||
@ -196,17 +196,18 @@ impl BibliographyElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Synthesize for BibliographyElem {
|
||||
impl Synthesize for Packed<BibliographyElem> {
|
||||
fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
|
||||
self.push_full(self.full(styles));
|
||||
self.push_style(self.style(styles));
|
||||
self.push_lang(TextElem::lang_in(styles));
|
||||
self.push_region(TextElem::region_in(styles));
|
||||
let elem = self.as_mut();
|
||||
elem.push_full(elem.full(styles));
|
||||
elem.push_style(elem.style(styles));
|
||||
elem.push_lang(TextElem::lang_in(styles));
|
||||
elem.push_region(TextElem::region_in(styles));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for BibliographyElem {
|
||||
impl Show for Packed<BibliographyElem> {
|
||||
#[typst_macros::time(name = "bibliography", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
const COLUMN_GUTTER: Em = Em::new(0.65);
|
||||
@ -220,9 +221,9 @@ impl Show for BibliographyElem {
|
||||
|
||||
seq.push(
|
||||
HeadingElem::new(title)
|
||||
.spanned(self.span())
|
||||
.with_level(NonZeroUsize::ONE)
|
||||
.pack(),
|
||||
.pack()
|
||||
.spanned(self.span()),
|
||||
);
|
||||
}
|
||||
|
||||
@ -246,11 +247,11 @@ impl Show for BibliographyElem {
|
||||
seq.push(VElem::new(row_gutter).with_weakness(3).pack());
|
||||
seq.push(
|
||||
GridElem::new(cells)
|
||||
.spanned(self.span())
|
||||
.with_columns(TrackSizings(smallvec![Sizing::Auto; 2]))
|
||||
.with_column_gutter(TrackSizings(smallvec![COLUMN_GUTTER.into()]))
|
||||
.with_row_gutter(TrackSizings(smallvec![(row_gutter).into()]))
|
||||
.pack(),
|
||||
.pack()
|
||||
.spanned(self.span()),
|
||||
);
|
||||
} else {
|
||||
for (_, reference) in references {
|
||||
@ -269,7 +270,7 @@ impl Show for BibliographyElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Finalize for BibliographyElem {
|
||||
impl Finalize for Packed<BibliographyElem> {
|
||||
fn finalize(&self, realized: Content, _: StyleChain) -> Content {
|
||||
const INDENT: Em = Em::new(1.0);
|
||||
realized
|
||||
@ -278,7 +279,7 @@ impl Finalize for BibliographyElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalName for BibliographyElem {
|
||||
impl LocalName for Packed<BibliographyElem> {
|
||||
fn local_name(lang: Lang, region: Option<Region>) -> &'static str {
|
||||
match lang {
|
||||
Lang::ALBANIAN => "Bibliografi",
|
||||
@ -607,7 +608,7 @@ struct Generator<'a> {
|
||||
/// The world that is used to evaluate mathematical material in citations.
|
||||
world: Tracked<'a, dyn World + 'a>,
|
||||
/// The document's bibliography.
|
||||
bibliography: BibliographyElem,
|
||||
bibliography: Packed<BibliographyElem>,
|
||||
/// The document's citation groups.
|
||||
groups: EcoVec<Prehashed<Content>>,
|
||||
/// Details about each group that are accumulated while driving hayagriva's
|
||||
@ -672,7 +673,7 @@ impl<'a> Generator<'a> {
|
||||
let mut driver = BibliographyDriver::new();
|
||||
for elem in &self.groups {
|
||||
let group = elem.to::<CiteGroup>().unwrap();
|
||||
let location = group.location().unwrap();
|
||||
let location = elem.location().unwrap();
|
||||
let children = group.children();
|
||||
|
||||
// Groups should never be empty.
|
||||
@ -945,19 +946,19 @@ impl ElemRenderer<'_> {
|
||||
if let Some(prefix) = suf_prefix {
|
||||
const COLUMN_GUTTER: Em = Em::new(0.65);
|
||||
content = GridElem::new(vec![GridCell::new(prefix), GridCell::new(content)])
|
||||
.spanned(self.span)
|
||||
.with_columns(TrackSizings(smallvec![Sizing::Auto; 2]))
|
||||
.with_column_gutter(TrackSizings(smallvec![COLUMN_GUTTER.into()]))
|
||||
.pack();
|
||||
.pack()
|
||||
.spanned(self.span);
|
||||
}
|
||||
|
||||
match elem.display {
|
||||
Some(Display::Block) => {
|
||||
content =
|
||||
BlockElem::new().spanned(self.span).with_body(Some(content)).pack();
|
||||
BlockElem::new().with_body(Some(content)).pack().spanned(self.span);
|
||||
}
|
||||
Some(Display::Indent) => {
|
||||
content = PadElem::new(content).spanned(self.span).pack();
|
||||
content = PadElem::new(content).pack().spanned(self.span);
|
||||
}
|
||||
Some(Display::LeftMargin) => {
|
||||
*prefix.get_or_insert_with(Default::default) += content;
|
||||
@ -987,8 +988,8 @@ impl ElemRenderer<'_> {
|
||||
fn display_link(&self, text: &hayagriva::Formatted, url: &str) -> Content {
|
||||
let dest = Destination::Url(url.into());
|
||||
LinkElem::new(dest.into(), self.display_formatted(text))
|
||||
.spanned(self.span)
|
||||
.pack()
|
||||
.spanned(self.span)
|
||||
}
|
||||
|
||||
/// Display transparent pass-through content.
|
||||
@ -1043,10 +1044,10 @@ fn apply_formatting(mut content: Content, format: &hayagriva::Formatting) -> Con
|
||||
citationberg::VerticalAlign::Baseline => {}
|
||||
citationberg::VerticalAlign::Sup => {
|
||||
// Add zero-width weak spacing to make the superscript "sticky".
|
||||
content = HElem::hole().pack() + SuperElem::new(content).spanned(span).pack();
|
||||
content = HElem::hole().pack() + SuperElem::new(content).pack().spanned(span);
|
||||
}
|
||||
citationberg::VerticalAlign::Sub => {
|
||||
content = HElem::hole().pack() + SubElem::new(content).spanned(span).pack();
|
||||
content = HElem::hole().pack() + SubElem::new(content).pack().spanned(span);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::diag::{bail, At, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, Cast, Content, Label, NativeElement, Show, Smart, StyleChain, Synthesize,
|
||||
cast, elem, Cast, Content, Label, Packed, Show, Smart, StyleChain, Synthesize,
|
||||
};
|
||||
use crate::introspection::Locatable;
|
||||
use crate::model::bibliography::Works;
|
||||
@ -99,20 +99,21 @@ pub struct CiteElem {
|
||||
pub region: Option<Region>,
|
||||
}
|
||||
|
||||
impl Synthesize for CiteElem {
|
||||
impl Synthesize for Packed<CiteElem> {
|
||||
fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
|
||||
self.push_supplement(self.supplement(styles));
|
||||
self.push_form(self.form(styles));
|
||||
self.push_style(self.style(styles));
|
||||
self.push_lang(TextElem::lang_in(styles));
|
||||
self.push_region(TextElem::region_in(styles));
|
||||
let elem = self.as_mut();
|
||||
elem.push_supplement(elem.supplement(styles));
|
||||
elem.push_form(elem.form(styles));
|
||||
elem.push_style(elem.style(styles));
|
||||
elem.push_lang(TextElem::lang_in(styles));
|
||||
elem.push_region(TextElem::region_in(styles));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
CiteElem,
|
||||
v: Content => v.to::<Self>().cloned().ok_or("expected citation")?,
|
||||
v: Content => v.to_packed::<Self>().map_err(|_| "expected citation")?.unpack(),
|
||||
}
|
||||
|
||||
/// The form of the citation.
|
||||
@ -139,10 +140,10 @@ pub enum CitationForm {
|
||||
pub struct CiteGroup {
|
||||
/// The citations.
|
||||
#[required]
|
||||
pub children: Vec<CiteElem>,
|
||||
pub children: Vec<Packed<CiteElem>>,
|
||||
}
|
||||
|
||||
impl Show for CiteGroup {
|
||||
impl Show for Packed<CiteGroup> {
|
||||
#[typst_macros::time(name = "cite", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, _: StyleChain) -> SourceResult<Content> {
|
||||
Ok(engine.delayed(|engine| {
|
||||
|
@ -3,7 +3,8 @@ use ecow::EcoString;
|
||||
use crate::diag::{bail, SourceResult, StrResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, Args, Array, Construct, Content, Datetime, Smart, StyleChain, Value,
|
||||
cast, elem, Args, Array, Construct, Content, Datetime, Packed, Smart, StyleChain,
|
||||
Value,
|
||||
};
|
||||
use crate::introspection::{Introspector, ManualPageCounter};
|
||||
use crate::layout::{Frame, LayoutRoot, PageElem};
|
||||
@ -65,7 +66,7 @@ impl Construct for DocumentElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutRoot for DocumentElem {
|
||||
impl LayoutRoot for Packed<DocumentElem> {
|
||||
/// Layout the document into a sequence of frames, one per page.
|
||||
#[typst_macros::time(name = "document", span = self.span())]
|
||||
fn layout_root(
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, Content, Show, StyleChain};
|
||||
use crate::foundations::{elem, Content, Packed, Show, StyleChain};
|
||||
use crate::text::{ItalicToggle, TextElem};
|
||||
|
||||
/// Emphasizes content by toggling italics.
|
||||
@ -33,7 +33,7 @@ pub struct EmphElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Show for EmphElem {
|
||||
impl Show for Packed<EmphElem> {
|
||||
#[typst_macros::time(name = "emph", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> {
|
||||
Ok(self.body().clone().styled(TextElem::set_emph(ItalicToggle)))
|
||||
|
@ -3,7 +3,7 @@ use std::str::FromStr;
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, scope, Array, Content, Fold, NativeElement, Smart, StyleChain,
|
||||
cast, elem, scope, Array, Content, Fold, Packed, Smart, StyleChain,
|
||||
};
|
||||
use crate::layout::{
|
||||
Alignment, Axes, BlockElem, Cell, CellGrid, Em, Fragment, GridLayouter, HAlignment,
|
||||
@ -194,7 +194,7 @@ pub struct EnumElem {
|
||||
/// ) [+ #phase]
|
||||
/// ```
|
||||
#[variadic]
|
||||
pub children: Vec<EnumItem>,
|
||||
pub children: Vec<Packed<EnumItem>>,
|
||||
|
||||
/// The numbers of parent items.
|
||||
#[internal]
|
||||
@ -208,7 +208,7 @@ impl EnumElem {
|
||||
type EnumItem;
|
||||
}
|
||||
|
||||
impl Layout for EnumElem {
|
||||
impl Layout for Packed<EnumElem> {
|
||||
#[typst_macros::time(name = "enum", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -263,7 +263,7 @@ impl Layout for EnumElem {
|
||||
cells.push(Cell::from(resolved));
|
||||
cells.push(Cell::from(Content::empty()));
|
||||
cells.push(Cell::from(
|
||||
item.body().clone().styled(Self::set_parents(Parent(number))),
|
||||
item.body().clone().styled(EnumElem::set_parents(Parent(number))),
|
||||
));
|
||||
number = number.saturating_add(1);
|
||||
}
|
||||
@ -308,7 +308,10 @@ cast! {
|
||||
};
|
||||
Self::new(body).with_number(number)
|
||||
},
|
||||
v: Content => v.to::<Self>().cloned().unwrap_or_else(|| Self::new(v.clone())),
|
||||
v: Content => match v.to_packed::<Self>() {
|
||||
Ok(packed) => packed.unpack(),
|
||||
Err(v) => Self::new(v),
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Hash)]
|
||||
|
@ -7,8 +7,8 @@ use ecow::EcoString;
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, scope, select_where, Content, Element, Finalize, NativeElement, Selector,
|
||||
Show, Smart, StyleChain, Synthesize,
|
||||
cast, elem, scope, select_where, Content, Element, Finalize, NativeElement, Packed,
|
||||
Selector, Show, Smart, StyleChain, Synthesize,
|
||||
};
|
||||
use crate::introspection::{
|
||||
Count, Counter, CounterKey, CounterUpdate, Locatable, Location,
|
||||
@ -134,7 +134,7 @@ pub struct FigureElem {
|
||||
pub placement: Option<Smart<VAlignment>>,
|
||||
|
||||
/// The figure's caption.
|
||||
pub caption: Option<FigureCaption>,
|
||||
pub caption: Option<Packed<FigureCaption>>,
|
||||
|
||||
/// The kind of figure this is.
|
||||
///
|
||||
@ -222,24 +222,29 @@ impl FigureElem {
|
||||
type FigureCaption;
|
||||
}
|
||||
|
||||
impl Synthesize for FigureElem {
|
||||
impl Synthesize for Packed<FigureElem> {
|
||||
fn synthesize(
|
||||
&mut self,
|
||||
engine: &mut Engine,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<()> {
|
||||
let numbering = self.numbering(styles);
|
||||
let span = self.span();
|
||||
let location = self.location();
|
||||
|
||||
let elem = self.as_mut();
|
||||
let placement = elem.placement(styles);
|
||||
let numbering = elem.numbering(styles);
|
||||
|
||||
// Determine the figure's kind.
|
||||
let kind = self.kind(styles).unwrap_or_else(|| {
|
||||
self.body()
|
||||
let kind = elem.kind(styles).unwrap_or_else(|| {
|
||||
elem.body()
|
||||
.query_first(Selector::can::<dyn Figurable>())
|
||||
.map(|elem| FigureKind::Elem(elem.func()))
|
||||
.unwrap_or_else(|| FigureKind::Elem(ImageElem::elem()))
|
||||
});
|
||||
|
||||
// Resolve the supplement.
|
||||
let supplement = match self.supplement(styles).as_ref() {
|
||||
let supplement = match elem.supplement(styles).as_ref() {
|
||||
Smart::Auto => {
|
||||
// Default to the local name for the kind, if available.
|
||||
let name = match &kind {
|
||||
@ -253,7 +258,7 @@ impl Synthesize for FigureElem {
|
||||
};
|
||||
|
||||
if numbering.is_some() && name.is_none() {
|
||||
bail!(self.span(), "please specify the figure's supplement")
|
||||
bail!(span, "please specify the figure's supplement")
|
||||
}
|
||||
|
||||
Some(name.unwrap_or_default())
|
||||
@ -263,45 +268,46 @@ impl Synthesize for FigureElem {
|
||||
// Resolve the supplement with the first descendant of the kind or
|
||||
// just the body, if none was found.
|
||||
let descendant = match kind {
|
||||
FigureKind::Elem(func) => self
|
||||
FigureKind::Elem(func) => elem
|
||||
.body()
|
||||
.query_first(Selector::Elem(func, None))
|
||||
.map(Cow::Owned),
|
||||
FigureKind::Name(_) => None,
|
||||
};
|
||||
|
||||
let target = descendant.unwrap_or_else(|| Cow::Borrowed(self.body()));
|
||||
let target = descendant.unwrap_or_else(|| Cow::Borrowed(elem.body()));
|
||||
Some(supplement.resolve(engine, [target])?)
|
||||
}
|
||||
};
|
||||
|
||||
// Construct the figure's counter.
|
||||
let counter =
|
||||
Counter::new(CounterKey::Selector(select_where!(Self, Kind => kind.clone())));
|
||||
let counter = Counter::new(CounterKey::Selector(
|
||||
select_where!(FigureElem, Kind => kind.clone()),
|
||||
));
|
||||
|
||||
// Fill the figure's caption.
|
||||
let mut caption = self.caption(styles);
|
||||
let mut caption = elem.caption(styles);
|
||||
if let Some(caption) = &mut caption {
|
||||
caption.push_kind(kind.clone());
|
||||
caption.push_supplement(supplement.clone());
|
||||
caption.push_numbering(numbering.clone());
|
||||
caption.push_counter(Some(counter.clone()));
|
||||
caption.push_figure_location(self.location());
|
||||
caption.push_figure_location(location);
|
||||
}
|
||||
|
||||
self.push_placement(self.placement(styles));
|
||||
self.push_caption(caption);
|
||||
self.push_kind(Smart::Custom(kind));
|
||||
self.push_supplement(Smart::Custom(supplement.map(Supplement::Content)));
|
||||
self.push_numbering(numbering);
|
||||
self.push_outlined(self.outlined(styles));
|
||||
self.push_counter(Some(counter));
|
||||
elem.push_placement(placement);
|
||||
elem.push_caption(caption);
|
||||
elem.push_kind(Smart::Custom(kind));
|
||||
elem.push_supplement(Smart::Custom(supplement.map(Supplement::Content)));
|
||||
elem.push_numbering(numbering);
|
||||
elem.push_outlined(elem.outlined(styles));
|
||||
elem.push_counter(Some(counter));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for FigureElem {
|
||||
impl Show for Packed<FigureElem> {
|
||||
#[typst_macros::time(name = "figure", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
let mut realized = self.body().clone();
|
||||
@ -319,60 +325,62 @@ impl Show for FigureElem {
|
||||
// Wrap the contents in a block.
|
||||
realized = BlockElem::new()
|
||||
.with_body(Some(realized))
|
||||
.spanned(self.span())
|
||||
.pack()
|
||||
.spanned(self.span())
|
||||
.aligned(Alignment::CENTER);
|
||||
|
||||
// Wrap in a float.
|
||||
if let Some(align) = self.placement(styles) {
|
||||
realized = PlaceElem::new(realized)
|
||||
.spanned(self.span())
|
||||
.with_float(true)
|
||||
.with_alignment(align.map(|align| HAlignment::Center + align))
|
||||
.pack();
|
||||
.pack()
|
||||
.spanned(self.span());
|
||||
}
|
||||
|
||||
Ok(realized)
|
||||
}
|
||||
}
|
||||
|
||||
impl Finalize for FigureElem {
|
||||
impl Finalize for Packed<FigureElem> {
|
||||
fn finalize(&self, realized: Content, _: StyleChain) -> Content {
|
||||
// Allow breakable figures with `show figure: set block(breakable: true)`.
|
||||
realized.styled(BlockElem::set_breakable(false))
|
||||
}
|
||||
}
|
||||
|
||||
impl Count for FigureElem {
|
||||
impl Count for Packed<FigureElem> {
|
||||
fn update(&self) -> Option<CounterUpdate> {
|
||||
// If the figure is numbered, step the counter by one.
|
||||
// This steps the `counter(figure)` which is global to all numbered figures.
|
||||
self.numbering(StyleChain::default())
|
||||
self.numbering()
|
||||
.is_some()
|
||||
.then(|| CounterUpdate::Step(NonZeroUsize::ONE))
|
||||
}
|
||||
}
|
||||
|
||||
impl Refable for FigureElem {
|
||||
impl Refable for Packed<FigureElem> {
|
||||
fn supplement(&self) -> Content {
|
||||
// After synthesis, this should always be custom content.
|
||||
let default = StyleChain::default();
|
||||
match self.supplement(default).as_ref() {
|
||||
match (**self).supplement(StyleChain::default()).as_ref() {
|
||||
Smart::Custom(Some(Supplement::Content(content))) => content.clone(),
|
||||
_ => Content::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
fn counter(&self) -> Counter {
|
||||
self.counter().clone().unwrap_or_else(|| Counter::of(Self::elem()))
|
||||
(**self)
|
||||
.counter()
|
||||
.clone()
|
||||
.unwrap_or_else(|| Counter::of(FigureElem::elem()))
|
||||
}
|
||||
|
||||
fn numbering(&self) -> Option<Numbering> {
|
||||
self.numbering(StyleChain::default())
|
||||
(**self).numbering(StyleChain::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Outlinable for FigureElem {
|
||||
impl Outlinable for Packed<FigureElem> {
|
||||
fn outline(&self, engine: &mut Engine) -> SourceResult<Option<Content>> {
|
||||
if !self.outlined(StyleChain::default()) {
|
||||
return Ok(None);
|
||||
@ -388,9 +396,9 @@ impl Outlinable for FigureElem {
|
||||
Some(counter),
|
||||
Some(numbering),
|
||||
) = (
|
||||
self.supplement(StyleChain::default()).clone(),
|
||||
self.counter(),
|
||||
self.numbering(StyleChain::default()),
|
||||
(**self).supplement(StyleChain::default()).clone(),
|
||||
(**self).counter(),
|
||||
self.numbering(),
|
||||
) {
|
||||
let location = self.location().unwrap();
|
||||
let numbers = counter.at(engine, location)?.display(engine, &numbering)?;
|
||||
@ -546,15 +554,16 @@ impl FigureCaption {
|
||||
}
|
||||
}
|
||||
|
||||
impl Synthesize for FigureCaption {
|
||||
impl Synthesize for Packed<FigureCaption> {
|
||||
fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
|
||||
self.push_position(self.position(styles));
|
||||
self.push_separator(Smart::Custom(self.get_separator(styles)));
|
||||
let elem = self.as_mut();
|
||||
elem.push_position(elem.position(styles));
|
||||
elem.push_separator(Smart::Custom(elem.get_separator(styles)));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for FigureCaption {
|
||||
impl Show for Packed<FigureCaption> {
|
||||
#[typst_macros::time(name = "figure.caption", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
let mut realized = self.body().clone();
|
||||
@ -578,7 +587,10 @@ impl Show for FigureCaption {
|
||||
|
||||
cast! {
|
||||
FigureCaption,
|
||||
v: Content => v.to::<Self>().cloned().unwrap_or_else(|| Self::new(v.clone())),
|
||||
v: Content => match v.to_packed::<Self>() {
|
||||
Ok(packed) => packed.unpack(),
|
||||
Err(v) => Self::new(v),
|
||||
},
|
||||
}
|
||||
|
||||
/// The `kind` parameter of a [`FigureElem`].
|
||||
|
@ -4,8 +4,8 @@ use std::str::FromStr;
|
||||
use crate::diag::{bail, At, SourceResult, StrResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, scope, Content, Finalize, Label, NativeElement, Show, Smart, StyleChain,
|
||||
Synthesize,
|
||||
cast, elem, scope, Content, Finalize, Label, NativeElement, Packed, Show, Smart,
|
||||
StyleChain, Synthesize,
|
||||
};
|
||||
use crate::introspection::{Count, Counter, CounterUpdate, Locatable, Location};
|
||||
use crate::layout::{Abs, Em, HElem, Length, Ratio};
|
||||
@ -104,7 +104,9 @@ impl FootnoteElem {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Packed<FootnoteElem> {
|
||||
/// Returns the location of the definition of this footnote.
|
||||
pub fn declaration_location(&self, engine: &Engine) -> StrResult<Location> {
|
||||
match self.body() {
|
||||
@ -120,22 +122,23 @@ impl FootnoteElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Synthesize for FootnoteElem {
|
||||
impl Synthesize for Packed<FootnoteElem> {
|
||||
fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
|
||||
self.push_numbering(self.numbering(styles).clone());
|
||||
let elem = self.as_mut();
|
||||
elem.push_numbering(elem.numbering(styles).clone());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for FootnoteElem {
|
||||
impl Show for Packed<FootnoteElem> {
|
||||
#[typst_macros::time(name = "footnote", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(engine.delayed(|engine| {
|
||||
let loc = self.declaration_location(engine).at(self.span())?;
|
||||
let numbering = self.numbering(styles);
|
||||
let counter = Counter::of(Self::elem());
|
||||
let counter = Counter::of(FootnoteElem::elem());
|
||||
let num = counter.at(engine, loc)?.display(engine, numbering)?;
|
||||
let sup = SuperElem::new(num).spanned(self.span()).pack();
|
||||
let sup = SuperElem::new(num).pack().spanned(self.span());
|
||||
let loc = loc.variant(1);
|
||||
// Add zero-width weak spacing to make the footnote "sticky".
|
||||
Ok(HElem::hole().pack() + sup.linked(Destination::Location(loc)))
|
||||
@ -143,7 +146,7 @@ impl Show for FootnoteElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Count for FootnoteElem {
|
||||
impl Count for Packed<FootnoteElem> {
|
||||
fn update(&self) -> Option<CounterUpdate> {
|
||||
(!self.is_ref()).then(|| CounterUpdate::Step(NonZeroUsize::ONE))
|
||||
}
|
||||
@ -203,7 +206,7 @@ pub struct FootnoteEntry {
|
||||
/// listing #footnote[World! 🌏]
|
||||
/// ```
|
||||
#[required]
|
||||
pub note: FootnoteElem,
|
||||
pub note: Packed<FootnoteElem>,
|
||||
|
||||
/// The separator between the document body and the footnote listing.
|
||||
///
|
||||
@ -269,7 +272,7 @@ pub struct FootnoteEntry {
|
||||
pub indent: Length,
|
||||
}
|
||||
|
||||
impl Show for FootnoteEntry {
|
||||
impl Show for Packed<FootnoteEntry> {
|
||||
#[typst_macros::time(name = "footnote.entry", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
let note = self.note();
|
||||
@ -286,8 +289,8 @@ impl Show for FootnoteEntry {
|
||||
|
||||
let num = counter.at(engine, loc)?.display(engine, numbering)?;
|
||||
let sup = SuperElem::new(num)
|
||||
.spanned(self.span())
|
||||
.pack()
|
||||
.spanned(self.span())
|
||||
.linked(Destination::Location(loc))
|
||||
.backlinked(loc.variant(1));
|
||||
Ok(Content::sequence([
|
||||
@ -299,7 +302,7 @@ impl Show for FootnoteEntry {
|
||||
}
|
||||
}
|
||||
|
||||
impl Finalize for FootnoteEntry {
|
||||
impl Finalize for Packed<FootnoteEntry> {
|
||||
fn finalize(&self, realized: Content, _: StyleChain) -> Content {
|
||||
let text_size = Em::new(0.85);
|
||||
let leading = Em::new(0.5);
|
||||
@ -311,5 +314,8 @@ impl Finalize for FootnoteEntry {
|
||||
|
||||
cast! {
|
||||
FootnoteElem,
|
||||
v: Content => v.to::<Self>().cloned().unwrap_or_else(|| Self::with_content(v.clone())),
|
||||
v: Content => match v.to_packed::<Self>() {
|
||||
Ok(packed) => packed.unpack(),
|
||||
Err(v) => Self::with_content(v),
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use std::num::NonZeroUsize;
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, Content, Finalize, NativeElement, Show, Smart, StyleChain, Styles,
|
||||
elem, Content, Finalize, NativeElement, Packed, Show, Smart, StyleChain, Styles,
|
||||
Synthesize,
|
||||
};
|
||||
use crate::introspection::{Count, Counter, CounterUpdate, Locatable};
|
||||
@ -126,53 +126,49 @@ pub struct HeadingElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Synthesize for HeadingElem {
|
||||
impl Synthesize for Packed<HeadingElem> {
|
||||
fn synthesize(
|
||||
&mut self,
|
||||
engine: &mut Engine,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<()> {
|
||||
// Resolve the supplement.
|
||||
let supplement = match self.supplement(styles) {
|
||||
let supplement = match (**self).supplement(styles) {
|
||||
Smart::Auto => TextElem::packed(Self::local_name_in(styles)),
|
||||
Smart::Custom(None) => Content::empty(),
|
||||
Smart::Custom(Some(supplement)) => {
|
||||
supplement.resolve(engine, [self.clone()])?
|
||||
supplement.resolve(engine, [self.clone().pack()])?
|
||||
}
|
||||
};
|
||||
|
||||
self.push_level(self.level(styles));
|
||||
self.push_numbering(self.numbering(styles).clone());
|
||||
self.push_supplement(Smart::Custom(Some(Supplement::Content(supplement))));
|
||||
self.push_outlined(self.outlined(styles));
|
||||
self.push_bookmarked(self.bookmarked(styles));
|
||||
let elem = self.as_mut();
|
||||
elem.push_level(elem.level(styles));
|
||||
elem.push_numbering(elem.numbering(styles).clone());
|
||||
elem.push_supplement(Smart::Custom(Some(Supplement::Content(supplement))));
|
||||
elem.push_outlined(elem.outlined(styles));
|
||||
elem.push_bookmarked(elem.bookmarked(styles));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for HeadingElem {
|
||||
impl Show for Packed<HeadingElem> {
|
||||
#[typst_macros::time(name = "heading", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
let mut realized = self.body().clone();
|
||||
if let Some(numbering) = self.numbering(styles).as_ref() {
|
||||
realized = Counter::of(Self::elem())
|
||||
if let Some(numbering) = (**self).numbering(styles).as_ref() {
|
||||
realized = Counter::of(HeadingElem::elem())
|
||||
.display(self.span(), Some(numbering.clone()), false)
|
||||
.spanned(self.span())
|
||||
+ HElem::new(Em::new(0.3).into()).with_weak(true).pack()
|
||||
+ realized;
|
||||
}
|
||||
Ok(BlockElem::new()
|
||||
.spanned(self.span())
|
||||
.spanned(self.span())
|
||||
.with_body(Some(realized))
|
||||
.pack())
|
||||
Ok(BlockElem::new().with_body(Some(realized)).pack().spanned(self.span()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Finalize for HeadingElem {
|
||||
impl Finalize for Packed<HeadingElem> {
|
||||
fn finalize(&self, realized: Content, styles: StyleChain) -> Content {
|
||||
let level = self.level(styles).get();
|
||||
let level = (**self).level(styles).get();
|
||||
let scale = match level {
|
||||
1 => 1.4,
|
||||
2 => 1.2,
|
||||
@ -193,47 +189,42 @@ impl Finalize for HeadingElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Count for HeadingElem {
|
||||
impl Count for Packed<HeadingElem> {
|
||||
fn update(&self) -> Option<CounterUpdate> {
|
||||
self.numbering(StyleChain::default())
|
||||
(**self)
|
||||
.numbering(StyleChain::default())
|
||||
.is_some()
|
||||
.then(|| CounterUpdate::Step(self.level(StyleChain::default())))
|
||||
.then(|| CounterUpdate::Step((**self).level(StyleChain::default())))
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
HeadingElem,
|
||||
v: Content => v.to::<Self>().ok_or("expected heading")?.clone(),
|
||||
}
|
||||
|
||||
impl Refable for HeadingElem {
|
||||
impl Refable for Packed<HeadingElem> {
|
||||
fn supplement(&self) -> Content {
|
||||
// After synthesis, this should always be custom content.
|
||||
match self.supplement(StyleChain::default()) {
|
||||
match (**self).supplement(StyleChain::default()) {
|
||||
Smart::Custom(Some(Supplement::Content(content))) => content,
|
||||
_ => Content::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
fn counter(&self) -> Counter {
|
||||
Counter::of(Self::elem())
|
||||
Counter::of(HeadingElem::elem())
|
||||
}
|
||||
|
||||
fn numbering(&self) -> Option<Numbering> {
|
||||
self.numbering(StyleChain::default()).clone()
|
||||
(**self).numbering(StyleChain::default()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Outlinable for HeadingElem {
|
||||
impl Outlinable for Packed<HeadingElem> {
|
||||
fn outline(&self, engine: &mut Engine) -> SourceResult<Option<Content>> {
|
||||
if !self.outlined(StyleChain::default()) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut content = self.body().clone();
|
||||
let default = StyleChain::default();
|
||||
if let Some(numbering) = self.numbering(default).as_ref() {
|
||||
let numbers = Counter::of(Self::elem())
|
||||
if let Some(numbering) = (**self).numbering(StyleChain::default()).as_ref() {
|
||||
let numbers = Counter::of(HeadingElem::elem())
|
||||
.at(engine, self.location().unwrap())?
|
||||
.display(engine, numbering)?;
|
||||
content = numbers + SpaceElem::new().pack() + content;
|
||||
@ -243,11 +234,11 @@ impl Outlinable for HeadingElem {
|
||||
}
|
||||
|
||||
fn level(&self) -> NonZeroUsize {
|
||||
self.level(StyleChain::default())
|
||||
(**self).level(StyleChain::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalName for HeadingElem {
|
||||
impl LocalName for Packed<HeadingElem> {
|
||||
fn local_name(lang: Lang, region: Option<Region>) -> &'static str {
|
||||
match lang {
|
||||
Lang::ALBANIAN => "Kapitull",
|
||||
|
@ -3,7 +3,7 @@ use ecow::{eco_format, EcoString};
|
||||
use crate::diag::{At, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, Content, Label, NativeElement, Repr, Show, Smart, StyleChain,
|
||||
cast, elem, Content, Label, Packed, Repr, Show, Smart, StyleChain,
|
||||
};
|
||||
use crate::introspection::Location;
|
||||
use crate::layout::Position;
|
||||
@ -89,7 +89,7 @@ impl LinkElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for LinkElem {
|
||||
impl Show for Packed<LinkElem> {
|
||||
#[typst_macros::time(name = "link", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, _: StyleChain) -> SourceResult<Content> {
|
||||
let body = self.body().clone();
|
||||
|
@ -1,8 +1,7 @@
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, scope, Array, Content, Fold, Func, NativeElement, Smart, StyleChain,
|
||||
Value,
|
||||
cast, elem, scope, Array, Content, Fold, Func, Packed, Smart, StyleChain, Value,
|
||||
};
|
||||
use crate::layout::{
|
||||
Axes, BlockElem, Cell, CellGrid, Em, Fragment, GridLayouter, HAlignment, Layout,
|
||||
@ -120,7 +119,7 @@ pub struct ListElem {
|
||||
/// ]
|
||||
/// ```
|
||||
#[variadic]
|
||||
pub children: Vec<ListItem>,
|
||||
pub children: Vec<Packed<ListItem>>,
|
||||
|
||||
/// The nesting depth.
|
||||
#[internal]
|
||||
@ -134,7 +133,7 @@ impl ListElem {
|
||||
type ListItem;
|
||||
}
|
||||
|
||||
impl Layout for ListElem {
|
||||
impl Layout for Packed<ListElem> {
|
||||
#[typst_macros::time(name = "list", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -163,7 +162,8 @@ impl Layout for ListElem {
|
||||
cells.push(Cell::from(Content::empty()));
|
||||
cells.push(Cell::from(marker.clone()));
|
||||
cells.push(Cell::from(Content::empty()));
|
||||
cells.push(Cell::from(item.body().clone().styled(Self::set_depth(Depth))));
|
||||
cells
|
||||
.push(Cell::from(item.body().clone().styled(ListElem::set_depth(Depth))));
|
||||
}
|
||||
|
||||
let stroke = None;
|
||||
@ -194,7 +194,10 @@ pub struct ListItem {
|
||||
|
||||
cast! {
|
||||
ListItem,
|
||||
v: Content => v.to::<Self>().cloned().unwrap_or_else(|| Self::new(v.clone())),
|
||||
v: Content => match v.to_packed::<Self>() {
|
||||
Ok(packed) => packed.unpack(),
|
||||
Err(v) => Self::new(v),
|
||||
}
|
||||
}
|
||||
|
||||
/// A list's marker.
|
||||
|
@ -5,7 +5,7 @@ use crate::diag::{bail, At, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, scope, select_where, Content, Finalize, Func, LocatableSelector,
|
||||
NativeElement, Show, Smart, StyleChain,
|
||||
NativeElement, Packed, Show, Smart, StyleChain,
|
||||
};
|
||||
use crate::introspection::{Counter, CounterKey, Locatable};
|
||||
use crate::layout::{BoxElem, Fr, HElem, HideElem, Length, Rel, RepeatElem, Spacing};
|
||||
@ -185,7 +185,7 @@ impl OutlineElem {
|
||||
type OutlineEntry;
|
||||
}
|
||||
|
||||
impl Show for OutlineElem {
|
||||
impl Show for Packed<OutlineElem> {
|
||||
#[typst_macros::time(name = "outline", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
let mut seq = vec![ParbreakElem::new().pack()];
|
||||
@ -197,9 +197,9 @@ impl Show for OutlineElem {
|
||||
|
||||
seq.push(
|
||||
HeadingElem::new(title)
|
||||
.spanned(self.span())
|
||||
.with_level(NonZeroUsize::ONE)
|
||||
.pack(),
|
||||
.pack()
|
||||
.spanned(self.span()),
|
||||
);
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ impl Show for OutlineElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Finalize for OutlineElem {
|
||||
impl Finalize for Packed<OutlineElem> {
|
||||
fn finalize(&self, realized: Content, _: StyleChain) -> Content {
|
||||
realized
|
||||
.styled(HeadingElem::set_outlined(false))
|
||||
@ -258,7 +258,7 @@ impl Finalize for OutlineElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalName for OutlineElem {
|
||||
impl LocalName for Packed<OutlineElem> {
|
||||
fn local_name(lang: Lang, region: Option<Region>) -> &'static str {
|
||||
match lang {
|
||||
Lang::ALBANIAN => "Përmbajtja",
|
||||
@ -492,7 +492,7 @@ impl OutlineEntry {
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for OutlineEntry {
|
||||
impl Show for Packed<OutlineEntry> {
|
||||
#[typst_macros::time(name = "outline.entry", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> {
|
||||
let mut seq = vec![];
|
||||
@ -518,10 +518,10 @@ impl Show for OutlineEntry {
|
||||
seq.push(SpaceElem::new().pack());
|
||||
seq.push(
|
||||
BoxElem::new()
|
||||
.spanned(self.span())
|
||||
.with_body(Some(filler.clone()))
|
||||
.with_width(Fr::one().into())
|
||||
.pack(),
|
||||
.pack()
|
||||
.spanned(self.span()),
|
||||
);
|
||||
seq.push(SpaceElem::new().pack());
|
||||
} else {
|
||||
|
@ -3,7 +3,7 @@ use comemo::Prehashed;
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
elem, Args, Cast, Construct, Content, NativeElement, Set, Smart, StyleChain,
|
||||
elem, Args, Cast, Construct, Content, NativeElement, Packed, Set, Smart, StyleChain,
|
||||
Unlabellable,
|
||||
};
|
||||
use crate::layout::{Em, Fragment, Length, Size};
|
||||
@ -122,7 +122,7 @@ impl Construct for ParElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl ParElem {
|
||||
impl Packed<ParElem> {
|
||||
/// Layout the paragraph into a collection of lines.
|
||||
#[typst_macros::time(name = "par", span = self.span())]
|
||||
pub fn layout(
|
||||
@ -177,4 +177,4 @@ pub enum Linebreaks {
|
||||
#[elem(title = "Paragraph Break", Unlabellable)]
|
||||
pub struct ParbreakElem {}
|
||||
|
||||
impl Unlabellable for ParbreakElem {}
|
||||
impl Unlabellable for Packed<ParbreakElem> {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, Content, Finalize, Label, NativeElement, Show, Smart, StyleChain,
|
||||
cast, elem, Content, Finalize, Label, NativeElement, Packed, Show, Smart, StyleChain,
|
||||
Synthesize,
|
||||
};
|
||||
use crate::layout::{Alignment, BlockElem, Em, HElem, PadElem, Spacing, VElem};
|
||||
@ -145,15 +145,16 @@ cast! {
|
||||
label: Label => Self::Label(label),
|
||||
}
|
||||
|
||||
impl Synthesize for QuoteElem {
|
||||
impl Synthesize for Packed<QuoteElem> {
|
||||
fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
|
||||
self.push_block(self.block(styles));
|
||||
self.push_quotes(self.quotes(styles));
|
||||
let elem = self.as_mut();
|
||||
elem.push_block(elem.block(styles));
|
||||
elem.push_quotes(elem.quotes(styles));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for QuoteElem {
|
||||
impl Show for Packed<QuoteElem> {
|
||||
#[typst_macros::time(name = "quote", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
let mut realized = self.body().clone();
|
||||
@ -169,7 +170,7 @@ impl Show for QuoteElem {
|
||||
|
||||
if block {
|
||||
realized =
|
||||
BlockElem::new().spanned(self.span()).with_body(Some(realized)).pack();
|
||||
BlockElem::new().with_body(Some(realized)).pack().spanned(self.span());
|
||||
|
||||
if let Some(attribution) = self.attribution(styles).as_ref() {
|
||||
let mut seq = vec![TextElem::packed('—'), SpaceElem::new().pack()];
|
||||
@ -181,9 +182,9 @@ impl Show for QuoteElem {
|
||||
Attribution::Label(label) => {
|
||||
seq.push(
|
||||
CiteElem::new(*label)
|
||||
.spanned(self.span())
|
||||
.with_form(Some(CitationForm::Prose))
|
||||
.pack(),
|
||||
.pack()
|
||||
.spanned(self.span()),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -197,14 +198,14 @@ impl Show for QuoteElem {
|
||||
realized = PadElem::new(realized).pack();
|
||||
} else if let Some(Attribution::Label(label)) = self.attribution(styles) {
|
||||
realized += SpaceElem::new().pack()
|
||||
+ CiteElem::new(*label).spanned(self.span()).pack();
|
||||
+ CiteElem::new(*label).pack().spanned(self.span());
|
||||
}
|
||||
|
||||
Ok(realized)
|
||||
}
|
||||
}
|
||||
|
||||
impl Finalize for QuoteElem {
|
||||
impl Finalize for Packed<QuoteElem> {
|
||||
fn finalize(&self, realized: Content, _: StyleChain) -> Content {
|
||||
let x = Em::new(1.0).into();
|
||||
let above = Em::new(2.4).into();
|
||||
|
@ -3,8 +3,8 @@ use ecow::eco_format;
|
||||
use crate::diag::{bail, At, Hint, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, Content, Func, IntoValue, Label, NativeElement, Show, Smart, StyleChain,
|
||||
Synthesize,
|
||||
cast, elem, Content, Func, IntoValue, Label, NativeElement, Packed, Show, Smart,
|
||||
StyleChain, Synthesize,
|
||||
};
|
||||
use crate::introspection::{Counter, Locatable};
|
||||
use crate::math::EquationElem;
|
||||
@ -129,27 +129,29 @@ pub struct RefElem {
|
||||
|
||||
/// A synthesized citation.
|
||||
#[synthesized]
|
||||
pub citation: Option<CiteElem>,
|
||||
pub citation: Option<Packed<CiteElem>>,
|
||||
|
||||
/// The referenced element.
|
||||
#[synthesized]
|
||||
pub element: Option<Content>,
|
||||
}
|
||||
|
||||
impl Synthesize for RefElem {
|
||||
impl Synthesize for Packed<RefElem> {
|
||||
fn synthesize(
|
||||
&mut self,
|
||||
engine: &mut Engine,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<()> {
|
||||
let citation = self.to_citation(engine, styles)?;
|
||||
self.push_citation(Some(citation));
|
||||
self.push_element(None);
|
||||
let citation = to_citation(self, engine, styles)?;
|
||||
|
||||
let target = *self.target();
|
||||
let elem = self.as_mut();
|
||||
elem.push_citation(Some(citation));
|
||||
elem.push_element(None);
|
||||
|
||||
let target = *elem.target();
|
||||
if !BibliographyElem::has(engine, target) {
|
||||
if let Ok(elem) = engine.introspector.query_label(target).cloned() {
|
||||
self.push_element(Some(elem.into_inner()));
|
||||
if let Ok(found) = engine.introspector.query_label(target).cloned() {
|
||||
elem.push_element(Some(found.into_inner()));
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -158,7 +160,7 @@ impl Synthesize for RefElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for RefElem {
|
||||
impl Show for Packed<RefElem> {
|
||||
#[typst_macros::time(name = "ref", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(engine.delayed(|engine| {
|
||||
@ -171,13 +173,13 @@ impl Show for RefElem {
|
||||
bail!(span, "label occurs in the document and its bibliography");
|
||||
}
|
||||
|
||||
return Ok(self.to_citation(engine, styles)?.spanned(span).pack());
|
||||
return Ok(to_citation(self, engine, styles)?.pack().spanned(span));
|
||||
}
|
||||
|
||||
let elem = elem.at(span)?;
|
||||
|
||||
if elem.func() == FootnoteElem::elem() {
|
||||
return Ok(FootnoteElem::with_label(target).spanned(span).pack());
|
||||
return Ok(FootnoteElem::with_label(target).pack().spanned(span));
|
||||
}
|
||||
|
||||
let elem = elem.clone();
|
||||
@ -236,23 +238,23 @@ impl Show for RefElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl RefElem {
|
||||
/// Turn the reference into a citation.
|
||||
pub fn to_citation(
|
||||
&self,
|
||||
engine: &mut Engine,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<CiteElem> {
|
||||
let mut elem = CiteElem::new(*self.target()).spanned(self.span());
|
||||
elem.set_location(self.location().unwrap());
|
||||
elem.synthesize(engine, styles)?;
|
||||
elem.push_supplement(match self.supplement(styles).clone() {
|
||||
/// Turn a reference into a citation.
|
||||
fn to_citation(
|
||||
reference: &Packed<RefElem>,
|
||||
engine: &mut Engine,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<Packed<CiteElem>> {
|
||||
let mut elem = Packed::new(CiteElem::new(*reference.target()).with_supplement(
|
||||
match reference.supplement(styles).clone() {
|
||||
Smart::Custom(Some(Supplement::Content(content))) => Some(content),
|
||||
_ => None,
|
||||
});
|
||||
},
|
||||
));
|
||||
|
||||
Ok(elem)
|
||||
}
|
||||
elem.synthesize(engine, styles)?;
|
||||
elem.set_location(reference.location().unwrap());
|
||||
|
||||
Ok(elem)
|
||||
}
|
||||
|
||||
/// Additional content for a reference.
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, Content, Show, StyleChain};
|
||||
use crate::foundations::{elem, Content, Packed, Show, StyleChain};
|
||||
use crate::text::{TextElem, WeightDelta};
|
||||
|
||||
/// Strongly emphasizes content by increasing the font weight.
|
||||
@ -37,7 +37,7 @@ pub struct StrongElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Show for StrongElem {
|
||||
impl Show for Packed<StrongElem> {
|
||||
#[typst_macros::time(name = "strong", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(self
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, scope, Content, Fold, NativeElement, Show, Smart, StyleChain,
|
||||
cast, elem, scope, Content, Fold, NativeElement, Packed, Show, Smart, StyleChain,
|
||||
};
|
||||
use crate::layout::{
|
||||
show_grid_cell, Abs, Alignment, Axes, Cell, CellGrid, Celled, Fragment, GridLayouter,
|
||||
@ -166,7 +166,7 @@ impl TableElem {
|
||||
type TableCell;
|
||||
}
|
||||
|
||||
impl Layout for TableElem {
|
||||
impl Layout for Packed<TableElem> {
|
||||
#[typst_macros::time(name = "table", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -202,7 +202,7 @@ impl Layout for TableElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalName for TableElem {
|
||||
impl LocalName for Packed<TableElem> {
|
||||
fn local_name(lang: Lang, _: Option<Region>) -> &'static str {
|
||||
match lang {
|
||||
Lang::ALBANIAN => "Tabel",
|
||||
@ -239,7 +239,7 @@ impl LocalName for TableElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Figurable for TableElem {}
|
||||
impl Figurable for Packed<TableElem> {}
|
||||
|
||||
/// A cell in the table. Use this to either override table properties for a
|
||||
/// particular cell, or in show rules to apply certain styles to multiple cells
|
||||
@ -315,7 +315,7 @@ impl ResolvableCell for TableCell {
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for TableCell {
|
||||
impl Show for Packed<TableCell> {
|
||||
fn show(&self, _engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
show_grid_cell(self.body().clone(), self.inset(styles), self.align(styles))
|
||||
}
|
||||
@ -323,9 +323,9 @@ impl Show for TableCell {
|
||||
|
||||
impl From<Content> for TableCell {
|
||||
fn from(value: Content) -> Self {
|
||||
value
|
||||
.to::<Self>()
|
||||
.cloned()
|
||||
.unwrap_or_else(|| Self::new(value.clone()))
|
||||
match value.to_packed::<Self>() {
|
||||
Ok(packed) => packed.unpack(),
|
||||
Err(v) => Self::new(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, scope, Array, Content, NativeElement, Smart, StyleChain,
|
||||
cast, elem, scope, Array, Content, NativeElement, Packed, Smart, StyleChain,
|
||||
};
|
||||
use crate::layout::{
|
||||
BlockElem, Em, Fragment, HElem, Layout, Length, Regions, Spacing, VElem,
|
||||
@ -98,7 +98,7 @@ pub struct TermsElem {
|
||||
/// ) [/ #product: Born in #year.]
|
||||
/// ```
|
||||
#[variadic]
|
||||
pub children: Vec<TermItem>,
|
||||
pub children: Vec<Packed<TermItem>>,
|
||||
}
|
||||
|
||||
#[scope]
|
||||
@ -107,7 +107,7 @@ impl TermsElem {
|
||||
type TermItem;
|
||||
}
|
||||
|
||||
impl Layout for TermsElem {
|
||||
impl Layout for Packed<TermsElem> {
|
||||
#[typst_macros::time(name = "terms", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -166,5 +166,5 @@ cast! {
|
||||
};
|
||||
Self::new(term, description)
|
||||
},
|
||||
v: Content => v.to::<Self>().cloned().ok_or("expected term item or array")?,
|
||||
v: Content => v.to_packed::<Self>().map_err(|_| "expected term item or array")?.unpack(),
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ use typed_arena::Arena;
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::{Engine, Route};
|
||||
use crate::foundations::{
|
||||
Behave, Behaviour, Content, Finalize, Guard, NativeElement, Recipe, Selector, Show,
|
||||
StyleChain, StyleVec, StyleVecBuilder, Styles, Synthesize,
|
||||
Behave, Behaviour, Content, Finalize, Guard, NativeElement, Packed, Recipe, Selector,
|
||||
Show, StyleChain, StyleVec, StyleVecBuilder, Styles, Synthesize,
|
||||
};
|
||||
use crate::introspection::{Locatable, Meta, MetaElem};
|
||||
use crate::layout::{
|
||||
@ -51,7 +51,7 @@ pub fn realize_root<'a>(
|
||||
builder.interrupt_page(Some(styles), true)?;
|
||||
let (pages, shared) = builder.doc.unwrap().pages.finish();
|
||||
let span = first_span(&pages);
|
||||
Ok((Cow::Owned(DocumentElem::new(pages.to_vec()).spanned(span).pack()), shared))
|
||||
Ok((Cow::Owned(DocumentElem::new(pages.to_vec()).pack().spanned(span)), shared))
|
||||
}
|
||||
|
||||
/// Realize into an element that is capable of block-level layout.
|
||||
@ -86,7 +86,7 @@ pub fn realize_block<'a>(
|
||||
|
||||
let (children, shared) = builder.flow.0.finish();
|
||||
let span = first_span(&children);
|
||||
Ok((Cow::Owned(FlowElem::new(children.to_vec()).spanned(span).pack()), shared))
|
||||
Ok((Cow::Owned(FlowElem::new(children.to_vec()).pack().spanned(span)), shared))
|
||||
}
|
||||
|
||||
/// Whether the target is affected by show rules in the given style chain.
|
||||
@ -137,7 +137,7 @@ pub fn realize(
|
||||
let span = elem.span();
|
||||
let meta = Meta::Elem(elem.clone());
|
||||
return Ok(Some(
|
||||
(elem + MetaElem::new().spanned(span).pack())
|
||||
(elem + MetaElem::new().pack().spanned(span))
|
||||
.styled(MetaElem::set_data(smallvec![meta])),
|
||||
));
|
||||
}
|
||||
@ -307,7 +307,7 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> {
|
||||
content = self
|
||||
.scratch
|
||||
.content
|
||||
.alloc(EquationElem::new(content.clone()).spanned(content.span()).pack());
|
||||
.alloc(EquationElem::new(content.clone()).pack().spanned(content.span()));
|
||||
}
|
||||
|
||||
if let Some(realized) = realize(self.engine, content, styles)? {
|
||||
@ -482,9 +482,9 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> {
|
||||
shared
|
||||
};
|
||||
let span = first_span(&children);
|
||||
let flow = FlowElem::new(children.to_vec()).spanned(span);
|
||||
let page = PageElem::new(flow.pack()).spanned(span);
|
||||
let stored = self.scratch.content.alloc(page.pack());
|
||||
let flow = FlowElem::new(children.to_vec());
|
||||
let page = PageElem::new(flow.pack().spanned(span));
|
||||
let stored = self.scratch.content.alloc(page.pack().spanned(span));
|
||||
self.accept(stored, styles)?;
|
||||
}
|
||||
Ok(())
|
||||
@ -622,7 +622,7 @@ impl<'a> ParBuilder<'a> {
|
||||
fn finish(self) -> (Content, StyleChain<'a>) {
|
||||
let (children, shared) = self.0.finish();
|
||||
let span = first_span(&children);
|
||||
(ParElem::new(children.to_vec()).spanned(span).pack(), shared)
|
||||
(ParElem::new(children.to_vec()).pack().spanned(span), shared)
|
||||
}
|
||||
}
|
||||
|
||||
@ -671,46 +671,49 @@ impl<'a> ListBuilder<'a> {
|
||||
items
|
||||
.iter()
|
||||
.map(|(item, local)| {
|
||||
let item = item.to::<ListItem>().unwrap();
|
||||
item.clone()
|
||||
.with_body(item.body().clone().styled_with_map(local.clone()))
|
||||
let mut item = item.to::<ListItem>().unwrap().clone();
|
||||
let body = item.body().clone().styled_with_map(local.clone());
|
||||
item.push_body(body);
|
||||
item
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
.with_tight(self.tight)
|
||||
.spanned(span)
|
||||
.pack()
|
||||
.spanned(span)
|
||||
} else if item.is::<EnumItem>() {
|
||||
EnumElem::new(
|
||||
items
|
||||
.iter()
|
||||
.map(|(item, local)| {
|
||||
let item = item.to::<EnumItem>().unwrap();
|
||||
item.clone()
|
||||
.with_body(item.body().clone().styled_with_map(local.clone()))
|
||||
let mut item = item.to::<EnumItem>().unwrap().clone();
|
||||
let body = item.body().clone().styled_with_map(local.clone());
|
||||
item.push_body(body);
|
||||
item
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
.with_tight(self.tight)
|
||||
.spanned(span)
|
||||
.pack()
|
||||
.spanned(span)
|
||||
} else if item.is::<TermItem>() {
|
||||
TermsElem::new(
|
||||
items
|
||||
.iter()
|
||||
.map(|(item, local)| {
|
||||
let item = item.to::<TermItem>().unwrap();
|
||||
item.clone()
|
||||
.with_term(item.term().clone().styled_with_map(local.clone()))
|
||||
.with_description(
|
||||
item.description().clone().styled_with_map(local.clone()),
|
||||
)
|
||||
let mut item = item.to::<TermItem>().unwrap().clone();
|
||||
let term = item.term().clone().styled_with_map(local.clone());
|
||||
let description =
|
||||
item.description().clone().styled_with_map(local.clone());
|
||||
item.push_term(term);
|
||||
item.push_description(description);
|
||||
item
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
.with_tight(self.tight)
|
||||
.spanned(span)
|
||||
.pack()
|
||||
.spanned(span)
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
@ -734,7 +737,7 @@ struct CiteGroupBuilder<'a> {
|
||||
/// The styles.
|
||||
styles: StyleChain<'a>,
|
||||
/// The citations.
|
||||
items: Vec<CiteElem>,
|
||||
items: Vec<Packed<CiteElem>>,
|
||||
/// Trailing content for which it is unclear whether it is part of the list.
|
||||
staged: Vec<(&'a Content, StyleChain<'a>)>,
|
||||
}
|
||||
@ -762,7 +765,7 @@ impl<'a> CiteGroupBuilder<'a> {
|
||||
|
||||
fn finish(self) -> (Content, StyleChain<'a>) {
|
||||
let span = self.items.first().map(|cite| cite.span()).unwrap_or(Span::detached());
|
||||
(CiteGroup::new(self.items).spanned(span).pack(), self.styles)
|
||||
(CiteGroup::new(self.items).pack().spanned(span), self.styles)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,9 @@ use ecow::{eco_format, EcoString};
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, ty, Content, Fold, Repr, Show, Smart, StyleChain};
|
||||
use crate::foundations::{
|
||||
elem, ty, Content, Fold, Packed, Repr, Show, Smart, StyleChain,
|
||||
};
|
||||
use crate::layout::{Abs, Em, Frame, FrameItem, Length, Point, Size};
|
||||
use crate::syntax::Span;
|
||||
use crate::text::{
|
||||
@ -84,7 +86,7 @@ pub struct UnderlineElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Show for UnderlineElem {
|
||||
impl Show for Packed<UnderlineElem> {
|
||||
#[typst_macros::time(name = "underline", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(self.body().clone().styled(TextElem::set_deco(Decoration {
|
||||
@ -176,7 +178,7 @@ pub struct OverlineElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Show for OverlineElem {
|
||||
impl Show for Packed<OverlineElem> {
|
||||
#[typst_macros::time(name = "overline", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(self.body().clone().styled(TextElem::set_deco(Decoration {
|
||||
@ -253,7 +255,7 @@ pub struct StrikeElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Show for StrikeElem {
|
||||
impl Show for Packed<StrikeElem> {
|
||||
#[typst_macros::time(name = "strike", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(self.body().clone().styled(TextElem::set_deco(Decoration {
|
||||
@ -323,7 +325,7 @@ pub struct HighlightElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Show for HighlightElem {
|
||||
impl Show for Packed<HighlightElem> {
|
||||
#[typst_macros::time(name = "highlight", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(self.body().clone().styled(TextElem::set_deco(Decoration {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::foundations::{elem, Behave, Behaviour};
|
||||
use crate::foundations::{elem, Behave, Behaviour, Packed};
|
||||
|
||||
/// Inserts a line break.
|
||||
///
|
||||
@ -36,7 +36,7 @@ pub struct LinebreakElem {
|
||||
pub justify: bool,
|
||||
}
|
||||
|
||||
impl Behave for LinebreakElem {
|
||||
impl Behave for Packed<LinebreakElem> {
|
||||
fn behaviour(&self) -> Behaviour {
|
||||
Behaviour::Destructive
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ use ttf_parser::Rect;
|
||||
|
||||
use crate::diag::{bail, SourceResult, StrResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::Packed;
|
||||
use crate::foundations::{
|
||||
cast, category, elem, Args, Array, Cast, Category, Construct, Content, Dict, Fold,
|
||||
NativeElement, Never, PlainText, Repr, Resolve, Scope, Set, Smart, StyleChain, Value,
|
||||
@ -673,7 +674,7 @@ impl Construct for TextElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl PlainText for TextElem {
|
||||
impl PlainText for Packed<TextElem> {
|
||||
fn plain_text(&self, text: &mut EcoString) {
|
||||
text.push_str(self.text());
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ use crate::diag::{At, FileError, SourceResult, StrResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, scope, Args, Array, Bytes, Content, Finalize, Fold, NativeElement,
|
||||
PlainText, Show, Smart, StyleChain, Styles, Synthesize, Value,
|
||||
Packed, PlainText, Show, Smart, StyleChain, Styles, Synthesize, Value,
|
||||
};
|
||||
use crate::layout::{BlockElem, Em, HAlignment};
|
||||
use crate::model::Figurable;
|
||||
@ -261,7 +261,7 @@ pub struct RawElem {
|
||||
/// Made accessible for the [`raw.line` element]($raw.line).
|
||||
/// Allows more styling control in `show` rules.
|
||||
#[synthesized]
|
||||
pub lines: Vec<RawLine>,
|
||||
pub lines: Vec<Packed<RawLine>>,
|
||||
}
|
||||
|
||||
#[scope]
|
||||
@ -287,11 +287,15 @@ impl RawElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Synthesize for RawElem {
|
||||
impl Synthesize for Packed<RawElem> {
|
||||
fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
|
||||
self.push_lang(self.lang(styles).clone());
|
||||
let span = self.span();
|
||||
let elem = self.as_mut();
|
||||
|
||||
let mut text = self.text().clone();
|
||||
let lang = elem.lang(styles).clone();
|
||||
elem.push_lang(lang);
|
||||
|
||||
let mut text = elem.text().clone();
|
||||
if text.contains('\t') {
|
||||
let tab_size = RawElem::tab_size_in(styles);
|
||||
text = align_tabs(&text, tab_size);
|
||||
@ -300,7 +304,7 @@ impl Synthesize for RawElem {
|
||||
let lines = split_newlines(&text);
|
||||
let count = lines.len() as i64;
|
||||
|
||||
let lang = self
|
||||
let lang = elem
|
||||
.lang(styles)
|
||||
.as_ref()
|
||||
.as_ref()
|
||||
@ -308,11 +312,11 @@ impl Synthesize for RawElem {
|
||||
.or(Some("txt".into()));
|
||||
|
||||
let extra_syntaxes = UnsyncLazy::new(|| {
|
||||
load_syntaxes(&self.syntaxes(styles), &self.syntaxes_data(styles)).unwrap()
|
||||
load_syntaxes(&elem.syntaxes(styles), &elem.syntaxes_data(styles)).unwrap()
|
||||
});
|
||||
|
||||
let theme = self.theme(styles).as_ref().as_ref().map(|theme_path| {
|
||||
load_theme(theme_path, self.theme_data(styles).as_ref().as_ref().unwrap())
|
||||
let theme = elem.theme(styles).as_ref().as_ref().map(|theme_path| {
|
||||
load_theme(theme_path, elem.theme_data(styles).as_ref().as_ref().unwrap())
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
@ -333,13 +337,13 @@ impl Synthesize for RawElem {
|
||||
&mut |_, range, style| styled(&text[range], foreground, style),
|
||||
&mut |i, range, line| {
|
||||
seq.push(
|
||||
RawLine::new(
|
||||
Packed::new(RawLine::new(
|
||||
i + 1,
|
||||
count,
|
||||
EcoString::from(&text[range]),
|
||||
Content::sequence(line.drain(..)),
|
||||
)
|
||||
.spanned(self.span()),
|
||||
))
|
||||
.spanned(span),
|
||||
);
|
||||
},
|
||||
)
|
||||
@ -364,34 +368,34 @@ impl Synthesize for RawElem {
|
||||
}
|
||||
|
||||
seq.push(
|
||||
RawLine::new(
|
||||
Packed::new(RawLine::new(
|
||||
i as i64 + 1,
|
||||
count,
|
||||
EcoString::from(line),
|
||||
Content::sequence(line_content),
|
||||
)
|
||||
.spanned(self.span()),
|
||||
))
|
||||
.spanned(span),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
seq.extend(lines.into_iter().enumerate().map(|(i, line)| {
|
||||
RawLine::new(
|
||||
Packed::new(RawLine::new(
|
||||
i as i64 + 1,
|
||||
count,
|
||||
EcoString::from(line),
|
||||
TextElem::packed(line),
|
||||
)
|
||||
.spanned(self.span())
|
||||
))
|
||||
.spanned(span)
|
||||
}));
|
||||
};
|
||||
|
||||
self.push_lines(seq);
|
||||
elem.push_lines(seq);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for RawElem {
|
||||
impl Show for Packed<RawElem> {
|
||||
#[typst_macros::time(name = "raw", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
let mut lines = EcoVec::with_capacity((2 * self.lines().len()).saturating_sub(1));
|
||||
@ -408,14 +412,14 @@ impl Show for RawElem {
|
||||
// Align the text before inserting it into the block.
|
||||
realized = realized.aligned(self.align(styles).into());
|
||||
realized =
|
||||
BlockElem::new().spanned(self.span()).with_body(Some(realized)).pack();
|
||||
BlockElem::new().with_body(Some(realized)).pack().spanned(self.span());
|
||||
}
|
||||
|
||||
Ok(realized)
|
||||
}
|
||||
}
|
||||
|
||||
impl Finalize for RawElem {
|
||||
impl Finalize for Packed<RawElem> {
|
||||
fn finalize(&self, realized: Content, _: StyleChain) -> Content {
|
||||
let mut styles = Styles::new();
|
||||
styles.set(TextElem::set_overhang(false));
|
||||
@ -428,7 +432,7 @@ impl Finalize for RawElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalName for RawElem {
|
||||
impl LocalName for Packed<RawElem> {
|
||||
fn local_name(lang: Lang, region: Option<Region>) -> &'static str {
|
||||
match lang {
|
||||
Lang::ALBANIAN => "List",
|
||||
@ -464,9 +468,9 @@ impl LocalName for RawElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Figurable for RawElem {}
|
||||
impl Figurable for Packed<RawElem> {}
|
||||
|
||||
impl PlainText for RawElem {
|
||||
impl PlainText for Packed<RawElem> {
|
||||
fn plain_text(&self, text: &mut EcoString) {
|
||||
text.push_str(self.text());
|
||||
}
|
||||
@ -498,14 +502,14 @@ pub struct RawLine {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Show for RawLine {
|
||||
impl Show for Packed<RawLine> {
|
||||
#[typst_macros::time(name = "raw.line", span = self.span())]
|
||||
fn show(&self, _: &mut Engine, _styles: StyleChain) -> SourceResult<Content> {
|
||||
Ok(self.body().clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl PlainText for RawLine {
|
||||
impl PlainText for Packed<RawLine> {
|
||||
fn plain_text(&self, text: &mut EcoString) {
|
||||
text.push_str(self.text());
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use ecow::EcoString;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, Content, Show, StyleChain};
|
||||
use crate::foundations::{elem, Content, Packed, Show, StyleChain};
|
||||
use crate::layout::{Em, Length};
|
||||
use crate::text::{variant, SpaceElem, TextElem, TextSize};
|
||||
use crate::World;
|
||||
@ -47,7 +47,7 @@ pub struct SubElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Show for SubElem {
|
||||
impl Show for Packed<SubElem> {
|
||||
#[typst_macros::time(name = "sub", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
let body = self.body().clone();
|
||||
@ -107,7 +107,7 @@ pub struct SuperElem {
|
||||
pub body: Content,
|
||||
}
|
||||
|
||||
impl Show for SuperElem {
|
||||
impl Show for Packed<SuperElem> {
|
||||
#[typst_macros::time(name = "super", span = self.span())]
|
||||
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||
let body = self.body().clone();
|
||||
|
@ -1,4 +1,6 @@
|
||||
use crate::foundations::{elem, Behave, Behaviour, PlainText, Repr, Unlabellable};
|
||||
use crate::foundations::{
|
||||
elem, Behave, Behaviour, Packed, PlainText, Repr, Unlabellable,
|
||||
};
|
||||
use ecow::EcoString;
|
||||
|
||||
/// A text space.
|
||||
@ -11,15 +13,15 @@ impl Repr for SpaceElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Behave for SpaceElem {
|
||||
impl Behave for Packed<SpaceElem> {
|
||||
fn behaviour(&self) -> Behaviour {
|
||||
Behaviour::Weak(2)
|
||||
}
|
||||
}
|
||||
|
||||
impl Unlabellable for SpaceElem {}
|
||||
impl Unlabellable for Packed<SpaceElem> {}
|
||||
|
||||
impl PlainText for SpaceElem {
|
||||
impl PlainText for Packed<SpaceElem> {
|
||||
fn plain_text(&self, text: &mut EcoString) {
|
||||
text.push(' ');
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use ecow::EcoString;
|
||||
use crate::diag::{bail, At, SourceResult, StrResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, func, scope, Bytes, Cast, Content, NativeElement, Resolve, Smart,
|
||||
cast, elem, func, scope, Bytes, Cast, Content, NativeElement, Packed, Resolve, Smart,
|
||||
StyleChain,
|
||||
};
|
||||
use crate::layout::{
|
||||
@ -124,7 +124,7 @@ impl ImageElem {
|
||||
#[named]
|
||||
fit: Option<ImageFit>,
|
||||
) -> StrResult<Content> {
|
||||
let mut elem = ImageElem::new(EcoString::new(), data).spanned(span);
|
||||
let mut elem = ImageElem::new(EcoString::new(), data);
|
||||
if let Some(format) = format {
|
||||
elem.push_format(format);
|
||||
}
|
||||
@ -140,11 +140,11 @@ impl ImageElem {
|
||||
if let Some(fit) = fit {
|
||||
elem.push_fit(fit);
|
||||
}
|
||||
Ok(elem.pack())
|
||||
Ok(elem.pack().spanned(span))
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for ImageElem {
|
||||
impl Layout for Packed<ImageElem> {
|
||||
#[typst_macros::time(name = "image", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -247,7 +247,7 @@ impl Layout for ImageElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalName for ImageElem {
|
||||
impl LocalName for Packed<ImageElem> {
|
||||
fn local_name(lang: Lang, region: Option<Region>) -> &'static str {
|
||||
match lang {
|
||||
Lang::ALBANIAN => "Figurë",
|
||||
@ -285,7 +285,7 @@ impl LocalName for ImageElem {
|
||||
}
|
||||
}
|
||||
|
||||
impl Figurable for ImageElem {}
|
||||
impl Figurable for Packed<ImageElem> {}
|
||||
|
||||
/// How an image should adjust itself to a given area.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, NativeElement, StyleChain};
|
||||
use crate::foundations::{elem, Packed, StyleChain};
|
||||
use crate::layout::{
|
||||
Abs, Angle, Axes, Fragment, Frame, FrameItem, Layout, Length, Regions, Rel, Size,
|
||||
};
|
||||
@ -58,7 +58,7 @@ pub struct LineElem {
|
||||
pub stroke: Stroke,
|
||||
}
|
||||
|
||||
impl Layout for LineElem {
|
||||
impl Layout for Packed<LineElem> {
|
||||
#[typst_macros::time(name = "line", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
|
@ -3,7 +3,7 @@ use kurbo::{CubicBez, ParamCurveExtrema};
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
array, cast, elem, Array, NativeElement, Reflect, Resolve, Smart, StyleChain,
|
||||
array, cast, elem, Array, Packed, Reflect, Resolve, Smart, StyleChain,
|
||||
};
|
||||
use crate::layout::{
|
||||
Abs, Axes, Fragment, Frame, FrameItem, Layout, Length, Point, Regions, Rel, Size,
|
||||
@ -70,7 +70,7 @@ pub struct PathElem {
|
||||
pub vertices: Vec<PathVertex>,
|
||||
}
|
||||
|
||||
impl Layout for PathElem {
|
||||
impl Layout for Packed<PathElem> {
|
||||
#[typst_macros::time(name = "path", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
|
@ -3,7 +3,7 @@ use std::f64::consts::PI;
|
||||
use crate::diag::{bail, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
elem, func, scope, Content, NativeElement, Resolve, Smart, StyleChain,
|
||||
elem, func, scope, Content, NativeElement, Packed, Resolve, Smart, StyleChain,
|
||||
};
|
||||
use crate::layout::{
|
||||
Axes, Em, Fragment, Frame, FrameItem, Layout, Length, Point, Regions, Rel,
|
||||
@ -114,18 +114,18 @@ impl PolygonElem {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut elem = PolygonElem::new(vertices).spanned(span);
|
||||
let mut elem = PolygonElem::new(vertices);
|
||||
if let Some(fill) = fill {
|
||||
elem.push_fill(fill);
|
||||
}
|
||||
if let Some(stroke) = stroke {
|
||||
elem.push_stroke(stroke);
|
||||
}
|
||||
elem.pack()
|
||||
elem.pack().spanned(span)
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for PolygonElem {
|
||||
impl Layout for Packed<PolygonElem> {
|
||||
#[typst_macros::time(name = "polygon", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
|
@ -2,7 +2,7 @@ use std::f64::consts::SQRT_2;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{elem, Content, NativeElement, Resolve, Smart, StyleChain};
|
||||
use crate::foundations::{elem, Content, Packed, Resolve, Smart, StyleChain};
|
||||
use crate::layout::{
|
||||
Abs, Axes, Corner, Corners, Fragment, Frame, FrameItem, Layout, Length, Point, Ratio,
|
||||
Regions, Rel, Sides, Size,
|
||||
@ -131,7 +131,7 @@ pub struct RectElem {
|
||||
pub body: Option<Content>,
|
||||
}
|
||||
|
||||
impl Layout for RectElem {
|
||||
impl Layout for Packed<RectElem> {
|
||||
#[typst_macros::time(name = "rect", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -237,7 +237,7 @@ pub struct SquareElem {
|
||||
pub body: Option<Content>,
|
||||
}
|
||||
|
||||
impl Layout for SquareElem {
|
||||
impl Layout for Packed<SquareElem> {
|
||||
#[typst_macros::time(name = "square", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -315,7 +315,7 @@ pub struct EllipseElem {
|
||||
pub body: Option<Content>,
|
||||
}
|
||||
|
||||
impl Layout for EllipseElem {
|
||||
impl Layout for Packed<EllipseElem> {
|
||||
#[typst_macros::time(name = "ellipse", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
@ -418,7 +418,7 @@ pub struct CircleElem {
|
||||
pub body: Option<Content>,
|
||||
}
|
||||
|
||||
impl Layout for CircleElem {
|
||||
impl Layout for Packed<CircleElem> {
|
||||
#[typst_macros::time(name = "circle", span = self.span())]
|
||||
fn layout(
|
||||
&self,
|
||||
|
Loading…
x
Reference in New Issue
Block a user