mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Share allocations for singletons (#4794)
This commit is contained in:
parent
a30b681251
commit
986d624b3a
@ -1,15 +1,16 @@
|
|||||||
use std::io::{self, IsTerminal, Write};
|
use std::io::{self, IsTerminal, Write};
|
||||||
|
|
||||||
use codespan_reporting::term::termcolor;
|
use codespan_reporting::term::termcolor;
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use termcolor::{ColorChoice, WriteColor};
|
use termcolor::{ColorChoice, WriteColor};
|
||||||
|
use typst::utils::singleton;
|
||||||
|
|
||||||
use crate::ARGS;
|
use crate::ARGS;
|
||||||
|
|
||||||
/// Returns a handle to the optionally colored terminal output.
|
/// Returns a handle to the optionally colored terminal output.
|
||||||
pub fn out() -> TermOut {
|
pub fn out() -> TermOut {
|
||||||
static OUTPUT: Lazy<TermOutInner> = Lazy::new(TermOutInner::new);
|
TermOut {
|
||||||
TermOut { inner: &OUTPUT }
|
inner: singleton!(TermOutInner, TermOutInner::new()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The stuff that has to be shared between instances of [`TermOut`].
|
/// The stuff that has to be shared between instances of [`TermOut`].
|
||||||
|
@ -97,13 +97,12 @@ fn summarize_font_family<'a>(variants: impl Iterator<Item = &'a FontInfo>) -> Ec
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use typst::diag::{FileError, FileResult};
|
use typst::diag::{FileError, FileResult};
|
||||||
use typst::foundations::{Bytes, Datetime, Smart};
|
use typst::foundations::{Bytes, Datetime, Smart};
|
||||||
use typst::layout::{Abs, Margin, PageElem};
|
use typst::layout::{Abs, Margin, PageElem};
|
||||||
use typst::syntax::{FileId, Source};
|
use typst::syntax::{FileId, Source};
|
||||||
use typst::text::{Font, FontBook, TextElem, TextSize};
|
use typst::text::{Font, FontBook, TextElem, TextSize};
|
||||||
use typst::utils::LazyHash;
|
use typst::utils::{singleton, LazyHash};
|
||||||
use typst::{Library, World};
|
use typst::{Library, World};
|
||||||
|
|
||||||
/// A world for IDE testing.
|
/// A world for IDE testing.
|
||||||
@ -118,15 +117,16 @@ mod tests {
|
|||||||
/// This is cheap because the shared base for all test runs is lazily
|
/// This is cheap because the shared base for all test runs is lazily
|
||||||
/// initialized just once.
|
/// initialized just once.
|
||||||
pub fn new(text: &str) -> Self {
|
pub fn new(text: &str) -> Self {
|
||||||
static BASE: Lazy<TestBase> = Lazy::new(TestBase::default);
|
|
||||||
let main = Source::detached(text);
|
let main = Source::detached(text);
|
||||||
Self { main, base: &*BASE }
|
Self {
|
||||||
|
main,
|
||||||
|
base: singleton!(TestBase, TestBase::default()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The ID of the main file in a `TestWorld`.
|
/// The ID of the main file in a `TestWorld`.
|
||||||
pub fn main_id() -> FileId {
|
pub fn main_id() -> FileId {
|
||||||
static ID: Lazy<FileId> = Lazy::new(|| Source::detached("").id());
|
*singleton!(FileId, Source::detached("").id())
|
||||||
*ID
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,9 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use siphasher::sip128::{Hasher128, SipHasher13};
|
use siphasher::sip128::{Hasher128, SipHasher13};
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use once_cell;
|
||||||
|
|
||||||
/// Turn a closure into a struct implementing [`Debug`].
|
/// Turn a closure into a struct implementing [`Debug`].
|
||||||
pub fn debug<F>(f: F) -> impl Debug
|
pub fn debug<F>(f: F) -> impl Debug
|
||||||
where
|
where
|
||||||
|
@ -1,8 +1,18 @@
|
|||||||
|
/// Create a lazy initialized, globally unique `'static` reference to a value.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! singleton {
|
||||||
|
($ty:ty, $value:expr) => {{
|
||||||
|
static VALUE: $crate::once_cell::sync::Lazy<$ty> =
|
||||||
|
$crate::once_cell::sync::Lazy::new(|| $value);
|
||||||
|
&*VALUE
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
/// Implement the `Sub` trait based on existing `Neg` and `Add` impls.
|
/// Implement the `Sub` trait based on existing `Neg` and `Add` impls.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! sub_impl {
|
macro_rules! sub_impl {
|
||||||
($a:ident - $b:ident -> $c:ident) => {
|
($a:ident - $b:ident -> $c:ident) => {
|
||||||
impl std::ops::Sub<$b> for $a {
|
impl ::core::ops::Sub<$b> for $a {
|
||||||
type Output = $c;
|
type Output = $c;
|
||||||
|
|
||||||
fn sub(self, other: $b) -> $c {
|
fn sub(self, other: $b) -> $c {
|
||||||
@ -16,7 +26,7 @@ macro_rules! sub_impl {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! assign_impl {
|
macro_rules! assign_impl {
|
||||||
($a:ident += $b:ident) => {
|
($a:ident += $b:ident) => {
|
||||||
impl std::ops::AddAssign<$b> for $a {
|
impl ::core::ops::AddAssign<$b> for $a {
|
||||||
fn add_assign(&mut self, other: $b) {
|
fn add_assign(&mut self, other: $b) {
|
||||||
*self = *self + other;
|
*self = *self + other;
|
||||||
}
|
}
|
||||||
@ -24,7 +34,7 @@ macro_rules! assign_impl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
($a:ident -= $b:ident) => {
|
($a:ident -= $b:ident) => {
|
||||||
impl std::ops::SubAssign<$b> for $a {
|
impl ::core::ops::SubAssign<$b> for $a {
|
||||||
fn sub_assign(&mut self, other: $b) {
|
fn sub_assign(&mut self, other: $b) {
|
||||||
*self = *self - other;
|
*self = *self - other;
|
||||||
}
|
}
|
||||||
@ -32,7 +42,7 @@ macro_rules! assign_impl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
($a:ident *= $b:ident) => {
|
($a:ident *= $b:ident) => {
|
||||||
impl std::ops::MulAssign<$b> for $a {
|
impl ::core::ops::MulAssign<$b> for $a {
|
||||||
fn mul_assign(&mut self, other: $b) {
|
fn mul_assign(&mut self, other: $b) {
|
||||||
*self = *self * other;
|
*self = *self * other;
|
||||||
}
|
}
|
||||||
@ -40,7 +50,7 @@ macro_rules! assign_impl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
($a:ident /= $b:ident) => {
|
($a:ident /= $b:ident) => {
|
||||||
impl std::ops::DivAssign<$b> for $a {
|
impl ::core::ops::DivAssign<$b> for $a {
|
||||||
fn div_assign(&mut self, other: $b) {
|
fn div_assign(&mut self, other: $b) {
|
||||||
*self = *self / other;
|
*self = *self / other;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ impl Eval for ast::Space<'_> {
|
|||||||
type Output = Content;
|
type Output = Content;
|
||||||
|
|
||||||
fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
Ok(SpaceElem::new().pack())
|
Ok(SpaceElem::shared().clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ impl Eval for ast::Linebreak<'_> {
|
|||||||
type Output = Content;
|
type Output = Content;
|
||||||
|
|
||||||
fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
Ok(LinebreakElem::new().pack())
|
Ok(LinebreakElem::shared().clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ impl Eval for ast::Parbreak<'_> {
|
|||||||
type Output = Content;
|
type Output = Content;
|
||||||
|
|
||||||
fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
Ok(ParbreakElem::new().pack())
|
Ok(ParbreakElem::shared().clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ impl Eval for ast::MathAlignPoint<'_> {
|
|||||||
type Output = Content;
|
type Output = Content;
|
||||||
|
|
||||||
fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
Ok(AlignPointElem::new().pack())
|
Ok(AlignPointElem::shared().clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use crate::foundations::{
|
|||||||
Selector, Type, Value,
|
Selector, Type, Value,
|
||||||
};
|
};
|
||||||
use crate::syntax::{ast, Span, SyntaxNode};
|
use crate::syntax::{ast, Span, SyntaxNode};
|
||||||
use crate::utils::{LazyHash, Static};
|
use crate::utils::{singleton, LazyHash, Static};
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use typst_macros::func;
|
pub use typst_macros::func;
|
||||||
@ -216,11 +216,11 @@ impl Func {
|
|||||||
|
|
||||||
/// Get details about the function's return type.
|
/// Get details about the function's return type.
|
||||||
pub fn returns(&self) -> Option<&'static CastInfo> {
|
pub fn returns(&self) -> Option<&'static CastInfo> {
|
||||||
static CONTENT: Lazy<CastInfo> =
|
|
||||||
Lazy::new(|| CastInfo::Type(Type::of::<Content>()));
|
|
||||||
match &self.repr {
|
match &self.repr {
|
||||||
Repr::Native(native) => Some(&native.0.returns),
|
Repr::Native(native) => Some(&native.0.returns),
|
||||||
Repr::Element(_) => Some(&CONTENT),
|
Repr::Element(_) => {
|
||||||
|
Some(singleton!(CastInfo, CastInfo::Type(Type::of::<Content>())))
|
||||||
|
}
|
||||||
Repr::Closure(_) => None,
|
Repr::Closure(_) => None,
|
||||||
Repr::With(with) => with.0.returns(),
|
Repr::With(with) => with.0.returns(),
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,20 @@
|
|||||||
use crate::diag::SourceResult;
|
use crate::diag::SourceResult;
|
||||||
use crate::foundations::{elem, Packed, StyleChain};
|
use crate::foundations::{elem, Content, NativeElement, Packed, StyleChain};
|
||||||
use crate::layout::Abs;
|
use crate::layout::Abs;
|
||||||
use crate::math::{LayoutMath, MathContext, MathFragment, MathRun};
|
use crate::math::{LayoutMath, MathContext, MathFragment, MathRun};
|
||||||
|
use crate::utils::singleton;
|
||||||
|
|
||||||
/// A math alignment point: `&`, `&&`.
|
/// A math alignment point: `&`, `&&`.
|
||||||
#[elem(title = "Alignment Point", LayoutMath)]
|
#[elem(title = "Alignment Point", LayoutMath)]
|
||||||
pub struct AlignPointElem {}
|
pub struct AlignPointElem {}
|
||||||
|
|
||||||
|
impl AlignPointElem {
|
||||||
|
/// Get the globally shared alignment point element.
|
||||||
|
pub fn shared() -> &'static Content {
|
||||||
|
singleton!(Content, AlignPointElem::new().pack())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LayoutMath for Packed<AlignPointElem> {
|
impl LayoutMath for Packed<AlignPointElem> {
|
||||||
fn layout_math(&self, ctx: &mut MathContext, _: StyleChain) -> SourceResult<()> {
|
fn layout_math(&self, ctx: &mut MathContext, _: StyleChain) -> SourceResult<()> {
|
||||||
ctx.push(MathFragment::Align);
|
ctx.push(MathFragment::Align);
|
||||||
|
@ -331,7 +331,7 @@ impl Outlinable for Packed<HeadingElem> {
|
|||||||
styles,
|
styles,
|
||||||
numbering,
|
numbering,
|
||||||
)?;
|
)?;
|
||||||
content = numbers + SpaceElem::new().pack() + content;
|
content = numbers + SpaceElem::shared().clone() + content;
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(content))
|
Ok(Some(content))
|
||||||
|
@ -190,7 +190,7 @@ impl OutlineElem {
|
|||||||
impl Show for Packed<OutlineElem> {
|
impl Show for Packed<OutlineElem> {
|
||||||
#[typst_macros::time(name = "outline", span = self.span())]
|
#[typst_macros::time(name = "outline", span = self.span())]
|
||||||
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||||
let mut seq = vec![ParbreakElem::new().pack()];
|
let mut seq = vec![ParbreakElem::shared().clone()];
|
||||||
// Build the outline title.
|
// Build the outline title.
|
||||||
if let Some(title) = self.title(styles).unwrap_or_else(|| {
|
if let Some(title) = self.title(styles).unwrap_or_else(|| {
|
||||||
Some(TextElem::packed(Self::local_name_in(styles)).spanned(self.span()))
|
Some(TextElem::packed(Self::local_name_in(styles)).spanned(self.span()))
|
||||||
@ -247,12 +247,12 @@ impl Show for Packed<OutlineElem> {
|
|||||||
|
|
||||||
// Add the overridable outline entry, followed by a line break.
|
// Add the overridable outline entry, followed by a line break.
|
||||||
seq.push(entry.pack());
|
seq.push(entry.pack());
|
||||||
seq.push(LinebreakElem::new().pack());
|
seq.push(LinebreakElem::shared().clone());
|
||||||
|
|
||||||
ancestors.push(elem);
|
ancestors.push(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
seq.push(ParbreakElem::new().pack());
|
seq.push(ParbreakElem::shared().clone());
|
||||||
|
|
||||||
Ok(Content::sequence(seq))
|
Ok(Content::sequence(seq))
|
||||||
}
|
}
|
||||||
@ -325,13 +325,13 @@ impl OutlineIndent {
|
|||||||
numbering,
|
numbering,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
hidden += numbers + SpaceElem::new().pack();
|
hidden += numbers + SpaceElem::shared().clone();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ancestors.is_empty() {
|
if !ancestors.is_empty() {
|
||||||
seq.push(HideElem::new(hidden).pack());
|
seq.push(HideElem::new(hidden).pack());
|
||||||
seq.push(SpaceElem::new().pack());
|
seq.push(SpaceElem::shared().clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,7 +508,7 @@ impl Show for Packed<OutlineEntry> {
|
|||||||
|
|
||||||
// Add filler symbols between the section name and page number.
|
// Add filler symbols between the section name and page number.
|
||||||
if let Some(filler) = self.fill() {
|
if let Some(filler) = self.fill() {
|
||||||
seq.push(SpaceElem::new().pack());
|
seq.push(SpaceElem::shared().clone());
|
||||||
seq.push(
|
seq.push(
|
||||||
BoxElem::new()
|
BoxElem::new()
|
||||||
.with_body(Some(filler.clone()))
|
.with_body(Some(filler.clone()))
|
||||||
@ -516,7 +516,7 @@ impl Show for Packed<OutlineEntry> {
|
|||||||
.pack()
|
.pack()
|
||||||
.spanned(self.span()),
|
.spanned(self.span()),
|
||||||
);
|
);
|
||||||
seq.push(SpaceElem::new().pack());
|
seq.push(SpaceElem::shared().clone());
|
||||||
} else {
|
} else {
|
||||||
seq.push(HElem::new(Fr::one().into()).pack());
|
seq.push(HElem::new(Fr::one().into()).pack());
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ use crate::foundations::{
|
|||||||
};
|
};
|
||||||
use crate::layout::{Em, Length};
|
use crate::layout::{Em, Length};
|
||||||
use crate::realize::StyleVec;
|
use crate::realize::StyleVec;
|
||||||
|
use crate::utils::singleton;
|
||||||
|
|
||||||
/// Arranges text, spacing and inline-level elements into a paragraph.
|
/// Arranges text, spacing and inline-level elements into a paragraph.
|
||||||
///
|
///
|
||||||
@ -150,9 +151,9 @@ impl Construct for ParElem {
|
|||||||
let styles = Self::set(engine, args)?;
|
let styles = Self::set(engine, args)?;
|
||||||
let body = args.expect::<Content>("body")?;
|
let body = args.expect::<Content>("body")?;
|
||||||
Ok(Content::sequence([
|
Ok(Content::sequence([
|
||||||
ParbreakElem::new().pack(),
|
ParbreakElem::shared().clone(),
|
||||||
body.styled_with_map(styles),
|
body.styled_with_map(styles),
|
||||||
ParbreakElem::new().pack(),
|
ParbreakElem::shared().clone(),
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,4 +198,11 @@ pub enum Linebreaks {
|
|||||||
#[elem(title = "Paragraph Break", Unlabellable)]
|
#[elem(title = "Paragraph Break", Unlabellable)]
|
||||||
pub struct ParbreakElem {}
|
pub struct ParbreakElem {}
|
||||||
|
|
||||||
|
impl ParbreakElem {
|
||||||
|
/// Get the globally shared paragraph element.
|
||||||
|
pub fn shared() -> &'static Content {
|
||||||
|
singleton!(Content, ParbreakElem::new().pack())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Unlabellable for Packed<ParbreakElem> {}
|
impl Unlabellable for Packed<ParbreakElem> {}
|
||||||
|
@ -189,7 +189,7 @@ impl Show for Packed<QuoteElem> {
|
|||||||
.spanned(self.span());
|
.spanned(self.span());
|
||||||
|
|
||||||
if let Some(attribution) = self.attribution(styles).as_ref() {
|
if let Some(attribution) = self.attribution(styles).as_ref() {
|
||||||
let mut seq = vec![TextElem::packed('—'), SpaceElem::new().pack()];
|
let mut seq = vec![TextElem::packed('—'), SpaceElem::shared().clone()];
|
||||||
|
|
||||||
match attribution {
|
match attribution {
|
||||||
Attribution::Content(content) => {
|
Attribution::Content(content) => {
|
||||||
@ -213,7 +213,7 @@ impl Show for Packed<QuoteElem> {
|
|||||||
|
|
||||||
realized = PadElem::new(realized).pack();
|
realized = PadElem::new(realized).pack();
|
||||||
} else if let Some(Attribution::Label(label)) = self.attribution(styles) {
|
} else if let Some(Attribution::Label(label)) = self.attribution(styles) {
|
||||||
realized += SpaceElem::new().pack()
|
realized += SpaceElem::shared().clone()
|
||||||
+ CiteElem::new(*label).pack().spanned(self.span());
|
+ CiteElem::new(*label).pack().spanned(self.span());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::foundations::{elem, Packed};
|
use crate::foundations::{elem, Content, NativeElement, Packed};
|
||||||
use crate::realize::{Behave, Behaviour};
|
use crate::realize::{Behave, Behaviour};
|
||||||
|
use crate::utils::singleton;
|
||||||
|
|
||||||
/// Inserts a line break.
|
/// Inserts a line break.
|
||||||
///
|
///
|
||||||
@ -37,6 +38,13 @@ pub struct LinebreakElem {
|
|||||||
pub justify: bool,
|
pub justify: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LinebreakElem {
|
||||||
|
/// Get the globally shared linebreak element.
|
||||||
|
pub fn shared() -> &'static Content {
|
||||||
|
singleton!(Content, LinebreakElem::new().pack())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Behave for Packed<LinebreakElem> {
|
impl Behave for Packed<LinebreakElem> {
|
||||||
fn behaviour(&self) -> Behaviour {
|
fn behaviour(&self) -> Behaviour {
|
||||||
Behaviour::Destructive
|
Behaviour::Destructive
|
||||||
|
@ -440,7 +440,7 @@ impl Show for Packed<RawElem> {
|
|||||||
let mut seq = EcoVec::with_capacity((2 * lines.len()).saturating_sub(1));
|
let mut seq = EcoVec::with_capacity((2 * lines.len()).saturating_sub(1));
|
||||||
for (i, line) in lines.iter().enumerate() {
|
for (i, line) in lines.iter().enumerate() {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
seq.push(LinebreakElem::new().pack());
|
seq.push(LinebreakElem::shared().clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
seq.push(line.clone().pack());
|
seq.push(line.clone().pack());
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
use ecow::EcoString;
|
use ecow::EcoString;
|
||||||
|
|
||||||
use crate::foundations::{elem, Packed, PlainText, Repr, Unlabellable};
|
use crate::foundations::{
|
||||||
|
elem, Content, NativeElement, Packed, PlainText, Repr, Unlabellable,
|
||||||
|
};
|
||||||
use crate::realize::{Behave, Behaviour};
|
use crate::realize::{Behave, Behaviour};
|
||||||
|
use crate::utils::singleton;
|
||||||
|
|
||||||
/// A text space.
|
/// A text space.
|
||||||
#[elem(Behave, Unlabellable, PlainText, Repr)]
|
#[elem(Behave, Unlabellable, PlainText, Repr)]
|
||||||
pub struct SpaceElem {}
|
pub struct SpaceElem {}
|
||||||
|
|
||||||
|
impl SpaceElem {
|
||||||
|
/// Get the globally shared space element.
|
||||||
|
pub fn shared() -> &'static Content {
|
||||||
|
singleton!(Content, SpaceElem::new().pack())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Repr for SpaceElem {
|
impl Repr for SpaceElem {
|
||||||
fn repr(&self) -> EcoString {
|
fn repr(&self) -> EcoString {
|
||||||
"[ ]".into()
|
"[ ]".into()
|
||||||
|
@ -211,11 +211,7 @@ pub enum Color {
|
|||||||
#[scope]
|
#[scope]
|
||||||
impl Color {
|
impl Color {
|
||||||
/// The module of preset color maps.
|
/// The module of preset color maps.
|
||||||
pub const MAP: fn() -> Module = || {
|
pub const MAP: fn() -> Module = || crate::utils::singleton!(Module, map()).clone();
|
||||||
// Lazy to avoid re-allocating.
|
|
||||||
static MODULE: Lazy<Module> = Lazy::new(map);
|
|
||||||
MODULE.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const BLACK: Self = Self::Luma(Luma::new(0.0, 1.0));
|
pub const BLACK: Self = Self::Luma(Luma::new(0.0, 1.0));
|
||||||
pub const GRAY: Self = Self::Luma(Luma::new(0.6666666, 1.0));
|
pub const GRAY: Self = Self::Luma(Luma::new(0.6666666, 1.0));
|
||||||
|
@ -5,14 +5,13 @@ use std::io::Write;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use typst::diag::{bail, FileError, FileResult, StrResult};
|
use typst::diag::{bail, FileError, FileResult, StrResult};
|
||||||
use typst::foundations::{func, Bytes, Datetime, NoneValue, Repr, Smart, Value};
|
use typst::foundations::{func, Bytes, Datetime, NoneValue, Repr, Smart, Value};
|
||||||
use typst::layout::{Abs, Margin, PageElem};
|
use typst::layout::{Abs, Margin, PageElem};
|
||||||
use typst::syntax::{FileId, Source};
|
use typst::syntax::{FileId, Source};
|
||||||
use typst::text::{Font, FontBook, TextElem, TextSize};
|
use typst::text::{Font, FontBook, TextElem, TextSize};
|
||||||
use typst::utils::LazyHash;
|
use typst::utils::{singleton, LazyHash};
|
||||||
use typst::visualize::Color;
|
use typst::visualize::Color;
|
||||||
use typst::{Library, World};
|
use typst::{Library, World};
|
||||||
|
|
||||||
@ -29,8 +28,10 @@ impl TestWorld {
|
|||||||
/// This is cheap because the shared base for all test runs is lazily
|
/// This is cheap because the shared base for all test runs is lazily
|
||||||
/// initialized just once.
|
/// initialized just once.
|
||||||
pub fn new(source: Source) -> Self {
|
pub fn new(source: Source) -> Self {
|
||||||
static BASE: Lazy<TestBase> = Lazy::new(TestBase::default);
|
Self {
|
||||||
Self { main: source, base: &*BASE }
|
main: source,
|
||||||
|
base: singleton!(TestBase, TestBase::default()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user