mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Switch from Rc
to Arc
This commit is contained in:
parent
fa57d86ed9
commit
20b1a38414
@ -3,11 +3,11 @@ use std::convert::TryFrom;
|
|||||||
use std::fmt::{self, Debug, Formatter, Write};
|
use std::fmt::{self, Debug, Formatter, Write};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::ops::{Add, AddAssign};
|
use std::ops::{Add, AddAssign};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::Value;
|
use super::Value;
|
||||||
use crate::diag::StrResult;
|
use crate::diag::StrResult;
|
||||||
use crate::util::RcExt;
|
use crate::util::ArcExt;
|
||||||
|
|
||||||
/// Create a new [`Array`] from values.
|
/// Create a new [`Array`] from values.
|
||||||
#[allow(unused_macros)]
|
#[allow(unused_macros)]
|
||||||
@ -23,7 +23,7 @@ macro_rules! array {
|
|||||||
|
|
||||||
/// An array of values with clone-on-write value semantics.
|
/// An array of values with clone-on-write value semantics.
|
||||||
#[derive(Default, Clone, PartialEq)]
|
#[derive(Default, Clone, PartialEq)]
|
||||||
pub struct Array(Rc<Vec<Value>>);
|
pub struct Array(Arc<Vec<Value>>);
|
||||||
|
|
||||||
impl Array {
|
impl Array {
|
||||||
/// Create a new, empty array.
|
/// Create a new, empty array.
|
||||||
@ -33,7 +33,7 @@ impl Array {
|
|||||||
|
|
||||||
/// Create a new array from a vector of values.
|
/// Create a new array from a vector of values.
|
||||||
pub fn from_vec(vec: Vec<Value>) -> Self {
|
pub fn from_vec(vec: Vec<Value>) -> Self {
|
||||||
Self(Rc::new(vec))
|
Self(Arc::new(vec))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the array is empty.
|
/// Whether the array is empty.
|
||||||
@ -59,19 +59,19 @@ impl Array {
|
|||||||
let len = self.len();
|
let len = self.len();
|
||||||
usize::try_from(index)
|
usize::try_from(index)
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(move |i| Rc::make_mut(&mut self.0).get_mut(i))
|
.and_then(move |i| Arc::make_mut(&mut self.0).get_mut(i))
|
||||||
.ok_or_else(|| out_of_bounds(index, len))
|
.ok_or_else(|| out_of_bounds(index, len))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push a value to the end of the array.
|
/// Push a value to the end of the array.
|
||||||
pub fn push(&mut self, value: Value) {
|
pub fn push(&mut self, value: Value) {
|
||||||
Rc::make_mut(&mut self.0).push(value);
|
Arc::make_mut(&mut self.0).push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the array.
|
/// Clear the array.
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
if Rc::strong_count(&self.0) == 1 {
|
if Arc::strong_count(&self.0) == 1 {
|
||||||
Rc::make_mut(&mut self.0).clear();
|
Arc::make_mut(&mut self.0).clear();
|
||||||
} else {
|
} else {
|
||||||
*self = Self::new();
|
*self = Self::new();
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ impl Array {
|
|||||||
/// Returns an error if two values could not be compared.
|
/// Returns an error if two values could not be compared.
|
||||||
pub fn sorted(mut self) -> StrResult<Self> {
|
pub fn sorted(mut self) -> StrResult<Self> {
|
||||||
let mut result = Ok(());
|
let mut result = Ok(());
|
||||||
Rc::make_mut(&mut self.0).sort_by(|a, b| {
|
Arc::make_mut(&mut self.0).sort_by(|a, b| {
|
||||||
a.partial_cmp(b).unwrap_or_else(|| {
|
a.partial_cmp(b).unwrap_or_else(|| {
|
||||||
if result.is_ok() {
|
if result.is_ok() {
|
||||||
result = Err(format!(
|
result = Err(format!(
|
||||||
@ -146,7 +146,7 @@ impl Add for Array {
|
|||||||
|
|
||||||
impl AddAssign for Array {
|
impl AddAssign for Array {
|
||||||
fn add_assign(&mut self, rhs: Array) {
|
fn add_assign(&mut self, rhs: Array) {
|
||||||
match Rc::try_unwrap(rhs.0) {
|
match Arc::try_unwrap(rhs.0) {
|
||||||
Ok(vec) => self.extend(vec),
|
Ok(vec) => self.extend(vec),
|
||||||
Err(rc) => self.extend(rc.iter().cloned()),
|
Err(rc) => self.extend(rc.iter().cloned()),
|
||||||
}
|
}
|
||||||
@ -155,13 +155,13 @@ impl AddAssign for Array {
|
|||||||
|
|
||||||
impl Extend<Value> for Array {
|
impl Extend<Value> for Array {
|
||||||
fn extend<T: IntoIterator<Item = Value>>(&mut self, iter: T) {
|
fn extend<T: IntoIterator<Item = Value>>(&mut self, iter: T) {
|
||||||
Rc::make_mut(&mut self.0).extend(iter);
|
Arc::make_mut(&mut self.0).extend(iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromIterator<Value> for Array {
|
impl FromIterator<Value> for Array {
|
||||||
fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
|
fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
|
||||||
Self(Rc::new(iter.into_iter().collect()))
|
Self(Arc::new(iter.into_iter().collect()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ impl IntoIterator for Array {
|
|||||||
type IntoIter = std::vec::IntoIter<Value>;
|
type IntoIter = std::vec::IntoIter<Value>;
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
Rc::take(self.0).into_iter()
|
Arc::take(self.0).into_iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{Scope, Scopes, Value};
|
use super::{Scope, Scopes, Value};
|
||||||
use crate::syntax::ast::{ClosureParam, Expr, Ident, Imports, TypedNode};
|
use crate::syntax::ast::{ClosureParam, Expr, Ident, Imports, TypedNode};
|
||||||
@ -35,7 +35,7 @@ impl<'a> CapturesVisitor<'a> {
|
|||||||
pub fn capture(&mut self, ident: Ident) {
|
pub fn capture(&mut self, ident: Ident) {
|
||||||
if self.internal.get(&ident).is_none() {
|
if self.internal.get(&ident).is_none() {
|
||||||
if let Some(slot) = self.external.get(&ident) {
|
if let Some(slot) = self.external.get(&ident) {
|
||||||
self.captures.def_slot(ident.take(), Rc::clone(slot));
|
self.captures.def_slot(ident.take(), Arc::clone(slot));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ use std::collections::BTreeMap;
|
|||||||
use std::fmt::{self, Debug, Formatter, Write};
|
use std::fmt::{self, Debug, Formatter, Write};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::ops::{Add, AddAssign};
|
use std::ops::{Add, AddAssign};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::Value;
|
use super::Value;
|
||||||
use crate::diag::StrResult;
|
use crate::diag::StrResult;
|
||||||
use crate::util::{EcoString, RcExt};
|
use crate::util::{ArcExt, EcoString};
|
||||||
|
|
||||||
/// Create a new [`Dict`] from key-value pairs.
|
/// Create a new [`Dict`] from key-value pairs.
|
||||||
#[allow(unused_macros)]
|
#[allow(unused_macros)]
|
||||||
@ -21,7 +21,7 @@ macro_rules! dict {
|
|||||||
|
|
||||||
/// A dictionary from strings to values with clone-on-write value semantics.
|
/// A dictionary from strings to values with clone-on-write value semantics.
|
||||||
#[derive(Default, Clone, PartialEq)]
|
#[derive(Default, Clone, PartialEq)]
|
||||||
pub struct Dict(Rc<BTreeMap<EcoString, Value>>);
|
pub struct Dict(Arc<BTreeMap<EcoString, Value>>);
|
||||||
|
|
||||||
impl Dict {
|
impl Dict {
|
||||||
/// Create a new, empty dictionary.
|
/// Create a new, empty dictionary.
|
||||||
@ -31,7 +31,7 @@ impl Dict {
|
|||||||
|
|
||||||
/// Create a new dictionary from a mapping of strings to values.
|
/// Create a new dictionary from a mapping of strings to values.
|
||||||
pub fn from_map(map: BTreeMap<EcoString, Value>) -> Self {
|
pub fn from_map(map: BTreeMap<EcoString, Value>) -> Self {
|
||||||
Self(Rc::new(map))
|
Self(Arc::new(map))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the dictionary is empty.
|
/// Whether the dictionary is empty.
|
||||||
@ -54,18 +54,18 @@ impl Dict {
|
|||||||
/// This inserts the key with [`None`](Value::None) as the value if not
|
/// This inserts the key with [`None`](Value::None) as the value if not
|
||||||
/// present so far.
|
/// present so far.
|
||||||
pub fn get_mut(&mut self, key: EcoString) -> &mut Value {
|
pub fn get_mut(&mut self, key: EcoString) -> &mut Value {
|
||||||
Rc::make_mut(&mut self.0).entry(key).or_default()
|
Arc::make_mut(&mut self.0).entry(key).or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a mapping from the given `key` to the given `value`.
|
/// Insert a mapping from the given `key` to the given `value`.
|
||||||
pub fn insert(&mut self, key: EcoString, value: Value) {
|
pub fn insert(&mut self, key: EcoString, value: Value) {
|
||||||
Rc::make_mut(&mut self.0).insert(key, value);
|
Arc::make_mut(&mut self.0).insert(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the dictionary.
|
/// Clear the dictionary.
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
if Rc::strong_count(&self.0) == 1 {
|
if Arc::strong_count(&self.0) == 1 {
|
||||||
Rc::make_mut(&mut self.0).clear();
|
Arc::make_mut(&mut self.0).clear();
|
||||||
} else {
|
} else {
|
||||||
*self = Self::new();
|
*self = Self::new();
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ impl Add for Dict {
|
|||||||
|
|
||||||
impl AddAssign for Dict {
|
impl AddAssign for Dict {
|
||||||
fn add_assign(&mut self, rhs: Dict) {
|
fn add_assign(&mut self, rhs: Dict) {
|
||||||
match Rc::try_unwrap(rhs.0) {
|
match Arc::try_unwrap(rhs.0) {
|
||||||
Ok(map) => self.extend(map),
|
Ok(map) => self.extend(map),
|
||||||
Err(rc) => self.extend(rc.iter().map(|(k, v)| (k.clone(), v.clone()))),
|
Err(rc) => self.extend(rc.iter().map(|(k, v)| (k.clone(), v.clone()))),
|
||||||
}
|
}
|
||||||
@ -121,13 +121,13 @@ impl AddAssign for Dict {
|
|||||||
|
|
||||||
impl Extend<(EcoString, Value)> for Dict {
|
impl Extend<(EcoString, Value)> for Dict {
|
||||||
fn extend<T: IntoIterator<Item = (EcoString, Value)>>(&mut self, iter: T) {
|
fn extend<T: IntoIterator<Item = (EcoString, Value)>>(&mut self, iter: T) {
|
||||||
Rc::make_mut(&mut self.0).extend(iter);
|
Arc::make_mut(&mut self.0).extend(iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromIterator<(EcoString, Value)> for Dict {
|
impl FromIterator<(EcoString, Value)> for Dict {
|
||||||
fn from_iter<T: IntoIterator<Item = (EcoString, Value)>>(iter: T) -> Self {
|
fn from_iter<T: IntoIterator<Item = (EcoString, Value)>>(iter: T) -> Self {
|
||||||
Self(Rc::new(iter.into_iter().collect()))
|
Self(Arc::new(iter.into_iter().collect()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ impl IntoIterator for Dict {
|
|||||||
type IntoIter = std::collections::btree_map::IntoIter<EcoString, Value>;
|
type IntoIter = std::collections::btree_map::IntoIter<EcoString, Value>;
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
Rc::take(self.0).into_iter()
|
Arc::take(self.0).into_iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::fmt::{self, Debug, Formatter, Write};
|
use std::fmt::{self, Debug, Formatter, Write};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{Cast, EvalContext, Value};
|
use super::{Cast, EvalContext, Value};
|
||||||
use crate::diag::{At, TypResult};
|
use crate::diag::{At, TypResult};
|
||||||
@ -8,9 +8,9 @@ use crate::util::EcoString;
|
|||||||
|
|
||||||
/// An evaluatable function.
|
/// An evaluatable function.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Function(Rc<Inner<Func>>);
|
pub struct Function(Arc<Inner<Func>>);
|
||||||
|
|
||||||
/// The unsized structure behind the [`Rc`].
|
/// The unsized structure behind the [`Arc`].
|
||||||
struct Inner<T: ?Sized> {
|
struct Inner<T: ?Sized> {
|
||||||
name: Option<EcoString>,
|
name: Option<EcoString>,
|
||||||
func: T,
|
func: T,
|
||||||
@ -24,7 +24,7 @@ impl Function {
|
|||||||
where
|
where
|
||||||
F: Fn(&mut EvalContext, &mut Args) -> TypResult<Value> + 'static,
|
F: Fn(&mut EvalContext, &mut Args) -> TypResult<Value> + 'static,
|
||||||
{
|
{
|
||||||
Self(Rc::new(Inner { name, func }))
|
Self(Arc::new(Inner { name, func }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The name of the function.
|
/// The name of the function.
|
||||||
@ -53,8 +53,8 @@ impl PartialEq for Function {
|
|||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
// We cast to thin pointers for comparison.
|
// We cast to thin pointers for comparison.
|
||||||
std::ptr::eq(
|
std::ptr::eq(
|
||||||
Rc::as_ptr(&self.0) as *const (),
|
Arc::as_ptr(&self.0) as *const (),
|
||||||
Rc::as_ptr(&other.0) as *const (),
|
Arc::as_ptr(&other.0) as *const (),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ impl Node {
|
|||||||
/// Create an inline-level node.
|
/// Create an inline-level node.
|
||||||
pub fn inline<T>(node: T) -> Self
|
pub fn inline<T>(node: T) -> Self
|
||||||
where
|
where
|
||||||
T: Layout + Debug + Hash + 'static,
|
T: Layout + Debug + Hash + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
Self::Inline(node.pack())
|
Self::Inline(node.pack())
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ impl Node {
|
|||||||
/// Create a block-level node.
|
/// Create a block-level node.
|
||||||
pub fn block<T>(node: T) -> Self
|
pub fn block<T>(node: T) -> Self
|
||||||
where
|
where
|
||||||
T: Layout + Debug + Hash + 'static,
|
T: Layout + Debug + Hash + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
Self::Block(node.pack())
|
Self::Block(node.pack())
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,14 @@ use std::cell::RefCell;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{Args, Class, Construct, EvalContext, Function, Set, Value};
|
use super::{Args, Class, Construct, EvalContext, Function, Set, Value};
|
||||||
use crate::diag::TypResult;
|
use crate::diag::TypResult;
|
||||||
use crate::util::EcoString;
|
use crate::util::EcoString;
|
||||||
|
|
||||||
/// A slot where a variable is stored.
|
/// A slot where a variable is stored.
|
||||||
pub type Slot = Rc<RefCell<Value>>;
|
pub type Slot = Arc<RefCell<Value>>;
|
||||||
|
|
||||||
/// A stack of scopes.
|
/// A stack of scopes.
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
@ -85,12 +85,12 @@ impl Scope {
|
|||||||
// FIXME: Use Ref::leak once stable.
|
// FIXME: Use Ref::leak once stable.
|
||||||
std::mem::forget(cell.borrow());
|
std::mem::forget(cell.borrow());
|
||||||
|
|
||||||
self.values.insert(var.into(), Rc::new(cell));
|
self.values.insert(var.into(), Arc::new(cell));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define a mutable variable with a value.
|
/// Define a mutable variable with a value.
|
||||||
pub fn def_mut(&mut self, var: impl Into<EcoString>, value: impl Into<Value>) {
|
pub fn def_mut(&mut self, var: impl Into<EcoString>, value: impl Into<Value>) {
|
||||||
self.values.insert(var.into(), Rc::new(RefCell::new(value.into())));
|
self.values.insert(var.into(), Arc::new(RefCell::new(value.into())));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define a variable with a slot.
|
/// Define a variable with a slot.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::any::{Any, TypeId};
|
use std::any::{Any, TypeId};
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
// TODO(style): Possible optimizations:
|
// TODO(style): Possible optimizations:
|
||||||
// - Ref-count map for cheaper cloning and smaller footprint
|
// - Ref-count map for cheaper cloning and smaller footprint
|
||||||
@ -334,13 +334,13 @@ impl Debug for Link<'_> {
|
|||||||
/// An entry for a single style property.
|
/// An entry for a single style property.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Entry {
|
struct Entry {
|
||||||
p: Rc<dyn Bounds>,
|
p: Arc<dyn Bounds>,
|
||||||
scoped: bool,
|
scoped: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entry {
|
impl Entry {
|
||||||
fn new<P: Property>(key: P, value: P::Value) -> Self {
|
fn new<P: Property>(key: P, value: P::Value) -> Self {
|
||||||
Self { p: Rc::new((key, value)), scoped: false }
|
Self { p: Arc::new((key, value)), scoped: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is<P: Property>(&self) -> bool {
|
fn is<P: Property>(&self) -> bool {
|
||||||
@ -390,11 +390,11 @@ impl Hash for Entry {
|
|||||||
///
|
///
|
||||||
/// This trait is not intended to be implemented manually, but rather through
|
/// This trait is not intended to be implemented manually, but rather through
|
||||||
/// the `#[properties]` proc-macro.
|
/// the `#[properties]` proc-macro.
|
||||||
pub trait Property: Copy + 'static {
|
pub trait Property: Copy + Sync + Send + 'static {
|
||||||
/// The type of value that is returned when getting this property from a
|
/// The type of value that is returned when getting this property from a
|
||||||
/// style map. For example, this could be [`Length`](crate::geom::Length)
|
/// style map. For example, this could be [`Length`](crate::geom::Length)
|
||||||
/// for a `WIDTH` property.
|
/// for a `WIDTH` property.
|
||||||
type Value: Debug + Clone + PartialEq + Hash + 'static;
|
type Value: Debug + Clone + PartialEq + Hash + Sync + Send + 'static;
|
||||||
|
|
||||||
/// The name of the property, used for debug printing.
|
/// The name of the property, used for debug printing.
|
||||||
const NAME: &'static str;
|
const NAME: &'static str;
|
||||||
@ -432,7 +432,7 @@ pub trait Nonfolding {}
|
|||||||
/// value types below. Although it is zero-sized, the property `P` must be part
|
/// value types below. Although it is zero-sized, the property `P` must be part
|
||||||
/// of the implementing type so that we can use it in the methods (it must be a
|
/// of the implementing type so that we can use it in the methods (it must be a
|
||||||
/// constrained type parameter).
|
/// constrained type parameter).
|
||||||
trait Bounds: 'static {
|
trait Bounds: Sync + Send + 'static {
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
fn dyn_fmt(&self, f: &mut Formatter) -> fmt::Result;
|
fn dyn_fmt(&self, f: &mut Formatter) -> fmt::Result;
|
||||||
fn dyn_eq(&self, other: &Entry) -> bool;
|
fn dyn_eq(&self, other: &Entry) -> bool;
|
||||||
|
@ -2,7 +2,7 @@ use std::any::Any;
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{ops, Args, Array, Class, Dict, Function, Node};
|
use super::{ops, Args, Array, Class, Dict, Function, Node};
|
||||||
use crate::diag::StrResult;
|
use crate::diag::StrResult;
|
||||||
@ -58,7 +58,7 @@ impl Value {
|
|||||||
/// Create an inline-level node value.
|
/// Create an inline-level node value.
|
||||||
pub fn inline<T>(node: T) -> Self
|
pub fn inline<T>(node: T) -> Self
|
||||||
where
|
where
|
||||||
T: Layout + Debug + Hash + 'static,
|
T: Layout + Debug + Hash + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
Self::Node(Node::inline(node))
|
Self::Node(Node::inline(node))
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ impl Value {
|
|||||||
/// Create a block-level node value.
|
/// Create a block-level node value.
|
||||||
pub fn block<T>(node: T) -> Self
|
pub fn block<T>(node: T) -> Self
|
||||||
where
|
where
|
||||||
T: Layout + Debug + Hash + 'static,
|
T: Layout + Debug + Hash + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
Self::Node(Node::block(node))
|
Self::Node(Node::block(node))
|
||||||
}
|
}
|
||||||
@ -211,15 +211,15 @@ impl From<Dynamic> for Value {
|
|||||||
|
|
||||||
/// A dynamic value.
|
/// A dynamic value.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Dynamic(Rc<dyn Bounds>);
|
pub struct Dynamic(Arc<dyn Bounds>);
|
||||||
|
|
||||||
impl Dynamic {
|
impl Dynamic {
|
||||||
/// Create a new instance from any value that satisifies the required bounds.
|
/// Create a new instance from any value that satisifies the required bounds.
|
||||||
pub fn new<T>(any: T) -> Self
|
pub fn new<T>(any: T) -> Self
|
||||||
where
|
where
|
||||||
T: Type + Debug + PartialEq + 'static,
|
T: Type + Debug + PartialEq + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
Self(Rc::new(any))
|
Self(Arc::new(any))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the wrapped type is `T`.
|
/// Whether the wrapped type is `T`.
|
||||||
@ -250,7 +250,7 @@ impl PartialEq for Dynamic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Bounds: Debug + 'static {
|
trait Bounds: Debug + Sync + Send + 'static {
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
fn dyn_eq(&self, other: &Dynamic) -> bool;
|
fn dyn_eq(&self, other: &Dynamic) -> bool;
|
||||||
fn dyn_type_name(&self) -> &'static str;
|
fn dyn_type_name(&self) -> &'static str;
|
||||||
@ -258,7 +258,7 @@ trait Bounds: Debug + 'static {
|
|||||||
|
|
||||||
impl<T> Bounds for T
|
impl<T> Bounds for T
|
||||||
where
|
where
|
||||||
T: Type + Debug + PartialEq + 'static,
|
T: Type + Debug + PartialEq + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use std::cmp::Eq;
|
use std::cmp::Eq;
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use image::{DynamicImage, GenericImageView, ImageFormat, ImageResult, Rgba};
|
use image::{DynamicImage, GenericImageView, ImageFormat, ImageResult, Rgba};
|
||||||
use pdf_writer::types::{
|
use pdf_writer::types::{
|
||||||
@ -26,7 +26,7 @@ use crate::Context;
|
|||||||
/// included in the PDF.
|
/// included in the PDF.
|
||||||
///
|
///
|
||||||
/// Returns the raw bytes making up the PDF file.
|
/// Returns the raw bytes making up the PDF file.
|
||||||
pub fn pdf(ctx: &Context, frames: &[Rc<Frame>]) -> Vec<u8> {
|
pub fn pdf(ctx: &Context, frames: &[Arc<Frame>]) -> Vec<u8> {
|
||||||
PdfExporter::new(ctx).export(frames)
|
PdfExporter::new(ctx).export(frames)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,14 +60,14 @@ impl<'a> PdfExporter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn export(mut self, frames: &[Rc<Frame>]) -> Vec<u8> {
|
fn export(mut self, frames: &[Arc<Frame>]) -> Vec<u8> {
|
||||||
self.build_pages(frames);
|
self.build_pages(frames);
|
||||||
self.write_fonts();
|
self.write_fonts();
|
||||||
self.write_images();
|
self.write_images();
|
||||||
self.write_structure()
|
self.write_structure()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_pages(&mut self, frames: &[Rc<Frame>]) {
|
fn build_pages(&mut self, frames: &[Arc<Frame>]) {
|
||||||
for frame in frames {
|
for frame in frames {
|
||||||
let page = PageExporter::new(self).export(frame);
|
let page = PageExporter::new(self).export(frame);
|
||||||
self.pages.push(page);
|
self.pages.push(page);
|
||||||
|
20
src/font.rs
20
src/font.rs
@ -3,7 +3,7 @@
|
|||||||
use std::collections::{hash_map::Entry, BTreeMap, HashMap};
|
use std::collections::{hash_map::Entry, BTreeMap, HashMap};
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ttf_parser::{name_id, GlyphId, PlatformId};
|
use ttf_parser::{name_id, GlyphId, PlatformId};
|
||||||
@ -33,15 +33,15 @@ impl FaceId {
|
|||||||
|
|
||||||
/// Storage for loaded and parsed font faces.
|
/// Storage for loaded and parsed font faces.
|
||||||
pub struct FontStore {
|
pub struct FontStore {
|
||||||
loader: Rc<dyn Loader>,
|
loader: Arc<dyn Loader>,
|
||||||
faces: Vec<Option<Face>>,
|
faces: Vec<Option<Face>>,
|
||||||
families: BTreeMap<String, Vec<FaceId>>,
|
families: BTreeMap<String, Vec<FaceId>>,
|
||||||
buffers: HashMap<FileHash, Rc<Vec<u8>>>,
|
buffers: HashMap<FileHash, Arc<Vec<u8>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontStore {
|
impl FontStore {
|
||||||
/// Create a new, empty font store.
|
/// Create a new, empty font store.
|
||||||
pub fn new(loader: Rc<dyn Loader>) -> Self {
|
pub fn new(loader: Arc<dyn Loader>) -> Self {
|
||||||
let mut faces = vec![];
|
let mut faces = vec![];
|
||||||
let mut families = BTreeMap::<String, Vec<FaceId>>::new();
|
let mut families = BTreeMap::<String, Vec<FaceId>>::new();
|
||||||
|
|
||||||
@ -109,11 +109,11 @@ impl FontStore {
|
|||||||
Entry::Occupied(entry) => entry.into_mut(),
|
Entry::Occupied(entry) => entry.into_mut(),
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
let buffer = self.loader.load(path).ok()?;
|
let buffer = self.loader.load(path).ok()?;
|
||||||
entry.insert(Rc::new(buffer))
|
entry.insert(Arc::new(buffer))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let face = Face::new(Rc::clone(buffer), index)?;
|
let face = Face::new(Arc::clone(buffer), index)?;
|
||||||
*slot = Some(face);
|
*slot = Some(face);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ pub struct Face {
|
|||||||
/// The raw face data, possibly shared with other faces from the same
|
/// The raw face data, possibly shared with other faces from the same
|
||||||
/// collection. Must stay alive put, because `ttf` points into it using
|
/// collection. Must stay alive put, because `ttf` points into it using
|
||||||
/// unsafe code.
|
/// unsafe code.
|
||||||
buffer: Rc<Vec<u8>>,
|
buffer: Arc<Vec<u8>>,
|
||||||
/// The face's index in the collection (zero if not a collection).
|
/// The face's index in the collection (zero if not a collection).
|
||||||
index: u32,
|
index: u32,
|
||||||
/// The underlying ttf-parser/rustybuzz face.
|
/// The underlying ttf-parser/rustybuzz face.
|
||||||
@ -182,11 +182,11 @@ pub struct LineMetrics {
|
|||||||
|
|
||||||
impl Face {
|
impl Face {
|
||||||
/// Parse a font face from a buffer and collection index.
|
/// Parse a font face from a buffer and collection index.
|
||||||
pub fn new(buffer: Rc<Vec<u8>>, index: u32) -> Option<Self> {
|
pub fn new(buffer: Arc<Vec<u8>>, index: u32) -> Option<Self> {
|
||||||
// Safety:
|
// Safety:
|
||||||
// - The slices's location is stable in memory:
|
// - The slices's location is stable in memory:
|
||||||
// - We don't move the underlying vector
|
// - We don't move the underlying vector
|
||||||
// - Nobody else can move it since we have a strong ref to the `Rc`.
|
// - Nobody else can move it since we have a strong ref to the `Arc`.
|
||||||
// - The internal static lifetime is not leaked because its rewritten
|
// - The internal static lifetime is not leaked because its rewritten
|
||||||
// to the self-lifetime in `ttf()`.
|
// to the self-lifetime in `ttf()`.
|
||||||
let slice: &'static [u8] =
|
let slice: &'static [u8] =
|
||||||
@ -238,7 +238,7 @@ impl Face {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The underlying buffer.
|
/// The underlying buffer.
|
||||||
pub fn buffer(&self) -> &Rc<Vec<u8>> {
|
pub fn buffer(&self) -> &Arc<Vec<u8>> {
|
||||||
&self.buffer
|
&self.buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
src/frame.rs
10
src/frame.rs
@ -1,7 +1,7 @@
|
|||||||
//! Finished layouts.
|
//! Finished layouts.
|
||||||
|
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::font::FaceId;
|
use crate::font::FaceId;
|
||||||
use crate::geom::{Align, Em, Length, Paint, Path, Point, Size, Spec, Transform};
|
use crate::geom::{Align, Em, Length, Paint, Path, Point, Size, Spec, Transform};
|
||||||
@ -43,7 +43,7 @@ impl Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add a group element.
|
/// Add a group element.
|
||||||
pub fn push_frame(&mut self, pos: Point, frame: Rc<Self>) {
|
pub fn push_frame(&mut self, pos: Point, frame: Arc<Self>) {
|
||||||
self.elements.push((pos, Element::Group(Group::new(frame))));
|
self.elements.push((pos, Element::Group(Group::new(frame))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ impl Frame {
|
|||||||
F: FnOnce(&mut Group),
|
F: FnOnce(&mut Group),
|
||||||
{
|
{
|
||||||
let mut wrapper = Frame { elements: vec![], ..*self };
|
let mut wrapper = Frame { elements: vec![], ..*self };
|
||||||
let mut group = Group::new(Rc::new(std::mem::take(self)));
|
let mut group = Group::new(Arc::new(std::mem::take(self)));
|
||||||
f(&mut group);
|
f(&mut group);
|
||||||
wrapper.push(Point::zero(), Element::Group(group));
|
wrapper.push(Point::zero(), Element::Group(group));
|
||||||
*self = wrapper;
|
*self = wrapper;
|
||||||
@ -149,7 +149,7 @@ pub enum Element {
|
|||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct Group {
|
pub struct Group {
|
||||||
/// The group's frame.
|
/// The group's frame.
|
||||||
pub frame: Rc<Frame>,
|
pub frame: Arc<Frame>,
|
||||||
/// A transformation to apply to the group.
|
/// A transformation to apply to the group.
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
/// Whether the frame should be a clipping boundary.
|
/// Whether the frame should be a clipping boundary.
|
||||||
@ -158,7 +158,7 @@ pub struct Group {
|
|||||||
|
|
||||||
impl Group {
|
impl Group {
|
||||||
/// Create a new group with default settings.
|
/// Create a new group with default settings.
|
||||||
pub fn new(frame: Rc<Frame>) -> Self {
|
pub fn new(frame: Arc<Frame>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
frame,
|
frame,
|
||||||
transform: Transform::identity(),
|
transform: Transform::identity(),
|
||||||
|
@ -5,7 +5,7 @@ use std::ffi::OsStr;
|
|||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use image::io::Reader as ImageReader;
|
use image::io::Reader as ImageReader;
|
||||||
use image::{DynamicImage, GenericImageView, ImageFormat};
|
use image::{DynamicImage, GenericImageView, ImageFormat};
|
||||||
@ -33,14 +33,14 @@ impl ImageId {
|
|||||||
|
|
||||||
/// Storage for loaded and decoded images.
|
/// Storage for loaded and decoded images.
|
||||||
pub struct ImageStore {
|
pub struct ImageStore {
|
||||||
loader: Rc<dyn Loader>,
|
loader: Arc<dyn Loader>,
|
||||||
files: HashMap<FileHash, ImageId>,
|
files: HashMap<FileHash, ImageId>,
|
||||||
images: Vec<Image>,
|
images: Vec<Image>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageStore {
|
impl ImageStore {
|
||||||
/// Create a new, empty image store.
|
/// Create a new, empty image store.
|
||||||
pub fn new(loader: Rc<dyn Loader>) -> Self {
|
pub fn new(loader: Arc<dyn Loader>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
loader,
|
loader,
|
||||||
files: HashMap::new(),
|
files: HashMap::new(),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::Regions;
|
use super::Regions;
|
||||||
use crate::frame::Frame;
|
use crate::frame::Frame;
|
||||||
@ -7,12 +7,12 @@ use crate::geom::{Length, Size, Spec};
|
|||||||
/// Constrain a frame with constraints.
|
/// Constrain a frame with constraints.
|
||||||
pub trait Constrain {
|
pub trait Constrain {
|
||||||
/// Reference-count the frame and wrap it with constraints.
|
/// Reference-count the frame and wrap it with constraints.
|
||||||
fn constrain(self, cts: Constraints) -> Constrained<Rc<Frame>>;
|
fn constrain(self, cts: Constraints) -> Constrained<Arc<Frame>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Constrain for Frame {
|
impl Constrain for Frame {
|
||||||
fn constrain(self, cts: Constraints) -> Constrained<Rc<Frame>> {
|
fn constrain(self, cts: Constraints) -> Constrained<Arc<Frame>> {
|
||||||
Constrained::new(Rc::new(self), cts)
|
Constrained::new(Arc::new(self), cts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::cmp::Reverse;
|
use std::cmp::Reverse;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ impl LayoutCache {
|
|||||||
&mut self,
|
&mut self,
|
||||||
hash: u64,
|
hash: u64,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
) -> Option<Vec<Constrained<Rc<Frame>>>> {
|
) -> Option<Vec<Constrained<Arc<Frame>>>> {
|
||||||
self.frames
|
self.frames
|
||||||
.get_mut(&hash)?
|
.get_mut(&hash)?
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
@ -193,7 +193,7 @@ impl LayoutCache {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FramesEntry {
|
pub struct FramesEntry {
|
||||||
/// The cached frames for a node.
|
/// The cached frames for a node.
|
||||||
frames: Vec<Constrained<Rc<Frame>>>,
|
frames: Vec<Constrained<Arc<Frame>>>,
|
||||||
/// How nested the frame was in the context is was originally appearing in.
|
/// How nested the frame was in the context is was originally appearing in.
|
||||||
level: usize,
|
level: usize,
|
||||||
/// For how long the element already exists.
|
/// For how long the element already exists.
|
||||||
@ -209,7 +209,7 @@ pub struct FramesEntry {
|
|||||||
|
|
||||||
impl FramesEntry {
|
impl FramesEntry {
|
||||||
/// Construct a new instance.
|
/// Construct a new instance.
|
||||||
pub fn new(frames: Vec<Constrained<Rc<Frame>>>, level: usize) -> Self {
|
pub fn new(frames: Vec<Constrained<Arc<Frame>>>, level: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
frames,
|
frames,
|
||||||
level,
|
level,
|
||||||
@ -222,7 +222,7 @@ impl FramesEntry {
|
|||||||
|
|
||||||
/// Checks if the cached frames are valid in the given regions and returns
|
/// Checks if the cached frames are valid in the given regions and returns
|
||||||
/// them if so.
|
/// them if so.
|
||||||
pub fn lookup(&mut self, regions: &Regions) -> Option<Vec<Constrained<Rc<Frame>>>> {
|
pub fn lookup(&mut self, regions: &Regions) -> Option<Vec<Constrained<Arc<Frame>>>> {
|
||||||
self.check(regions).then(|| {
|
self.check(regions).then(|| {
|
||||||
self.temperature[0] = self.temperature[0].saturating_add(1);
|
self.temperature[0] = self.temperature[0].saturating_add(1);
|
||||||
self.frames.clone()
|
self.frames.clone()
|
||||||
@ -396,9 +396,9 @@ mod tests {
|
|||||||
use crate::geom::{Size, Spec};
|
use crate::geom::{Size, Spec};
|
||||||
use crate::layout::Constraints;
|
use crate::layout::Constraints;
|
||||||
|
|
||||||
fn empty_frames() -> Vec<Constrained<Rc<Frame>>> {
|
fn empty_frames() -> Vec<Constrained<Arc<Frame>>> {
|
||||||
vec![Constrained {
|
vec![Constrained {
|
||||||
item: Rc::new(Frame::default()),
|
item: Arc::new(Frame::default()),
|
||||||
cts: Constraints::new(Spec::splat(false)),
|
cts: Constraints::new(Spec::splat(false)),
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ pub use regions::*;
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::eval::{StyleChain, Styled};
|
use crate::eval::{StyleChain, Styled};
|
||||||
use crate::font::FontStore;
|
use crate::font::FontStore;
|
||||||
@ -29,7 +29,7 @@ pub struct RootNode(pub Vec<Styled<PageNode>>);
|
|||||||
|
|
||||||
impl RootNode {
|
impl RootNode {
|
||||||
/// Layout the document into a sequence of frames, one per page.
|
/// Layout the document into a sequence of frames, one per page.
|
||||||
pub fn layout(&self, ctx: &mut Context) -> Vec<Rc<Frame>> {
|
pub fn layout(&self, ctx: &mut Context) -> Vec<Arc<Frame>> {
|
||||||
let (mut ctx, styles) = LayoutContext::new(ctx);
|
let (mut ctx, styles) = LayoutContext::new(ctx);
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
@ -56,17 +56,17 @@ pub trait Layout {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>>;
|
) -> Vec<Constrained<Arc<Frame>>>;
|
||||||
|
|
||||||
/// Convert to a packed node.
|
/// Convert to a packed node.
|
||||||
fn pack(self) -> PackedNode
|
fn pack(self) -> PackedNode
|
||||||
where
|
where
|
||||||
Self: Debug + Hash + Sized + 'static,
|
Self: Debug + Hash + Sized + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
PackedNode {
|
PackedNode {
|
||||||
#[cfg(feature = "layout-cache")]
|
#[cfg(feature = "layout-cache")]
|
||||||
hash: self.hash64(),
|
hash: self.hash64(),
|
||||||
node: Rc::new(self),
|
node: Arc::new(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ impl Layout for EmptyNode {
|
|||||||
_: &mut LayoutContext,
|
_: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
_: StyleChain,
|
_: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let size = regions.expand.select(regions.current, Size::zero());
|
let size = regions.expand.select(regions.current, Size::zero());
|
||||||
let mut cts = Constraints::new(regions.expand);
|
let mut cts = Constraints::new(regions.expand);
|
||||||
cts.exact = regions.current.filter(regions.expand);
|
cts.exact = regions.current.filter(regions.expand);
|
||||||
@ -124,7 +124,7 @@ impl Layout for EmptyNode {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PackedNode {
|
pub struct PackedNode {
|
||||||
/// The type-erased node.
|
/// The type-erased node.
|
||||||
node: Rc<dyn Bounds>,
|
node: Arc<dyn Bounds>,
|
||||||
/// A precomputed hash for the node.
|
/// A precomputed hash for the node.
|
||||||
#[cfg(feature = "layout-cache")]
|
#[cfg(feature = "layout-cache")]
|
||||||
hash: u64,
|
hash: u64,
|
||||||
@ -205,7 +205,7 @@ impl Layout for PackedNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let styles = styles.barred(self.node.as_any().type_id());
|
let styles = styles.barred(self.node.as_any().type_id());
|
||||||
|
|
||||||
#[cfg(not(feature = "layout-cache"))]
|
#[cfg(not(feature = "layout-cache"))]
|
||||||
@ -243,10 +243,7 @@ impl Layout for PackedNode {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pack(self) -> PackedNode
|
fn pack(self) -> PackedNode {
|
||||||
where
|
|
||||||
Self: Sized + Hash + 'static,
|
|
||||||
{
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -266,8 +263,8 @@ impl Debug for PackedNode {
|
|||||||
impl PartialEq for PackedNode {
|
impl PartialEq for PackedNode {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
std::ptr::eq(
|
std::ptr::eq(
|
||||||
Rc::as_ptr(&self.node) as *const (),
|
Arc::as_ptr(&self.node) as *const (),
|
||||||
Rc::as_ptr(&other.node) as *const (),
|
Arc::as_ptr(&other.node) as *const (),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,14 +279,14 @@ impl Hash for PackedNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Bounds: Layout + Debug + 'static {
|
trait Bounds: Layout + Debug + Sync + Send + 'static {
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
fn hash64(&self) -> u64;
|
fn hash64(&self) -> u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Bounds for T
|
impl<T> Bounds for T
|
||||||
where
|
where
|
||||||
T: Layout + Hash + Debug + 'static,
|
T: Layout + Hash + Debug + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
@ -320,7 +317,7 @@ impl Layout for SizedNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let is_auto = self.sizing.map_is_none();
|
let is_auto = self.sizing.map_is_none();
|
||||||
let is_rel = self.sizing.map(|s| s.map_or(false, Linear::is_relative));
|
let is_rel = self.sizing.map(|s| s.map_or(false, Linear::is_relative));
|
||||||
|
|
||||||
@ -346,7 +343,7 @@ impl Layout for SizedNode {
|
|||||||
|
|
||||||
// Ensure frame size matches regions size if expansion is on.
|
// Ensure frame size matches regions size if expansion is on.
|
||||||
let target = regions.expand.select(regions.current, frame.size);
|
let target = regions.expand.select(regions.current, frame.size);
|
||||||
Rc::make_mut(frame).resize(target, Align::LEFT_TOP);
|
Arc::make_mut(frame).resize(target, Align::LEFT_TOP);
|
||||||
|
|
||||||
// Set base & exact constraints if the child is automatically sized
|
// Set base & exact constraints if the child is automatically sized
|
||||||
// since we don't know what the child might have done. Also set base if
|
// since we don't know what the child might have done. Also set base if
|
||||||
@ -374,11 +371,11 @@ impl Layout for FillNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let mut frames = self.child.layout(ctx, regions, styles);
|
let mut frames = self.child.layout(ctx, regions, styles);
|
||||||
for Constrained { item: frame, .. } in &mut frames {
|
for Constrained { item: frame, .. } in &mut frames {
|
||||||
let shape = Shape::filled(Geometry::Rect(frame.size), self.fill);
|
let shape = Shape::filled(Geometry::Rect(frame.size), self.fill);
|
||||||
Rc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape));
|
Arc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape));
|
||||||
}
|
}
|
||||||
frames
|
frames
|
||||||
}
|
}
|
||||||
@ -399,11 +396,11 @@ impl Layout for StrokeNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let mut frames = self.child.layout(ctx, regions, styles);
|
let mut frames = self.child.layout(ctx, regions, styles);
|
||||||
for Constrained { item: frame, .. } in &mut frames {
|
for Constrained { item: frame, .. } in &mut frames {
|
||||||
let shape = Shape::stroked(Geometry::Rect(frame.size), self.stroke);
|
let shape = Shape::stroked(Geometry::Rect(frame.size), self.stroke);
|
||||||
Rc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape));
|
Arc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape));
|
||||||
}
|
}
|
||||||
frames
|
frames
|
||||||
}
|
}
|
||||||
|
16
src/lib.rs
16
src/lib.rs
@ -52,7 +52,7 @@ pub mod parse;
|
|||||||
pub mod source;
|
pub mod source;
|
||||||
pub mod syntax;
|
pub mod syntax;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::diag::TypResult;
|
use crate::diag::TypResult;
|
||||||
use crate::eval::{Eval, EvalContext, Module, Scope, StyleMap};
|
use crate::eval::{Eval, EvalContext, Module, Scope, StyleMap};
|
||||||
@ -68,7 +68,7 @@ use crate::source::{SourceId, SourceStore};
|
|||||||
/// The core context which holds the loader, configuration and cached artifacts.
|
/// The core context which holds the loader, configuration and cached artifacts.
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
/// The loader the context was created with.
|
/// The loader the context was created with.
|
||||||
pub loader: Rc<dyn Loader>,
|
pub loader: Arc<dyn Loader>,
|
||||||
/// Stores loaded source files.
|
/// Stores loaded source files.
|
||||||
pub sources: SourceStore,
|
pub sources: SourceStore,
|
||||||
/// Stores parsed font faces.
|
/// Stores parsed font faces.
|
||||||
@ -88,7 +88,7 @@ pub struct Context {
|
|||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
/// Create a new context with the default settings.
|
/// Create a new context with the default settings.
|
||||||
pub fn new(loader: Rc<dyn Loader>) -> Self {
|
pub fn new(loader: Arc<dyn Loader>) -> Self {
|
||||||
Self::builder().build(loader)
|
Self::builder().build(loader)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ impl Context {
|
|||||||
/// Returns either a vector of frames representing individual pages or
|
/// Returns either a vector of frames representing individual pages or
|
||||||
/// diagnostics in the form of a vector of error message with file and span
|
/// diagnostics in the form of a vector of error message with file and span
|
||||||
/// information.
|
/// information.
|
||||||
pub fn typeset(&mut self, id: SourceId) -> TypResult<Vec<Rc<Frame>>> {
|
pub fn typeset(&mut self, id: SourceId) -> TypResult<Vec<Arc<Frame>>> {
|
||||||
let module = self.evaluate(id)?;
|
let module = self.evaluate(id)?;
|
||||||
let tree = module.into_root();
|
let tree = module.into_root();
|
||||||
let frames = tree.layout(self);
|
let frames = tree.layout(self);
|
||||||
@ -183,11 +183,11 @@ impl ContextBuilder {
|
|||||||
|
|
||||||
/// Finish building the context by providing the `loader` used to load
|
/// Finish building the context by providing the `loader` used to load
|
||||||
/// fonts, images, source files and other resources.
|
/// fonts, images, source files and other resources.
|
||||||
pub fn build(self, loader: Rc<dyn Loader>) -> Context {
|
pub fn build(self, loader: Arc<dyn Loader>) -> Context {
|
||||||
Context {
|
Context {
|
||||||
sources: SourceStore::new(Rc::clone(&loader)),
|
sources: SourceStore::new(Arc::clone(&loader)),
|
||||||
fonts: FontStore::new(Rc::clone(&loader)),
|
fonts: FontStore::new(Arc::clone(&loader)),
|
||||||
images: ImageStore::new(Rc::clone(&loader)),
|
images: ImageStore::new(Arc::clone(&loader)),
|
||||||
loader,
|
loader,
|
||||||
#[cfg(feature = "layout-cache")]
|
#[cfg(feature = "layout-cache")]
|
||||||
layout_cache: LayoutCache::new(self.policy, self.max_size),
|
layout_cache: LayoutCache::new(self.policy, self.max_size),
|
||||||
|
@ -27,7 +27,7 @@ impl Layout for AlignNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
// The child only needs to expand along an axis if there's no alignment.
|
// The child only needs to expand along an axis if there's no alignment.
|
||||||
let mut pod = regions.clone();
|
let mut pod = regions.clone();
|
||||||
pod.expand &= self.aligns.map_is_none();
|
pod.expand &= self.aligns.map_is_none();
|
||||||
@ -49,7 +49,7 @@ impl Layout for AlignNode {
|
|||||||
let target = regions.expand.select(current, frame.size);
|
let target = regions.expand.select(current, frame.size);
|
||||||
let default = Spec::new(Align::Left, Align::Top);
|
let default = Spec::new(Align::Left, Align::Top);
|
||||||
let aligns = self.aligns.unwrap_or(default);
|
let aligns = self.aligns.unwrap_or(default);
|
||||||
Rc::make_mut(frame).resize(target, aligns);
|
Arc::make_mut(frame).resize(target, aligns);
|
||||||
|
|
||||||
// Set constraints.
|
// Set constraints.
|
||||||
cts.expand = regions.expand;
|
cts.expand = regions.expand;
|
||||||
|
@ -37,7 +37,7 @@ impl Layout for ColumnsNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let columns = self.columns.get();
|
let columns = self.columns.get();
|
||||||
|
|
||||||
// Separating the infinite space into infinite columns does not make
|
// Separating the infinite space into infinite columns does not make
|
||||||
|
@ -18,7 +18,7 @@ impl Layout for FlowNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
FlowLayouter::new(self, regions.clone()).layout(ctx, styles)
|
FlowLayouter::new(self, regions.clone()).layout(ctx, styles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ struct FlowLayouter<'a> {
|
|||||||
/// Spacing and layouted nodes.
|
/// Spacing and layouted nodes.
|
||||||
items: Vec<FlowItem>,
|
items: Vec<FlowItem>,
|
||||||
/// Finished frames for previous regions.
|
/// Finished frames for previous regions.
|
||||||
finished: Vec<Constrained<Rc<Frame>>>,
|
finished: Vec<Constrained<Arc<Frame>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A prepared item in a flow layout.
|
/// A prepared item in a flow layout.
|
||||||
@ -82,9 +82,9 @@ enum FlowItem {
|
|||||||
/// Fractional spacing between other items.
|
/// Fractional spacing between other items.
|
||||||
Fractional(Fractional),
|
Fractional(Fractional),
|
||||||
/// A frame for a layouted child node and how to align it.
|
/// A frame for a layouted child node and how to align it.
|
||||||
Frame(Rc<Frame>, Spec<Align>),
|
Frame(Arc<Frame>, Spec<Align>),
|
||||||
/// An absolutely placed frame.
|
/// An absolutely placed frame.
|
||||||
Placed(Rc<Frame>),
|
Placed(Arc<Frame>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FlowLayouter<'a> {
|
impl<'a> FlowLayouter<'a> {
|
||||||
@ -113,7 +113,7 @@ impl<'a> FlowLayouter<'a> {
|
|||||||
mut self,
|
mut self,
|
||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
for styled in self.children {
|
for styled in self.children {
|
||||||
let styles = styled.map.chain(&styles);
|
let styles = styled.map.chain(&styles);
|
||||||
match styled.item {
|
match styled.item {
|
||||||
|
@ -38,7 +38,7 @@ impl Layout for GridNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
// Prepare grid layout by unifying content and gutter tracks.
|
// Prepare grid layout by unifying content and gutter tracks.
|
||||||
let mut layouter = GridLayouter::new(self, regions.clone(), styles);
|
let mut layouter = GridLayouter::new(self, regions.clone(), styles);
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ struct GridLayouter<'a> {
|
|||||||
/// Constraints for the active region.
|
/// Constraints for the active region.
|
||||||
cts: Constraints,
|
cts: Constraints,
|
||||||
/// Frames for finished regions.
|
/// Frames for finished regions.
|
||||||
finished: Vec<Constrained<Rc<Frame>>>,
|
finished: Vec<Constrained<Arc<Frame>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produced by initial row layout, auto and linear rows are already finished,
|
/// Produced by initial row layout, auto and linear rows are already finished,
|
||||||
@ -355,7 +355,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Layout the grid row-by-row.
|
/// Layout the grid row-by-row.
|
||||||
fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Rc<Frame>>> {
|
fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
for y in 0 .. self.rows.len() {
|
for y in 0 .. self.rows.len() {
|
||||||
// Skip to next region if current one is full, but only for content
|
// Skip to next region if current one is full, but only for content
|
||||||
// rows, not for gutter rows.
|
// rows, not for gutter rows.
|
||||||
|
@ -51,7 +51,7 @@ impl Layout for HeadingNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let upscale = (1.6 - 0.1 * self.level as f64).max(0.75);
|
let upscale = (1.6 - 0.1 * self.level as f64).max(0.75);
|
||||||
|
|
||||||
let mut passed = StyleMap::new();
|
let mut passed = StyleMap::new();
|
||||||
@ -82,7 +82,7 @@ impl Layout for HeadingNode {
|
|||||||
|
|
||||||
// FIXME: Constraints and region size.
|
// FIXME: Constraints and region size.
|
||||||
for Constrained { item: frame, .. } in &mut frames {
|
for Constrained { item: frame, .. } in &mut frames {
|
||||||
let frame = Rc::make_mut(frame);
|
let frame = Arc::make_mut(frame);
|
||||||
frame.size.y += above + below;
|
frame.size.y += above + below;
|
||||||
frame.translate(Point::with_y(above));
|
frame.translate(Point::with_y(above));
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,12 @@ impl Layout for HideNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let mut frames = self.0.layout(ctx, regions, styles);
|
let mut frames = self.0.layout(ctx, regions, styles);
|
||||||
|
|
||||||
// Clear the frames.
|
// Clear the frames.
|
||||||
for Constrained { item: frame, .. } in &mut frames {
|
for Constrained { item: frame, .. } in &mut frames {
|
||||||
*frame = Rc::new(Frame { elements: vec![], ..**frame });
|
*frame = Arc::new(Frame { elements: vec![], ..**frame });
|
||||||
}
|
}
|
||||||
|
|
||||||
frames
|
frames
|
||||||
|
@ -44,7 +44,7 @@ impl Layout for ImageNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let img = ctx.images.get(self.0);
|
let img = ctx.images.get(self.0);
|
||||||
let pxw = img.width() as f64;
|
let pxw = img.width() as f64;
|
||||||
let pxh = img.height() as f64;
|
let pxh = img.height() as f64;
|
||||||
|
@ -10,13 +10,14 @@ pub struct LinkNode;
|
|||||||
#[class]
|
#[class]
|
||||||
impl LinkNode {
|
impl LinkNode {
|
||||||
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Node> {
|
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Node> {
|
||||||
let url: String = args.expect::<EcoString>("url")?.into();
|
let url = args.expect::<EcoString>("url")?;
|
||||||
let body = args.find().unwrap_or_else(|| {
|
let body = args.find().unwrap_or_else(|| {
|
||||||
let mut text = url.as_str();
|
let mut text = url.as_str();
|
||||||
for prefix in ["mailto:", "tel:"] {
|
for prefix in ["mailto:", "tel:"] {
|
||||||
text = text.trim_start_matches(prefix);
|
text = text.trim_start_matches(prefix);
|
||||||
}
|
}
|
||||||
Node::Text(text.into())
|
let shorter = text.len() < url.len();
|
||||||
|
Node::Text(if shorter { text.into() } else { url.clone() })
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(body.styled(TextNode::LINK, Some(url)))
|
Ok(body.styled(TextNode::LINK, Some(url)))
|
||||||
|
@ -39,7 +39,7 @@ impl<L: ListKind> Layout for ListNode<L> {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let em = styles.get(TextNode::SIZE).abs;
|
let em = styles.get(TextNode::SIZE).abs;
|
||||||
let label_indent = styles.get(Self::LABEL_INDENT).resolve(em);
|
let label_indent = styles.get(Self::LABEL_INDENT).resolve(em);
|
||||||
let body_indent = styles.get(Self::BODY_INDENT).resolve(em);
|
let body_indent = styles.get(Self::BODY_INDENT).resolve(em);
|
||||||
@ -65,7 +65,7 @@ impl<L: ListKind> Layout for ListNode<L> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// How to label a list.
|
/// How to label a list.
|
||||||
pub trait ListKind: Debug + Default + Hash + 'static {
|
pub trait ListKind: Debug + Default + Hash + Sync + Send + 'static {
|
||||||
/// Return the item's label.
|
/// Return the item's label.
|
||||||
fn label(&self) -> EcoString;
|
fn label(&self) -> EcoString;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ macro_rules! prelude {
|
|||||||
prelude! {
|
prelude! {
|
||||||
pub use std::fmt::{self, Debug, Formatter};
|
pub use std::fmt::{self, Debug, Formatter};
|
||||||
pub use std::num::NonZeroUsize;
|
pub use std::num::NonZeroUsize;
|
||||||
pub use std::rc::Rc;
|
pub use std::sync::Arc;
|
||||||
pub use std::hash::Hash;
|
pub use std::hash::Hash;
|
||||||
|
|
||||||
pub use typst_macros::class;
|
pub use typst_macros::class;
|
||||||
|
@ -37,7 +37,7 @@ impl Layout for PadNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
// Layout child into padded regions.
|
// Layout child into padded regions.
|
||||||
let pod = regions.map(|size| shrink(size, self.padding));
|
let pod = regions.map(|size| shrink(size, self.padding));
|
||||||
let mut frames = self.child.layout(ctx, &pod, styles);
|
let mut frames = self.child.layout(ctx, &pod, styles);
|
||||||
@ -52,7 +52,7 @@ impl Layout for PadNode {
|
|||||||
let offset = Point::new(padding.left, padding.top);
|
let offset = Point::new(padding.left, padding.top);
|
||||||
|
|
||||||
// Grow the frame and translate everything in the frame inwards.
|
// Grow the frame and translate everything in the frame inwards.
|
||||||
let frame = Rc::make_mut(frame);
|
let frame = Arc::make_mut(frame);
|
||||||
frame.size = padded;
|
frame.size = padded;
|
||||||
frame.translate(offset);
|
frame.translate(offset);
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ impl PageNode {
|
|||||||
|
|
||||||
impl PageNode {
|
impl PageNode {
|
||||||
/// Layout the page run into a sequence of frames, one per page.
|
/// Layout the page run into a sequence of frames, one per page.
|
||||||
pub fn layout(&self, ctx: &mut LayoutContext, styles: StyleChain) -> Vec<Rc<Frame>> {
|
pub fn layout(&self, ctx: &mut LayoutContext, styles: StyleChain) -> Vec<Arc<Frame>> {
|
||||||
// When one of the lengths is infinite the page fits its content along
|
// When one of the lengths is infinite the page fits its content along
|
||||||
// that axis.
|
// that axis.
|
||||||
let width = styles.get(Self::WIDTH).unwrap_or(Length::inf());
|
let width = styles.get(Self::WIDTH).unwrap_or(Length::inf());
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Paragraph layout.
|
//! Paragraph layout.
|
||||||
|
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
use unicode_bidi::{BidiInfo, Level};
|
use unicode_bidi::{BidiInfo, Level};
|
||||||
@ -9,7 +9,7 @@ use xi_unicode::LineBreakIterator;
|
|||||||
|
|
||||||
use super::prelude::*;
|
use super::prelude::*;
|
||||||
use super::{shape, ShapedText, SpacingKind, TextNode};
|
use super::{shape, ShapedText, SpacingKind, TextNode};
|
||||||
use crate::util::{EcoString, RangeExt, RcExt, SliceExt};
|
use crate::util::{ArcExt, EcoString, RangeExt, SliceExt};
|
||||||
|
|
||||||
/// A node that arranges its children into a paragraph.
|
/// A node that arranges its children into a paragraph.
|
||||||
#[derive(Hash)]
|
#[derive(Hash)]
|
||||||
@ -75,7 +75,7 @@ impl Layout for ParNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
// Collect all text into one string used for BiDi analysis.
|
// Collect all text into one string used for BiDi analysis.
|
||||||
let text = self.collect_text();
|
let text = self.collect_text();
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ impl<'a> ParLayouter<'a> {
|
|||||||
let size = Size::new(regions.current.x, regions.base.y);
|
let size = Size::new(regions.current.x, regions.base.y);
|
||||||
let pod = Regions::one(size, regions.base, Spec::splat(false));
|
let pod = Regions::one(size, regions.base, Spec::splat(false));
|
||||||
let frame = node.layout(ctx, &pod, styles).remove(0);
|
let frame = node.layout(ctx, &pod, styles).remove(0);
|
||||||
items.push(ParItem::Frame(Rc::take(frame.item)));
|
items.push(ParItem::Frame(Arc::take(frame.item)));
|
||||||
ranges.push(range);
|
ranges.push(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ impl<'a> ParLayouter<'a> {
|
|||||||
self,
|
self,
|
||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: Regions,
|
regions: Regions,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let mut stack = LineStack::new(self.leading, regions);
|
let mut stack = LineStack::new(self.leading, regions);
|
||||||
|
|
||||||
// The current line attempt.
|
// The current line attempt.
|
||||||
@ -582,7 +582,7 @@ struct LineStack<'a> {
|
|||||||
regions: Regions,
|
regions: Regions,
|
||||||
size: Size,
|
size: Size,
|
||||||
lines: Vec<LineLayout<'a>>,
|
lines: Vec<LineLayout<'a>>,
|
||||||
finished: Vec<Constrained<Rc<Frame>>>,
|
finished: Vec<Constrained<Arc<Frame>>>,
|
||||||
cts: Constraints,
|
cts: Constraints,
|
||||||
overflowing: bool,
|
overflowing: bool,
|
||||||
fractional: bool,
|
fractional: bool,
|
||||||
@ -650,7 +650,7 @@ impl<'a> LineStack<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Finish the last region and return the built frames.
|
/// Finish the last region and return the built frames.
|
||||||
fn finish(mut self, ctx: &LayoutContext) -> Vec<Constrained<Rc<Frame>>> {
|
fn finish(mut self, ctx: &LayoutContext) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
self.finish_region(ctx);
|
self.finish_region(ctx);
|
||||||
self.finished
|
self.finished
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ impl Layout for PlaceNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let out_of_flow = self.out_of_flow();
|
let out_of_flow = self.out_of_flow();
|
||||||
|
|
||||||
// The pod is the base area of the region because for absolute
|
// The pod is the base area of the region because for absolute
|
||||||
@ -43,7 +43,7 @@ impl Layout for PlaceNode {
|
|||||||
// If expansion is off, zero all sizes so that we don't take up any
|
// If expansion is off, zero all sizes so that we don't take up any
|
||||||
// space in our parent. Otherwise, respect the expand settings.
|
// space in our parent. Otherwise, respect the expand settings.
|
||||||
let target = regions.expand.select(regions.current, Size::zero());
|
let target = regions.expand.select(regions.current, Size::zero());
|
||||||
Rc::make_mut(frame).resize(target, Align::LEFT_TOP);
|
Arc::make_mut(frame).resize(target, Align::LEFT_TOP);
|
||||||
|
|
||||||
// Set base constraint because our pod size is base and exact
|
// Set base constraint because our pod size is base and exact
|
||||||
// constraints if we needed to expand or offset.
|
// constraints if we needed to expand or offset.
|
||||||
|
@ -66,7 +66,7 @@ impl<S: ShapeKind> Layout for ShapeNode<S> {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let mut frames;
|
let mut frames;
|
||||||
if let Some(child) = &self.child {
|
if let Some(child) = &self.child {
|
||||||
let mut padding = styles.get(Self::PADDING);
|
let mut padding = styles.get(Self::PADDING);
|
||||||
@ -118,7 +118,7 @@ impl<S: ShapeKind> Layout for ShapeNode<S> {
|
|||||||
frames = vec![Frame::new(size).constrain(Constraints::tight(regions))];
|
frames = vec![Frame::new(size).constrain(Constraints::tight(regions))];
|
||||||
}
|
}
|
||||||
|
|
||||||
let frame = Rc::make_mut(&mut frames[0].item);
|
let frame = Arc::make_mut(&mut frames[0].item);
|
||||||
|
|
||||||
// Add fill and/or stroke.
|
// Add fill and/or stroke.
|
||||||
let fill = styles.get(Self::FILL);
|
let fill = styles.get(Self::FILL);
|
||||||
@ -149,7 +149,7 @@ impl<S: ShapeKind> Layout for ShapeNode<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Categorizes shapes.
|
/// Categorizes shapes.
|
||||||
pub trait ShapeKind: Debug + Default + Hash + 'static {
|
pub trait ShapeKind: Debug + Default + Hash + Sync + Send + 'static {
|
||||||
const ROUND: bool;
|
const ROUND: bool;
|
||||||
const QUADRATIC: bool;
|
const QUADRATIC: bool;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ impl Layout for StackNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
StackLayouter::new(self, regions.clone(), styles).layout(ctx)
|
StackLayouter::new(self, regions.clone(), styles).layout(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ struct StackLayouter<'a> {
|
|||||||
/// Spacing and layouted nodes.
|
/// Spacing and layouted nodes.
|
||||||
items: Vec<StackItem>,
|
items: Vec<StackItem>,
|
||||||
/// Finished frames for previous regions.
|
/// Finished frames for previous regions.
|
||||||
finished: Vec<Constrained<Rc<Frame>>>,
|
finished: Vec<Constrained<Arc<Frame>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A prepared item in a stack layout.
|
/// A prepared item in a stack layout.
|
||||||
@ -100,7 +100,7 @@ enum StackItem {
|
|||||||
/// Fractional spacing between other items.
|
/// Fractional spacing between other items.
|
||||||
Fractional(Fractional),
|
Fractional(Fractional),
|
||||||
/// A layouted child node.
|
/// A layouted child node.
|
||||||
Frame(Rc<Frame>, Align),
|
Frame(Arc<Frame>, Align),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StackLayouter<'a> {
|
impl<'a> StackLayouter<'a> {
|
||||||
@ -131,7 +131,7 @@ impl<'a> StackLayouter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Layout all children.
|
/// Layout all children.
|
||||||
fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Rc<Frame>>> {
|
fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
// Spacing to insert before the next node.
|
// Spacing to insert before the next node.
|
||||||
let mut deferred = None;
|
let mut deferred = None;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ impl Layout for TableNode {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let primary = styles.get(Self::PRIMARY);
|
let primary = styles.get(Self::PRIMARY);
|
||||||
let secondary = styles.get(Self::SECONDARY);
|
let secondary = styles.get(Self::SECONDARY);
|
||||||
let thickness = styles.get(Self::THICKNESS);
|
let thickness = styles.get(Self::THICKNESS);
|
||||||
|
@ -55,7 +55,7 @@ impl TextNode {
|
|||||||
#[fold(|a, b| a.into_iter().chain(b).collect())]
|
#[fold(|a, b| a.into_iter().chain(b).collect())]
|
||||||
pub const LINES: Vec<Decoration> = vec![];
|
pub const LINES: Vec<Decoration> = vec![];
|
||||||
/// An URL the text should link to.
|
/// An URL the text should link to.
|
||||||
pub const LINK: Option<String> = None;
|
pub const LINK: Option<EcoString> = None;
|
||||||
|
|
||||||
/// The size of the glyphs.
|
/// The size of the glyphs.
|
||||||
#[fold(Linear::compose)]
|
#[fold(Linear::compose)]
|
||||||
@ -211,12 +211,12 @@ castable! {
|
|||||||
|
|
||||||
/// A specific font family like "Arial".
|
/// A specific font family like "Arial".
|
||||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct NamedFamily(String);
|
pub struct NamedFamily(EcoString);
|
||||||
|
|
||||||
impl NamedFamily {
|
impl NamedFamily {
|
||||||
/// Create a named font family variant.
|
/// Create a named font family variant.
|
||||||
pub fn new(string: &str) -> Self {
|
pub fn new(string: &str) -> Self {
|
||||||
Self(string.to_lowercase())
|
Self(string.to_lowercase().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The lowercased family name.
|
/// The lowercased family name.
|
||||||
|
@ -36,7 +36,7 @@ impl<T: TransformKind> Layout for TransformNode<T> {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
regions: &Regions,
|
regions: &Regions,
|
||||||
styles: StyleChain,
|
styles: StyleChain,
|
||||||
) -> Vec<Constrained<Rc<Frame>>> {
|
) -> Vec<Constrained<Arc<Frame>>> {
|
||||||
let origin = styles.get(Self::ORIGIN).unwrap_or(Align::CENTER_HORIZON);
|
let origin = styles.get(Self::ORIGIN).unwrap_or(Align::CENTER_HORIZON);
|
||||||
let matrix = self.kind.matrix();
|
let matrix = self.kind.matrix();
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ impl<T: TransformKind> Layout for TransformNode<T> {
|
|||||||
.pre_concat(matrix)
|
.pre_concat(matrix)
|
||||||
.pre_concat(Transform::translation(-x, -y));
|
.pre_concat(Transform::translation(-x, -y));
|
||||||
|
|
||||||
Rc::make_mut(frame).transform(transform);
|
Arc::make_mut(frame).transform(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
frames
|
frames
|
||||||
@ -56,7 +56,7 @@ impl<T: TransformKind> Layout for TransformNode<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Kinds of transformations.
|
/// Kinds of transformations.
|
||||||
pub trait TransformKind: Debug + Hash + Sized + 'static {
|
pub trait TransformKind: Debug + Hash + Sized + Sync + Send + 'static {
|
||||||
fn construct(args: &mut Args) -> TypResult<Self>;
|
fn construct(args: &mut Args) -> TypResult<Self>;
|
||||||
fn matrix(&self) -> Transform;
|
fn matrix(&self) -> Transform;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use memmap2::Mmap;
|
use memmap2::Mmap;
|
||||||
use same_file::Handle;
|
use same_file::Handle;
|
||||||
@ -35,10 +35,10 @@ impl FsLoader {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder-style method to wrap the loader in an [`Rc`] to make it usable
|
/// Builder-style method to wrap the loader in an [`Arc`] to make it usable
|
||||||
/// with the [`Context`](crate::Context).
|
/// with the [`Context`](crate::Context).
|
||||||
pub fn wrap(self) -> Rc<Self> {
|
pub fn wrap(self) -> Arc<Self> {
|
||||||
Rc::new(self)
|
Arc::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search for fonts in the operating system's font directories.
|
/// Search for fonts in the operating system's font directories.
|
||||||
|
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{FileHash, Loader};
|
use super::{FileHash, Loader};
|
||||||
use crate::font::FaceInfo;
|
use crate::font::FaceInfo;
|
||||||
@ -31,10 +31,10 @@ impl MemLoader {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder-style method to wrap the loader in an [`Rc`] to make it usable
|
/// Builder-style method to wrap the loader in an [`Arc`] to make it usable
|
||||||
/// with the [`Context`](crate::Context).
|
/// with the [`Context`](crate::Context).
|
||||||
pub fn wrap(self) -> Rc<Self> {
|
pub fn wrap(self) -> Arc<Self> {
|
||||||
Rc::new(self)
|
Arc::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a path-file mapping. If the data forms a font, then that font
|
/// Insert a path-file mapping. If the data forms a font, then that font
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::syntax::{Green, GreenNode, NodeKind};
|
use crate::syntax::{Green, GreenNode, NodeKind};
|
||||||
|
|
||||||
@ -78,8 +78,8 @@ impl<'a> Reparser<'a> {
|
|||||||
|
|
||||||
impl Reparser<'_> {
|
impl Reparser<'_> {
|
||||||
/// Find the innermost child that is incremental safe.
|
/// Find the innermost child that is incremental safe.
|
||||||
pub fn reparse(&self, green: &mut Rc<GreenNode>) -> Range<usize> {
|
pub fn reparse(&self, green: &mut Arc<GreenNode>) -> Range<usize> {
|
||||||
self.reparse_step(Rc::make_mut(green), 0, TokenMode::Markup, true)
|
self.reparse_step(Arc::make_mut(green), 0, TokenMode::Markup, true)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
*green = parse(self.src);
|
*green = parse(self.src);
|
||||||
0 .. self.src.len()
|
0 .. self.src.len()
|
||||||
@ -167,7 +167,7 @@ impl Reparser<'_> {
|
|||||||
if last_kind.succession_rule() != SuccessionRule::Unsafe {
|
if last_kind.succession_rule() != SuccessionRule::Unsafe {
|
||||||
if let Some(range) = match child {
|
if let Some(range) = match child {
|
||||||
Green::Node(node) => self.reparse_step(
|
Green::Node(node) => self.reparse_step(
|
||||||
Rc::make_mut(node),
|
Arc::make_mut(node),
|
||||||
first_start,
|
first_start,
|
||||||
child_mode,
|
child_mode,
|
||||||
outermost,
|
outermost,
|
||||||
|
@ -12,14 +12,14 @@ pub use resolve::*;
|
|||||||
pub use scanner::*;
|
pub use scanner::*;
|
||||||
pub use tokens::*;
|
pub use tokens::*;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::syntax::ast::{Associativity, BinOp, UnOp};
|
use crate::syntax::ast::{Associativity, BinOp, UnOp};
|
||||||
use crate::syntax::{ErrorPos, Green, GreenNode, NodeKind};
|
use crate::syntax::{ErrorPos, Green, GreenNode, NodeKind};
|
||||||
use crate::util::EcoString;
|
use crate::util::EcoString;
|
||||||
|
|
||||||
/// Parse a source file.
|
/// Parse a source file.
|
||||||
pub fn parse(src: &str) -> Rc<GreenNode> {
|
pub fn parse(src: &str) -> Arc<GreenNode> {
|
||||||
let mut p = Parser::new(src, TokenMode::Markup);
|
let mut p = Parser::new(src, TokenMode::Markup);
|
||||||
markup(&mut p, true);
|
markup(&mut p, true);
|
||||||
match p.finish().into_iter().next() {
|
match p.finish().into_iter().next() {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
is_id_continue, is_id_start, is_newline, resolve_hex, resolve_raw, resolve_string,
|
is_id_continue, is_id_start, is_newline, resolve_hex, resolve_raw, resolve_string,
|
||||||
@ -321,7 +321,7 @@ impl<'s> Tokens<'s> {
|
|||||||
|
|
||||||
// Special case for empty inline block.
|
// Special case for empty inline block.
|
||||||
if backticks == 2 {
|
if backticks == 2 {
|
||||||
return NodeKind::Raw(Rc::new(RawNode {
|
return NodeKind::Raw(Arc::new(RawNode {
|
||||||
text: EcoString::new(),
|
text: EcoString::new(),
|
||||||
lang: None,
|
lang: None,
|
||||||
block: false,
|
block: false,
|
||||||
@ -341,7 +341,7 @@ impl<'s> Tokens<'s> {
|
|||||||
|
|
||||||
if found == backticks {
|
if found == backticks {
|
||||||
let end = self.s.index() - found as usize;
|
let end = self.s.index() - found as usize;
|
||||||
NodeKind::Raw(Rc::new(resolve_raw(
|
NodeKind::Raw(Arc::new(resolve_raw(
|
||||||
column,
|
column,
|
||||||
backticks,
|
backticks,
|
||||||
self.s.get(start .. end),
|
self.s.get(start .. end),
|
||||||
@ -393,7 +393,7 @@ impl<'s> Tokens<'s> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if terminated {
|
if terminated {
|
||||||
NodeKind::Math(Rc::new(MathNode {
|
NodeKind::Math(Arc::new(MathNode {
|
||||||
formula: self.s.get(start .. end).into(),
|
formula: self.s.get(start .. end).into(),
|
||||||
display,
|
display,
|
||||||
}))
|
}))
|
||||||
@ -581,7 +581,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn Raw(text: &str, lang: Option<&str>, block: bool) -> NodeKind {
|
fn Raw(text: &str, lang: Option<&str>, block: bool) -> NodeKind {
|
||||||
NodeKind::Raw(Rc::new(RawNode {
|
NodeKind::Raw(Arc::new(RawNode {
|
||||||
text: text.into(),
|
text: text.into(),
|
||||||
lang: lang.map(Into::into),
|
lang: lang.map(Into::into),
|
||||||
block,
|
block,
|
||||||
@ -589,7 +589,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn Math(formula: &str, display: bool) -> NodeKind {
|
fn Math(formula: &str, display: bool) -> NodeKind {
|
||||||
NodeKind::Math(Rc::new(MathNode { formula: formula.into(), display }))
|
NodeKind::Math(Arc::new(MathNode { formula: formula.into(), display }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Str(string: &str) -> NodeKind {
|
fn Str(string: &str) -> NodeKind {
|
||||||
|
@ -4,7 +4,7 @@ use std::collections::HashMap;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::diag::TypResult;
|
use crate::diag::TypResult;
|
||||||
use crate::loading::{FileHash, Loader};
|
use crate::loading::{FileHash, Loader};
|
||||||
@ -37,14 +37,14 @@ impl SourceId {
|
|||||||
|
|
||||||
/// Storage for loaded source files.
|
/// Storage for loaded source files.
|
||||||
pub struct SourceStore {
|
pub struct SourceStore {
|
||||||
loader: Rc<dyn Loader>,
|
loader: Arc<dyn Loader>,
|
||||||
files: HashMap<FileHash, SourceId>,
|
files: HashMap<FileHash, SourceId>,
|
||||||
sources: Vec<SourceFile>,
|
sources: Vec<SourceFile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceStore {
|
impl SourceStore {
|
||||||
/// Create a new, empty source store.
|
/// Create a new, empty source store.
|
||||||
pub fn new(loader: Rc<dyn Loader>) -> Self {
|
pub fn new(loader: Arc<dyn Loader>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
loader,
|
loader,
|
||||||
files: HashMap::new(),
|
files: HashMap::new(),
|
||||||
@ -125,7 +125,7 @@ pub struct SourceFile {
|
|||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
src: String,
|
src: String,
|
||||||
lines: Vec<Line>,
|
lines: Vec<Line>,
|
||||||
root: Rc<GreenNode>,
|
root: Arc<GreenNode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceFile {
|
impl SourceFile {
|
||||||
@ -148,7 +148,7 @@ impl SourceFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The root node of the file's untyped green tree.
|
/// The root node of the file's untyped green tree.
|
||||||
pub fn root(&self) -> &Rc<GreenNode> {
|
pub fn root(&self) -> &Arc<GreenNode> {
|
||||||
&self.root
|
&self.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ mod span;
|
|||||||
|
|
||||||
use std::fmt::{self, Debug, Display, Formatter};
|
use std::fmt::{self, Debug, Display, Formatter};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub use highlight::*;
|
pub use highlight::*;
|
||||||
pub use pretty::*;
|
pub use pretty::*;
|
||||||
@ -24,7 +24,7 @@ use crate::util::EcoString;
|
|||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub enum Green {
|
pub enum Green {
|
||||||
/// A reference-counted inner node.
|
/// A reference-counted inner node.
|
||||||
Node(Rc<GreenNode>),
|
Node(Arc<GreenNode>),
|
||||||
/// A terminal, owned token.
|
/// A terminal, owned token.
|
||||||
Token(GreenData),
|
Token(GreenData),
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ impl Green {
|
|||||||
pub fn convert(&mut self, kind: NodeKind) {
|
pub fn convert(&mut self, kind: NodeKind) {
|
||||||
match self {
|
match self {
|
||||||
Self::Node(node) => {
|
Self::Node(node) => {
|
||||||
let node = Rc::make_mut(node);
|
let node = Arc::make_mut(node);
|
||||||
node.erroneous |= kind.is_error();
|
node.erroneous |= kind.is_error();
|
||||||
node.data.kind = kind;
|
node.data.kind = kind;
|
||||||
}
|
}
|
||||||
@ -187,12 +187,12 @@ impl GreenNode {
|
|||||||
|
|
||||||
impl From<GreenNode> for Green {
|
impl From<GreenNode> for Green {
|
||||||
fn from(node: GreenNode) -> Self {
|
fn from(node: GreenNode) -> Self {
|
||||||
Rc::new(node).into()
|
Arc::new(node).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rc<GreenNode>> for Green {
|
impl From<Arc<GreenNode>> for Green {
|
||||||
fn from(node: Rc<GreenNode>) -> Self {
|
fn from(node: Arc<GreenNode>) -> Self {
|
||||||
Self::Node(node)
|
Self::Node(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -259,7 +259,7 @@ pub struct RedNode {
|
|||||||
|
|
||||||
impl RedNode {
|
impl RedNode {
|
||||||
/// Create a new red node from a root [`GreenNode`].
|
/// Create a new red node from a root [`GreenNode`].
|
||||||
pub fn from_root(root: Rc<GreenNode>, id: SourceId) -> Self {
|
pub fn from_root(root: Arc<GreenNode>, id: SourceId) -> Self {
|
||||||
Self { id, offset: 0, green: root.into() }
|
Self { id, offset: 0, green: root.into() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,9 +611,9 @@ pub enum NodeKind {
|
|||||||
Emph,
|
Emph,
|
||||||
/// An arbitrary number of backticks followed by inner contents, terminated
|
/// An arbitrary number of backticks followed by inner contents, terminated
|
||||||
/// with the same number of backticks: `` `...` ``.
|
/// with the same number of backticks: `` `...` ``.
|
||||||
Raw(Rc<RawNode>),
|
Raw(Arc<RawNode>),
|
||||||
/// Dollar signs surrounding inner contents.
|
/// Dollar signs surrounding inner contents.
|
||||||
Math(Rc<MathNode>),
|
Math(Arc<MathNode>),
|
||||||
/// A section heading: `= Introduction`.
|
/// A section heading: `= Introduction`.
|
||||||
Heading,
|
Heading,
|
||||||
/// An item in an unordered list: `- ...`.
|
/// An item in an unordered list: `- ...`.
|
||||||
|
@ -3,9 +3,9 @@ use std::cmp::Ordering;
|
|||||||
use std::fmt::{self, Debug, Display, Formatter, Write};
|
use std::fmt::{self, Debug, Display, Formatter, Write};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ops::{Add, AddAssign, Deref};
|
use std::ops::{Add, AddAssign, Deref};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::RcExt;
|
use super::ArcExt;
|
||||||
|
|
||||||
/// Create a new [`EcoString`] from a format string.
|
/// Create a new [`EcoString`] from a format string.
|
||||||
macro_rules! format_eco {
|
macro_rules! format_eco {
|
||||||
@ -27,13 +27,13 @@ pub struct EcoString(Repr);
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum Repr {
|
enum Repr {
|
||||||
Small { buf: [u8; LIMIT], len: u8 },
|
Small { buf: [u8; LIMIT], len: u8 },
|
||||||
Large(Rc<String>),
|
Large(Arc<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The maximum number of bytes that can be stored inline.
|
/// The maximum number of bytes that can be stored inline.
|
||||||
///
|
///
|
||||||
/// The value is chosen such that an `EcoString` fits exactly into 16 bytes
|
/// The value is chosen such that an `EcoString` fits exactly into 16 bytes
|
||||||
/// (which are needed anyway due to the `Rc`s alignment, at least on 64-bit
|
/// (which are needed anyway due to the `Arc`s alignment, at least on 64-bit
|
||||||
/// platforms).
|
/// platforms).
|
||||||
///
|
///
|
||||||
/// Must be at least 4 to hold any char.
|
/// Must be at least 4 to hold any char.
|
||||||
@ -50,7 +50,7 @@ impl EcoString {
|
|||||||
if capacity <= LIMIT {
|
if capacity <= LIMIT {
|
||||||
Self::new()
|
Self::new()
|
||||||
} else {
|
} else {
|
||||||
Self(Repr::Large(Rc::new(String::with_capacity(capacity))))
|
Self(Repr::Large(Arc::new(String::with_capacity(capacity))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ impl EcoString {
|
|||||||
buf[.. len].copy_from_slice(slice.as_bytes());
|
buf[.. len].copy_from_slice(slice.as_bytes());
|
||||||
Repr::Small { buf, len: len as u8 }
|
Repr::Small { buf, len: len as u8 }
|
||||||
} else {
|
} else {
|
||||||
Repr::Large(Rc::new(s.into()))
|
Repr::Large(Arc::new(s.into()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ impl EcoString {
|
|||||||
self.push_str(c.encode_utf8(&mut [0; 4]));
|
self.push_str(c.encode_utf8(&mut [0; 4]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Repr::Large(rc) => Rc::make_mut(rc).push(c),
|
Repr::Large(rc) => Arc::make_mut(rc).push(c),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,10 +117,10 @@ impl EcoString {
|
|||||||
let mut spilled = String::with_capacity(new);
|
let mut spilled = String::with_capacity(new);
|
||||||
spilled.push_str(self);
|
spilled.push_str(self);
|
||||||
spilled.push_str(string);
|
spilled.push_str(string);
|
||||||
self.0 = Repr::Large(Rc::new(spilled));
|
self.0 = Repr::Large(Arc::new(spilled));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Repr::Large(rc) => Rc::make_mut(rc).push_str(string),
|
Repr::Large(rc) => Arc::make_mut(rc).push_str(string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ impl EcoString {
|
|||||||
*len -= c.len_utf8() as u8;
|
*len -= c.len_utf8() as u8;
|
||||||
}
|
}
|
||||||
Repr::Large(rc) => {
|
Repr::Large(rc) => {
|
||||||
Rc::make_mut(rc).pop();
|
Arc::make_mut(rc).pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(c)
|
Some(c)
|
||||||
@ -143,8 +143,8 @@ impl EcoString {
|
|||||||
match &mut self.0 {
|
match &mut self.0 {
|
||||||
Repr::Small { len, .. } => *len = 0,
|
Repr::Small { len, .. } => *len = 0,
|
||||||
Repr::Large(rc) => {
|
Repr::Large(rc) => {
|
||||||
if Rc::strong_count(rc) == 1 {
|
if Arc::strong_count(rc) == 1 {
|
||||||
Rc::make_mut(rc).clear();
|
Arc::make_mut(rc).clear();
|
||||||
} else {
|
} else {
|
||||||
*self = Self::new();
|
*self = Self::new();
|
||||||
}
|
}
|
||||||
@ -351,11 +351,17 @@ impl From<String> for EcoString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&EcoString> for String {
|
||||||
|
fn from(s: &EcoString) -> Self {
|
||||||
|
s.as_str().to_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<EcoString> for String {
|
impl From<EcoString> for String {
|
||||||
fn from(s: EcoString) -> Self {
|
fn from(s: EcoString) -> Self {
|
||||||
match s.0 {
|
match s.0 {
|
||||||
Repr::Small { .. } => s.as_str().to_owned(),
|
Repr::Small { .. } => s.as_str().to_owned(),
|
||||||
Repr::Large(rc) => Rc::take(rc),
|
Repr::Large(rc) => Arc::take(rc),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ use std::cell::RefMut;
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::path::{Component, Path, PathBuf};
|
use std::path::{Component, Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Additional methods for strings.
|
/// Additional methods for strings.
|
||||||
pub trait StrExt {
|
pub trait StrExt {
|
||||||
@ -62,18 +62,18 @@ impl<T> OptionExt<T> for Option<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods for reference-counted pointers.
|
/// Additional methods for reference-counted pointers.
|
||||||
pub trait RcExt<T> {
|
pub trait ArcExt<T> {
|
||||||
/// Takes the inner value if there is exactly one strong reference and
|
/// Takes the inner value if there is exactly one strong reference and
|
||||||
/// clones it otherwise.
|
/// clones it otherwise.
|
||||||
fn take(self) -> T;
|
fn take(self) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> RcExt<T> for Rc<T>
|
impl<T> ArcExt<T> for Arc<T>
|
||||||
where
|
where
|
||||||
T: Clone,
|
T: Clone,
|
||||||
{
|
{
|
||||||
fn take(self) -> T {
|
fn take(self) -> T {
|
||||||
match Rc::try_unwrap(self) {
|
match Arc::try_unwrap(self) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(rc) => (*rc).clone(),
|
Err(rc) => (*rc).clone(),
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use std::ffi::OsStr;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use tiny_skia as sk;
|
use tiny_skia as sk;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
@ -258,7 +258,7 @@ fn test_part(
|
|||||||
line: usize,
|
line: usize,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
rng: &mut LinearShift,
|
rng: &mut LinearShift,
|
||||||
) -> (bool, bool, Vec<Rc<Frame>>) {
|
) -> (bool, bool, Vec<Arc<Frame>>) {
|
||||||
let mut ok = true;
|
let mut ok = true;
|
||||||
|
|
||||||
let id = ctx.sources.provide(src_path, src);
|
let id = ctx.sources.provide(src_path, src);
|
||||||
@ -483,7 +483,7 @@ fn test_incremental(
|
|||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
i: usize,
|
i: usize,
|
||||||
tree: &RootNode,
|
tree: &RootNode,
|
||||||
frames: &[Rc<Frame>],
|
frames: &[Arc<Frame>],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut ok = true;
|
let mut ok = true;
|
||||||
|
|
||||||
@ -527,7 +527,7 @@ fn test_incremental(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw all frames into one image with padding in between.
|
/// Draw all frames into one image with padding in between.
|
||||||
fn render(ctx: &mut Context, frames: &[Rc<Frame>]) -> sk::Pixmap {
|
fn render(ctx: &mut Context, frames: &[Arc<Frame>]) -> sk::Pixmap {
|
||||||
let pixel_per_pt = 2.0;
|
let pixel_per_pt = 2.0;
|
||||||
let pixmaps: Vec<_> = frames
|
let pixmaps: Vec<_> = frames
|
||||||
.iter()
|
.iter()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user