Make clippy a bit happier
This commit is contained in:
parent
fef5502517
commit
f5dcb84e36
@ -372,13 +372,13 @@ impl Packer {
|
||||
return;
|
||||
}
|
||||
|
||||
if !self.par.styles.compatible(&styles, ParNode::has_property) {
|
||||
if !self.par.styles.compatible(styles, ParNode::has_property) {
|
||||
self.parbreak(None);
|
||||
self.par.styles = styles.clone();
|
||||
return;
|
||||
}
|
||||
|
||||
self.par.styles.intersect(&styles);
|
||||
self.par.styles.intersect(styles);
|
||||
}
|
||||
|
||||
/// Break to a new page if the `styles` contain page styles that are
|
||||
@ -389,7 +389,7 @@ impl Packer {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.top && !self.flow.styles.compatible(&styles, PageNode::has_property) {
|
||||
if self.top && !self.flow.styles.compatible(styles, PageNode::has_property) {
|
||||
self.pagebreak();
|
||||
self.flow.styles = styles.clone();
|
||||
return;
|
||||
|
@ -390,7 +390,7 @@ impl<'a> PageExporter<'a> {
|
||||
// Make the coordinate system start at the top-left.
|
||||
self.bottom = frame.size.y.to_f32();
|
||||
self.content.transform([1.0, 0.0, 0.0, -1.0, 0.0, self.bottom]);
|
||||
self.write_frame(&frame);
|
||||
self.write_frame(frame);
|
||||
Page {
|
||||
size: frame.size,
|
||||
content: self.content,
|
||||
|
@ -656,7 +656,7 @@ mod cff {
|
||||
|
||||
if count > 0 {
|
||||
let offsize = usize::from(s.read::<u8>()?);
|
||||
if offsize < 1 || offsize > 4 {
|
||||
if !matches!(offsize, 1 ..= 4) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ impl RgbaColor {
|
||||
}
|
||||
|
||||
impl FromStr for RgbaColor {
|
||||
type Err = ParseRgbaError;
|
||||
type Err = RgbaError;
|
||||
|
||||
/// Constructs a new color from hex strings like the following:
|
||||
/// - `#aef` (shorthand, with leading hashtag),
|
||||
@ -83,7 +83,7 @@ impl FromStr for RgbaColor {
|
||||
fn from_str(hex_str: &str) -> Result<Self, Self::Err> {
|
||||
let hex_str = hex_str.strip_prefix('#').unwrap_or(hex_str);
|
||||
if !hex_str.is_ascii() {
|
||||
return Err(ParseRgbaError);
|
||||
return Err(RgbaError);
|
||||
}
|
||||
|
||||
let len = hex_str.len();
|
||||
@ -92,7 +92,7 @@ impl FromStr for RgbaColor {
|
||||
let alpha = len == 4 || len == 8;
|
||||
|
||||
if !long && !short {
|
||||
return Err(ParseRgbaError);
|
||||
return Err(RgbaError);
|
||||
}
|
||||
|
||||
let mut values: [u8; 4] = [255; 4];
|
||||
@ -102,7 +102,7 @@ impl FromStr for RgbaColor {
|
||||
let pos = elem * item_len;
|
||||
|
||||
let item = &hex_str[pos .. (pos + item_len)];
|
||||
values[elem] = u8::from_str_radix(item, 16).map_err(|_| ParseRgbaError)?;
|
||||
values[elem] = u8::from_str_radix(item, 16).map_err(|_| RgbaError)?;
|
||||
|
||||
if short {
|
||||
// Duplicate number for shorthand notation, i.e. `a` -> `aa`
|
||||
@ -134,15 +134,15 @@ impl Debug for RgbaColor {
|
||||
|
||||
/// The error when parsing an [`RgbaColor`] from a string fails.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct ParseRgbaError;
|
||||
pub struct RgbaError;
|
||||
|
||||
impl Display for ParseRgbaError {
|
||||
impl Display for RgbaError {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad("invalid color")
|
||||
f.pad("invalid hex string")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for ParseRgbaError {}
|
||||
impl std::error::Error for RgbaError {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
@ -166,7 +166,7 @@ mod tests {
|
||||
fn test_parse_invalid_colors() {
|
||||
#[track_caller]
|
||||
fn test(hex: &str) {
|
||||
assert_eq!(RgbaColor::from_str(hex), Err(ParseRgbaError));
|
||||
assert_eq!(RgbaColor::from_str(hex), Err(RgbaError));
|
||||
}
|
||||
|
||||
test("12345");
|
||||
|
@ -27,7 +27,7 @@ impl Debug for Scalar {
|
||||
|
||||
impl Ord for Scalar {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.partial_cmp(&other).expect("float is NaN")
|
||||
self.partial_cmp(other).expect("float is NaN")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ impl ImageStore {
|
||||
Entry::Vacant(entry) => {
|
||||
let buffer = self.loader.load(path)?;
|
||||
let ext = path.extension().and_then(OsStr::to_str).unwrap_or_default();
|
||||
let image = Image::parse(&buffer, &ext)?;
|
||||
let image = Image::parse(&buffer, ext)?;
|
||||
let id = ImageId(self.images.len() as u32);
|
||||
if let Some(callback) = &self.on_load {
|
||||
callback(id, &image);
|
||||
|
@ -377,22 +377,14 @@ pub struct PatternProperties {
|
||||
impl PatternProperties {
|
||||
/// Check if it is vital to keep an entry based on its properties.
|
||||
pub fn must_keep(&self) -> bool {
|
||||
if self.top_level && !self.mature {
|
||||
// Keep an undo stack.
|
||||
true
|
||||
} else if self.all_zeros && !self.mature {
|
||||
// Keep the most recently created items, even if they have not yet
|
||||
// been used.
|
||||
true
|
||||
} else if self.multi_use && !self.abandoned {
|
||||
true
|
||||
} else if self.hit {
|
||||
true
|
||||
} else if self.sparse {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
// Keep an undo stack.
|
||||
(self.top_level && !self.mature)
|
||||
// Keep the most recently created items, even if they have not yet
|
||||
// been used.
|
||||
|| (self.all_zeros && !self.mature)
|
||||
|| (self.multi_use && !self.abandoned)
|
||||
|| self.hit
|
||||
|| self.sparse
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,7 +282,10 @@ impl Debug for PackedNode {
|
||||
|
||||
impl PartialEq for PackedNode {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Rc::as_ptr(&self.node) as *const () == Rc::as_ptr(&other.node) as *const ()
|
||||
std::ptr::eq(
|
||||
Rc::as_ptr(&self.node) as *const (),
|
||||
Rc::as_ptr(&other.node) as *const (),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,10 @@
|
||||
//! [cache]: layout::LayoutCache
|
||||
//! [PDF]: export::pdf
|
||||
|
||||
#![allow(clippy::len_without_is_empty)]
|
||||
#![allow(clippy::or_fun_call)]
|
||||
#![allow(clippy::try_err)]
|
||||
|
||||
#[macro_use]
|
||||
pub mod util;
|
||||
#[macro_use]
|
||||
|
@ -6,16 +6,14 @@ use super::ParNode;
|
||||
/// `align`: Configure the alignment along the layouting axes.
|
||||
pub fn align(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
||||
let aligns: Spec<_> = args.find().unwrap_or_default();
|
||||
let body: Node = args.expect("body")?;
|
||||
let body: PackedNode = args.expect("body")?;
|
||||
|
||||
let mut styles = Styles::new();
|
||||
if let Some(align) = aligns.x {
|
||||
styles.set(ParNode::ALIGN, align);
|
||||
}
|
||||
|
||||
Ok(Value::block(
|
||||
body.into_block().styled(styles).aligned(aligns),
|
||||
))
|
||||
Ok(Value::block(body.styled(styles).aligned(aligns)))
|
||||
}
|
||||
|
||||
dynamic! {
|
||||
|
@ -5,13 +5,10 @@ use super::ParNode;
|
||||
|
||||
/// `columns`: Set content into multiple columns.
|
||||
pub fn columns(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
||||
let columns = args.expect("column count")?;
|
||||
let gutter = args.named("gutter")?.unwrap_or(Relative::new(0.04).into());
|
||||
let body: Node = args.expect("body")?;
|
||||
Ok(Value::block(ColumnsNode {
|
||||
columns,
|
||||
gutter,
|
||||
child: body.into_block(),
|
||||
columns: args.expect("column count")?,
|
||||
gutter: args.named("gutter")?.unwrap_or(Relative::new(0.04).into()),
|
||||
child: args.expect("body")?,
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ impl Layout for FlowNode {
|
||||
ctx: &mut LayoutContext,
|
||||
regions: &Regions,
|
||||
) -> Vec<Constrained<Rc<Frame>>> {
|
||||
FlowLayouter::new(self, regions).layout(ctx)
|
||||
FlowLayouter::new(self, regions.clone()).layout(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,12 +32,12 @@ impl Debug for FlowNode {
|
||||
/// A child of a flow node.
|
||||
#[derive(Hash)]
|
||||
pub enum FlowChild {
|
||||
/// A paragraph/block break.
|
||||
Break(Styles),
|
||||
/// Vertical spacing between other children.
|
||||
Spacing(SpacingNode),
|
||||
/// An arbitrary node.
|
||||
Node(PackedNode),
|
||||
/// A paragraph/block break.
|
||||
Break(Styles),
|
||||
/// Skip the rest of the region and move to the next.
|
||||
Skip,
|
||||
}
|
||||
@ -46,9 +46,9 @@ impl FlowChild {
|
||||
/// A reference to the child's styles.
|
||||
pub fn styles(&self) -> Option<&Styles> {
|
||||
match self {
|
||||
Self::Break(styles) => Some(styles),
|
||||
Self::Spacing(node) => Some(&node.styles),
|
||||
Self::Node(node) => Some(&node.styles),
|
||||
Self::Break(styles) => Some(styles),
|
||||
Self::Skip => None,
|
||||
}
|
||||
}
|
||||
@ -56,9 +56,9 @@ impl FlowChild {
|
||||
/// A mutable reference to the child's styles.
|
||||
pub fn styles_mut(&mut self) -> Option<&mut Styles> {
|
||||
match self {
|
||||
Self::Break(styles) => Some(styles),
|
||||
Self::Spacing(node) => Some(&mut node.styles),
|
||||
Self::Node(node) => Some(&mut node.styles),
|
||||
Self::Break(styles) => Some(styles),
|
||||
Self::Skip => None,
|
||||
}
|
||||
}
|
||||
@ -67,14 +67,14 @@ impl FlowChild {
|
||||
impl Debug for FlowChild {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::Spacing(node) => node.fmt(f),
|
||||
Self::Node(node) => node.fmt(f),
|
||||
Self::Break(styles) => {
|
||||
if f.alternate() {
|
||||
styles.fmt(f)?;
|
||||
}
|
||||
write!(f, "Break")
|
||||
}
|
||||
Self::Spacing(node) => node.fmt(f),
|
||||
Self::Node(node) => node.fmt(f),
|
||||
Self::Skip => f.pad("Skip"),
|
||||
}
|
||||
}
|
||||
@ -84,10 +84,10 @@ impl Debug for FlowChild {
|
||||
struct FlowLayouter<'a> {
|
||||
/// The flow node to layout.
|
||||
children: &'a [FlowChild],
|
||||
/// Whether the flow should expand to fill the region.
|
||||
expand: Spec<bool>,
|
||||
/// The regions to layout children into.
|
||||
regions: Regions,
|
||||
/// Whether the flow should expand to fill the region.
|
||||
expand: Spec<bool>,
|
||||
/// The full size of `regions.current` that was available before we started
|
||||
/// subtracting.
|
||||
full: Size,
|
||||
@ -115,19 +115,18 @@ enum FlowItem {
|
||||
|
||||
impl<'a> FlowLayouter<'a> {
|
||||
/// Create a new flow layouter.
|
||||
fn new(flow: &'a FlowNode, regions: &Regions) -> Self {
|
||||
fn new(flow: &'a FlowNode, mut regions: Regions) -> Self {
|
||||
let expand = regions.expand;
|
||||
let full = regions.current;
|
||||
|
||||
// Disable vertical expansion for children.
|
||||
let mut regions = regions.clone();
|
||||
regions.expand.y = false;
|
||||
|
||||
Self {
|
||||
children: &flow.0,
|
||||
regions,
|
||||
expand,
|
||||
full,
|
||||
regions,
|
||||
used: Size::zero(),
|
||||
fr: Fractional::zero(),
|
||||
items: vec![],
|
||||
@ -139,6 +138,16 @@ impl<'a> FlowLayouter<'a> {
|
||||
fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Rc<Frame>>> {
|
||||
for child in self.children {
|
||||
match child {
|
||||
FlowChild::Spacing(node) => {
|
||||
self.layout_spacing(node.kind);
|
||||
}
|
||||
FlowChild::Node(node) => {
|
||||
if self.regions.is_full() {
|
||||
self.finish_region();
|
||||
}
|
||||
|
||||
self.layout_node(ctx, node);
|
||||
}
|
||||
FlowChild::Break(styles) => {
|
||||
let chain = styles.chain(&ctx.styles);
|
||||
let em = chain.get(TextNode::SIZE).abs;
|
||||
@ -148,20 +157,6 @@ impl<'a> FlowLayouter<'a> {
|
||||
FlowChild::Skip => {
|
||||
self.finish_region();
|
||||
}
|
||||
FlowChild::Spacing(node) => match node.kind {
|
||||
SpacingKind::Linear(v) => self.layout_absolute(v),
|
||||
SpacingKind::Fractional(v) => {
|
||||
self.items.push(FlowItem::Fractional(v));
|
||||
self.fr += v;
|
||||
}
|
||||
},
|
||||
FlowChild::Node(node) => {
|
||||
if self.regions.is_full() {
|
||||
self.finish_region();
|
||||
}
|
||||
|
||||
self.layout_node(ctx, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,6 +164,17 @@ impl<'a> FlowLayouter<'a> {
|
||||
self.finished
|
||||
}
|
||||
|
||||
/// Layout spacing.
|
||||
fn layout_spacing(&mut self, spacing: SpacingKind) {
|
||||
match spacing {
|
||||
SpacingKind::Linear(v) => self.layout_absolute(v),
|
||||
SpacingKind::Fractional(v) => {
|
||||
self.items.push(FlowItem::Fractional(v));
|
||||
self.fr += v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Layout absolute spacing.
|
||||
fn layout_absolute(&mut self, amount: Linear) {
|
||||
// Resolve the linear, limiting it to the remaining available space.
|
||||
|
@ -15,7 +15,7 @@ pub fn grid(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
||||
column_gutter.unwrap_or_else(|| base_gutter.clone()),
|
||||
row_gutter.unwrap_or(base_gutter),
|
||||
),
|
||||
children: args.all().map(Node::into_block).collect(),
|
||||
children: args.all().collect(),
|
||||
}))
|
||||
}
|
||||
|
||||
@ -87,8 +87,6 @@ castable! {
|
||||
struct GridLayouter<'a> {
|
||||
/// The children of the grid.
|
||||
children: &'a [PackedNode],
|
||||
/// Whether the grid should expand to fill the region.
|
||||
expand: Spec<bool>,
|
||||
/// The column tracks including gutter tracks.
|
||||
cols: Vec<TrackSizing>,
|
||||
/// The row tracks including gutter tracks.
|
||||
@ -97,6 +95,10 @@ struct GridLayouter<'a> {
|
||||
regions: Regions,
|
||||
/// Resolved column sizes.
|
||||
rcols: Vec<Length>,
|
||||
/// Rows in the current region.
|
||||
lrows: Vec<Row>,
|
||||
/// Whether the grid should expand to fill the region.
|
||||
expand: Spec<bool>,
|
||||
/// The full height of the current region.
|
||||
full: Length,
|
||||
/// The used-up size of the current region. The horizontal size is
|
||||
@ -104,8 +106,6 @@ struct GridLayouter<'a> {
|
||||
used: Size,
|
||||
/// The sum of fractional ratios in the current region.
|
||||
fr: Fractional,
|
||||
/// Rows in the current region.
|
||||
lrows: Vec<Row>,
|
||||
/// Constraints for the active region.
|
||||
cts: Constraints,
|
||||
/// Frames for finished regions.
|
||||
@ -161,22 +161,26 @@ impl<'a> GridLayouter<'a> {
|
||||
cols.pop();
|
||||
rows.pop();
|
||||
|
||||
let expand = regions.expand;
|
||||
let full = regions.current.y;
|
||||
let rcols = vec![Length::zero(); cols.len()];
|
||||
let lrows = vec![];
|
||||
|
||||
// We use the regions for auto row measurement. Since at that moment,
|
||||
// columns are already sized, we can enable horizontal expansion.
|
||||
let expand = regions.expand;
|
||||
regions.expand = Spec::new(true, false);
|
||||
|
||||
Self {
|
||||
children: &grid.children,
|
||||
expand,
|
||||
rcols: vec![Length::zero(); cols.len()],
|
||||
cols,
|
||||
rows,
|
||||
full: regions.current.y,
|
||||
regions,
|
||||
rcols,
|
||||
lrows,
|
||||
expand,
|
||||
full,
|
||||
used: Size::zero(),
|
||||
fr: Fractional::zero(),
|
||||
lrows: vec![],
|
||||
cts: Constraints::new(expand),
|
||||
finished: vec![],
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ pub struct HeadingNode {
|
||||
#[properties]
|
||||
impl HeadingNode {
|
||||
/// The heading's font family.
|
||||
pub const FAMILY: Smart<String> = Smart::Auto;
|
||||
pub const FAMILY: Smart<FontFamily> = Smart::Auto;
|
||||
/// The fill color of heading in the text. Just the surrounding text color
|
||||
/// if `auto`.
|
||||
pub const FILL: Smart<Paint> = Smart::Auto;
|
||||
@ -25,7 +25,7 @@ impl HeadingNode {
|
||||
impl Construct for HeadingNode {
|
||||
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Node> {
|
||||
Ok(Node::block(Self {
|
||||
child: args.expect::<Node>("body")?.into_block(),
|
||||
child: args.expect("body")?,
|
||||
level: args.named("level")?.unwrap_or(1),
|
||||
}))
|
||||
}
|
||||
@ -50,8 +50,9 @@ impl Layout for HeadingNode {
|
||||
ctx.styles.set(TextNode::SIZE, Relative::new(upscale).into());
|
||||
|
||||
if let Smart::Custom(family) = ctx.styles.get_ref(Self::FAMILY) {
|
||||
let list: Vec<_> = std::iter::once(FontFamily::named(family))
|
||||
.chain(ctx.styles.get_ref(TextNode::FAMILY_LIST).iter().cloned())
|
||||
let list = std::iter::once(family)
|
||||
.chain(ctx.styles.get_ref(TextNode::FAMILY_LIST))
|
||||
.cloned()
|
||||
.collect();
|
||||
ctx.styles.set(TextNode::FAMILY_LIST, list);
|
||||
}
|
||||
|
@ -26,12 +26,7 @@ impl<L: Labelling> Construct for ListNode<L> {
|
||||
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Node> {
|
||||
Ok(args
|
||||
.all()
|
||||
.map(|node: Node| {
|
||||
Node::block(Self {
|
||||
child: node.into_block(),
|
||||
labelling: L::default(),
|
||||
})
|
||||
})
|
||||
.map(|child: PackedNode| Node::block(Self { child, labelling: L::default() }))
|
||||
.sum())
|
||||
}
|
||||
}
|
||||
|
@ -193,3 +193,9 @@ castable! {
|
||||
Expected: "string",
|
||||
Value::Str(string) => string.into(),
|
||||
}
|
||||
|
||||
castable! {
|
||||
PackedNode,
|
||||
Expected: "node",
|
||||
Value::Node(node) => node.into_block(),
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ pub fn pad(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
||||
let top = args.named("top")?;
|
||||
let right = args.named("right")?;
|
||||
let bottom = args.named("bottom")?;
|
||||
let body: Node = args.expect("body")?;
|
||||
let body: PackedNode = args.expect("body")?;
|
||||
let padding = Sides::new(
|
||||
left.or(all).unwrap_or_default(),
|
||||
top.or(all).unwrap_or_default(),
|
||||
@ -17,7 +17,7 @@ pub fn pad(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
||||
bottom.or(all).unwrap_or_default(),
|
||||
);
|
||||
|
||||
Ok(Value::block(body.into_block().padded(padding)))
|
||||
Ok(Value::block(body.padded(padding)))
|
||||
}
|
||||
|
||||
/// A node that adds padding to its child.
|
||||
|
@ -44,8 +44,8 @@ impl PageNode {
|
||||
impl Construct for PageNode {
|
||||
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Node> {
|
||||
Ok(Node::Page(Self {
|
||||
child: args.expect::<Node>("body")?.into_block(),
|
||||
styles: Styles::new(),
|
||||
child: args.expect("body")?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
@ -114,6 +114,7 @@ impl PageNode {
|
||||
bottom: ctx.styles.get(Self::BOTTOM).unwrap_or(default.bottom),
|
||||
};
|
||||
|
||||
// Realize columns with columns node.
|
||||
let columns = ctx.styles.get(Self::COLUMNS);
|
||||
let child = if columns.get() > 1 {
|
||||
ColumnsNode {
|
||||
@ -126,14 +127,14 @@ impl PageNode {
|
||||
self.child.clone()
|
||||
};
|
||||
|
||||
// Pad the child.
|
||||
let padded = PadNode { child, padding }.pack();
|
||||
// Realize margins with padding node.
|
||||
let child = PadNode { child, padding }.pack();
|
||||
|
||||
// Layout the child.
|
||||
let expand = size.map(Length::is_finite);
|
||||
let regions = Regions::repeat(size, size, expand);
|
||||
let mut frames: Vec<_> =
|
||||
padded.layout(ctx, ®ions).into_iter().map(|c| c.item).collect();
|
||||
child.layout(ctx, ®ions).into_iter().map(|c| c.item).collect();
|
||||
|
||||
// Add background fill if requested.
|
||||
if let Some(fill) = ctx.styles.get(Self::FILL) {
|
||||
@ -238,12 +239,12 @@ macro_rules! papers {
|
||||
}
|
||||
|
||||
impl FromStr for Paper {
|
||||
type Err = ParsePaperError;
|
||||
type Err = PaperError;
|
||||
|
||||
fn from_str(name: &str) -> Result<Self, Self::Err> {
|
||||
match name.to_lowercase().as_str() {
|
||||
$($($pats)* => Ok(Self::$var),)*
|
||||
_ => Err(ParsePaperError),
|
||||
_ => Err(PaperError),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -413,12 +414,12 @@ castable! {
|
||||
|
||||
/// The error when parsing a [`Paper`] from a string fails.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct ParsePaperError;
|
||||
pub struct PaperError;
|
||||
|
||||
impl Display for ParsePaperError {
|
||||
impl Display for PaperError {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad("invalid paper name")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for ParsePaperError {}
|
||||
impl std::error::Error for PaperError {}
|
||||
|
@ -30,7 +30,7 @@ impl ParNode {
|
||||
impl Construct for ParNode {
|
||||
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Node> {
|
||||
// Lift to a block so that it doesn't merge with adjacent stuff.
|
||||
Ok(Node::Block(args.expect::<Node>("body")?.into_block()))
|
||||
Ok(Node::Block(args.expect("body")?))
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,10 +60,8 @@ impl Set for ParNode {
|
||||
bail!(span, "must be horizontal");
|
||||
}
|
||||
Some(v)
|
||||
} else if let Some(dir) = dir {
|
||||
Some(if dir == Dir::LTR { Align::Left } else { Align::Right })
|
||||
} else {
|
||||
None
|
||||
dir.map(|dir| dir.start().into())
|
||||
};
|
||||
|
||||
styles.set_opt(Self::DIR, dir);
|
||||
@ -85,7 +83,8 @@ impl Layout for ParNode {
|
||||
let text = self.collect_text();
|
||||
|
||||
// Find out the BiDi embedding levels.
|
||||
let bidi = BidiInfo::new(&text, Level::from_dir(ctx.styles.get(Self::DIR)));
|
||||
let level = Level::from_dir(ctx.styles.get(Self::DIR));
|
||||
let bidi = BidiInfo::new(&text, level);
|
||||
|
||||
// Prepare paragraph layout by building a representation on which we can
|
||||
// do line breaking without layouting each and every line from scratch.
|
||||
@ -255,7 +254,7 @@ impl<'a> ParLayouter<'a> {
|
||||
let subrange = start .. cursor;
|
||||
let text = &bidi.text[subrange.clone()];
|
||||
let styles = node.styles.chain(&ctx.styles);
|
||||
let shaped = shape(&mut ctx.fonts, text, styles, level.dir());
|
||||
let shaped = shape(ctx.fonts, text, styles, level.dir());
|
||||
items.push(ParItem::Text(shaped));
|
||||
ranges.push(subrange);
|
||||
}
|
||||
@ -446,7 +445,7 @@ impl<'a> LineLayout<'a> {
|
||||
// empty string.
|
||||
if !range.is_empty() || rest.is_empty() {
|
||||
// Reshape that part.
|
||||
let reshaped = shaped.reshape(&mut ctx.fonts, range);
|
||||
let reshaped = shaped.reshape(ctx.fonts, range);
|
||||
last = Some(ParItem::Text(reshaped));
|
||||
}
|
||||
|
||||
@ -467,7 +466,7 @@ impl<'a> LineLayout<'a> {
|
||||
// Reshape if necessary.
|
||||
if range.len() < shaped.text.len() {
|
||||
if !range.is_empty() {
|
||||
let reshaped = shaped.reshape(&mut ctx.fonts, range);
|
||||
let reshaped = shaped.reshape(ctx.fonts, range);
|
||||
first = Some(ParItem::Text(reshaped));
|
||||
}
|
||||
|
||||
@ -531,7 +530,7 @@ impl<'a> LineLayout<'a> {
|
||||
match item {
|
||||
ParItem::Absolute(v) => offset += *v,
|
||||
ParItem::Fractional(v) => offset += v.resolve(self.fr, remaining),
|
||||
ParItem::Text(shaped) => position(shaped.build(&ctx.fonts)),
|
||||
ParItem::Text(shaped) => position(shaped.build(ctx.fonts)),
|
||||
ParItem::Frame(frame) => position(frame.clone()),
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,9 @@ pub fn place(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
||||
let aligns = args.find().unwrap_or(Spec::new(Some(Align::Left), None));
|
||||
let tx = args.named("dx")?.unwrap_or_default();
|
||||
let ty = args.named("dy")?.unwrap_or_default();
|
||||
let body: Node = args.expect("body")?;
|
||||
let body: PackedNode = args.expect("body")?;
|
||||
Ok(Value::block(PlacedNode(
|
||||
body.into_block().moved(Point::new(tx, ty)).aligned(aligns),
|
||||
body.moved(Point::new(tx, ty)).aligned(aligns),
|
||||
)))
|
||||
}
|
||||
|
||||
|
@ -79,9 +79,7 @@ fn shape_impl(
|
||||
}
|
||||
|
||||
// The shape's contents.
|
||||
let child = args
|
||||
.find()
|
||||
.map(|body: Node| body.into_block().padded(Sides::splat(padding)));
|
||||
let child = args.find().map(|body: PackedNode| body.padded(Sides::splat(padding)));
|
||||
|
||||
Ok(Value::inline(
|
||||
ShapeNode { kind, fill, stroke, child }
|
||||
|
@ -6,16 +6,14 @@ use super::prelude::*;
|
||||
pub fn box_(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
||||
let width = args.named("width")?;
|
||||
let height = args.named("height")?;
|
||||
let body: Node = args.find().unwrap_or_default();
|
||||
Ok(Value::inline(
|
||||
body.into_block().sized(Spec::new(width, height)),
|
||||
))
|
||||
let body: PackedNode = args.find().unwrap_or_default();
|
||||
Ok(Value::inline(body.sized(Spec::new(width, height))))
|
||||
}
|
||||
|
||||
/// `block`: Place content into the flow.
|
||||
pub fn block(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
||||
let body: Node = args.find().unwrap_or_default();
|
||||
Ok(Value::block(body.into_block()))
|
||||
let body: PackedNode = args.find().unwrap_or_default();
|
||||
Ok(Value::block(body))
|
||||
}
|
||||
|
||||
/// A node that sizes its child.
|
||||
|
@ -1,33 +1,15 @@
|
||||
//! Side-by-side layout of nodes along an axis.
|
||||
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
use super::prelude::*;
|
||||
use super::{AlignNode, SpacingKind, SpacingNode};
|
||||
|
||||
/// `stack`: Stack children along an axis.
|
||||
pub fn stack(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
||||
let dir = args.named("dir")?.unwrap_or(Dir::TTB);
|
||||
let spacing = args.named("spacing")?;
|
||||
|
||||
let mut children = vec![];
|
||||
let mut deferred = None;
|
||||
|
||||
// Build the list of stack children.
|
||||
for child in args.all() {
|
||||
match child {
|
||||
StackChild::Spacing(_) => deferred = None,
|
||||
StackChild::Node(_) => {
|
||||
if let Some(v) = deferred {
|
||||
children.push(StackChild::spacing(v));
|
||||
}
|
||||
deferred = spacing;
|
||||
}
|
||||
}
|
||||
children.push(child);
|
||||
}
|
||||
|
||||
Ok(Value::block(StackNode { dir, children }))
|
||||
Ok(Value::block(StackNode {
|
||||
dir: args.named("dir")?.unwrap_or(Dir::TTB),
|
||||
spacing: args.named("spacing")?,
|
||||
children: args.all().collect(),
|
||||
}))
|
||||
}
|
||||
|
||||
/// A node that stacks its children.
|
||||
@ -35,6 +17,8 @@ pub fn stack(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
||||
pub struct StackNode {
|
||||
/// The stacking direction.
|
||||
pub dir: Dir,
|
||||
/// The spacing between non-spacing children.
|
||||
pub spacing: Option<SpacingKind>,
|
||||
/// The children to be stacked.
|
||||
pub children: Vec<StackChild>,
|
||||
}
|
||||
@ -45,7 +29,7 @@ impl Layout for StackNode {
|
||||
ctx: &mut LayoutContext,
|
||||
regions: &Regions,
|
||||
) -> Vec<Constrained<Rc<Frame>>> {
|
||||
StackLayouter::new(self, regions).layout(ctx)
|
||||
StackLayouter::new(self, regions.clone()).layout(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,9 +42,8 @@ pub enum StackChild {
|
||||
Node(PackedNode),
|
||||
}
|
||||
|
||||
impl StackChild {
|
||||
/// Create a spacing node from a spacing kind.
|
||||
pub fn spacing(kind: SpacingKind) -> Self {
|
||||
impl From<SpacingKind> for StackChild {
|
||||
fn from(kind: SpacingKind) -> Self {
|
||||
Self::Spacing(SpacingNode { kind, styles: Styles::new() })
|
||||
}
|
||||
}
|
||||
@ -77,23 +60,27 @@ impl Debug for StackChild {
|
||||
castable! {
|
||||
StackChild,
|
||||
Expected: "linear, fractional or template",
|
||||
Value::Length(v) => Self::spacing(SpacingKind::Linear(v.into())),
|
||||
Value::Relative(v) => Self::spacing(SpacingKind::Linear(v.into())),
|
||||
Value::Linear(v) => Self::spacing(SpacingKind::Linear(v)),
|
||||
Value::Fractional(v) => Self::spacing(SpacingKind::Fractional(v)),
|
||||
Value::Length(v) => SpacingKind::Linear(v.into()).into(),
|
||||
Value::Relative(v) => SpacingKind::Linear(v.into()).into(),
|
||||
Value::Linear(v) => SpacingKind::Linear(v).into(),
|
||||
Value::Fractional(v) => SpacingKind::Fractional(v).into(),
|
||||
Value::Node(v) => Self::Node(v.into_block()),
|
||||
}
|
||||
|
||||
/// Performs stack layout.
|
||||
struct StackLayouter<'a> {
|
||||
/// The stack node to layout.
|
||||
stack: &'a StackNode,
|
||||
/// The axis of the block direction.
|
||||
/// The flow node to layout.
|
||||
children: &'a [StackChild],
|
||||
/// The stacking direction.
|
||||
dir: Dir,
|
||||
/// The axis of the stacking direction.
|
||||
axis: SpecAxis,
|
||||
/// Whether the stack should expand to fill the region.
|
||||
expand: Spec<bool>,
|
||||
/// The spacing between non-spacing children.
|
||||
spacing: Option<SpacingKind>,
|
||||
/// The regions to layout children into.
|
||||
regions: Regions,
|
||||
/// Whether the stack should expand to fill the region.
|
||||
expand: Spec<bool>,
|
||||
/// The full size of `regions.current` that was available before we started
|
||||
/// subtracting.
|
||||
full: Size,
|
||||
@ -119,21 +106,23 @@ enum StackItem {
|
||||
|
||||
impl<'a> StackLayouter<'a> {
|
||||
/// Create a new stack layouter.
|
||||
fn new(stack: &'a StackNode, regions: &Regions) -> Self {
|
||||
let axis = stack.dir.axis();
|
||||
fn new(stack: &'a StackNode, mut regions: Regions) -> Self {
|
||||
let dir = stack.dir;
|
||||
let axis = dir.axis();
|
||||
let expand = regions.expand;
|
||||
let full = regions.current;
|
||||
|
||||
// Disable expansion along the block axis for children.
|
||||
let mut regions = regions.clone();
|
||||
regions.expand.set(axis, false);
|
||||
|
||||
Self {
|
||||
stack,
|
||||
children: &stack.children,
|
||||
dir,
|
||||
axis,
|
||||
spacing: stack.spacing,
|
||||
regions,
|
||||
expand,
|
||||
full,
|
||||
regions,
|
||||
used: Gen::zero(),
|
||||
fr: Fractional::zero(),
|
||||
items: vec![],
|
||||
@ -143,21 +132,26 @@ impl<'a> StackLayouter<'a> {
|
||||
|
||||
/// Layout all children.
|
||||
fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Rc<Frame>>> {
|
||||
for child in &self.stack.children {
|
||||
// Spacing to insert before the next node.
|
||||
let mut deferred = None;
|
||||
|
||||
for child in self.children {
|
||||
match child {
|
||||
StackChild::Spacing(node) => match node.kind {
|
||||
SpacingKind::Linear(v) => self.layout_absolute(v),
|
||||
SpacingKind::Fractional(v) => {
|
||||
self.items.push(StackItem::Fractional(v));
|
||||
self.fr += v;
|
||||
}
|
||||
},
|
||||
StackChild::Spacing(node) => {
|
||||
self.layout_spacing(node.kind);
|
||||
deferred = None;
|
||||
}
|
||||
StackChild::Node(node) => {
|
||||
if let Some(kind) = deferred {
|
||||
self.layout_spacing(kind);
|
||||
}
|
||||
|
||||
if self.regions.is_full() {
|
||||
self.finish_region();
|
||||
}
|
||||
|
||||
self.layout_node(ctx, node);
|
||||
deferred = self.spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,6 +160,17 @@ impl<'a> StackLayouter<'a> {
|
||||
self.finished
|
||||
}
|
||||
|
||||
/// Layout spacing.
|
||||
fn layout_spacing(&mut self, spacing: SpacingKind) {
|
||||
match spacing {
|
||||
SpacingKind::Linear(v) => self.layout_absolute(v),
|
||||
SpacingKind::Fractional(v) => {
|
||||
self.items.push(StackItem::Fractional(v));
|
||||
self.fr += v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Layout absolute spacing.
|
||||
fn layout_absolute(&mut self, amount: Linear) {
|
||||
// Resolve the linear, limiting it to the remaining available space.
|
||||
@ -183,7 +188,7 @@ impl<'a> StackLayouter<'a> {
|
||||
let align = node
|
||||
.downcast::<AlignNode>()
|
||||
.and_then(|node| node.aligns.get(self.axis))
|
||||
.unwrap_or(self.stack.dir.start().into());
|
||||
.unwrap_or(self.dir.start().into());
|
||||
|
||||
let frames = node.layout(ctx, &self.regions);
|
||||
let len = frames.len();
|
||||
@ -218,7 +223,7 @@ impl<'a> StackLayouter<'a> {
|
||||
|
||||
let mut output = Frame::new(size);
|
||||
let mut cursor = Length::zero();
|
||||
let mut ruler: Align = self.stack.dir.start().into();
|
||||
let mut ruler: Align = self.dir.start().into();
|
||||
|
||||
// Place all frames.
|
||||
for item in self.items.drain(..) {
|
||||
@ -230,7 +235,7 @@ impl<'a> StackLayouter<'a> {
|
||||
cursor += v.resolve(self.fr, remaining);
|
||||
}
|
||||
StackItem::Frame(frame, align) => {
|
||||
if self.stack.dir.is_positive() {
|
||||
if self.dir.is_positive() {
|
||||
ruler = ruler.max(align);
|
||||
} else {
|
||||
ruler = ruler.min(align);
|
||||
@ -240,7 +245,7 @@ impl<'a> StackLayouter<'a> {
|
||||
let parent = size.get(self.axis);
|
||||
let child = frame.size.get(self.axis);
|
||||
let block = ruler.resolve(parent - self.used.main)
|
||||
+ if self.stack.dir.is_positive() {
|
||||
+ if self.dir.is_positive() {
|
||||
cursor
|
||||
} else {
|
||||
self.used.main - child - cursor
|
||||
|
@ -173,13 +173,6 @@ pub enum FontFamily {
|
||||
Named(NamedFamily),
|
||||
}
|
||||
|
||||
impl FontFamily {
|
||||
/// Create a named font family variant, directly from a string.
|
||||
pub fn named(string: &str) -> Self {
|
||||
Self::Named(NamedFamily::new(string))
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FontFamily {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
@ -193,13 +186,13 @@ impl Debug for FontFamily {
|
||||
|
||||
dynamic! {
|
||||
FontFamily: "font family",
|
||||
Value::Str(string) => Self::named(&string),
|
||||
Value::Str(string) => Self::Named(NamedFamily::new(&string)),
|
||||
}
|
||||
|
||||
castable! {
|
||||
Vec<FontFamily>,
|
||||
Expected: "string, generic family or array thereof",
|
||||
Value::Str(string) => vec![FontFamily::named(&string)],
|
||||
Value::Str(string) => vec![FontFamily::Named(NamedFamily::new(&string))],
|
||||
Value::Array(values) => {
|
||||
values.into_iter().filter_map(|v| v.cast().ok()).collect()
|
||||
},
|
||||
|
@ -28,15 +28,13 @@ pub fn rotate(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
||||
}
|
||||
|
||||
fn transform_impl(args: &mut Args, transform: Transform) -> TypResult<Value> {
|
||||
let body: Node = args.expect("body")?;
|
||||
let body: PackedNode = args.expect("body")?;
|
||||
let origin = args
|
||||
.named("origin")?
|
||||
.unwrap_or(Spec::splat(None))
|
||||
.unwrap_or(Align::CENTER_HORIZON);
|
||||
|
||||
Ok(Value::inline(
|
||||
body.into_block().transformed(transform, origin),
|
||||
))
|
||||
Ok(Value::inline(body.transformed(transform, origin)))
|
||||
}
|
||||
|
||||
/// A node that transforms its child without affecting layout.
|
||||
|
@ -275,13 +275,13 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
|
||||
|
||||
Some(NodeKind::Error(_, _)) => {
|
||||
p.eat();
|
||||
Err(())
|
||||
Err(ParseError)
|
||||
}
|
||||
|
||||
// Nothing.
|
||||
_ => {
|
||||
p.expected("expression");
|
||||
Err(())
|
||||
Err(ParseError)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -428,7 +428,7 @@ fn item(p: &mut Parser) -> ParseResult<NodeKind> {
|
||||
marker.end(p, error);
|
||||
p.eat();
|
||||
expr(p).ok();
|
||||
Err(())
|
||||
Err(ParseError)
|
||||
}
|
||||
})?;
|
||||
|
||||
@ -519,7 +519,7 @@ fn args(p: &mut Parser, direct: bool, brackets: bool) -> ParseResult {
|
||||
Some(NodeKind::LeftBracket) if brackets => {}
|
||||
_ => {
|
||||
p.expected("argument list");
|
||||
return Err(());
|
||||
return Err(ParseError);
|
||||
}
|
||||
}
|
||||
|
||||
@ -689,7 +689,7 @@ fn ident(p: &mut Parser) -> ParseResult {
|
||||
}
|
||||
_ => {
|
||||
p.expected("identifier");
|
||||
Err(())
|
||||
Err(ParseError)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -701,7 +701,7 @@ fn body(p: &mut Parser) -> ParseResult {
|
||||
Some(NodeKind::LeftBrace) => block(p),
|
||||
_ => {
|
||||
p.expected_at("body");
|
||||
return Err(());
|
||||
return Err(ParseError);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -1,13 +1,10 @@
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::mem;
|
||||
|
||||
use super::{TokenMode, Tokens};
|
||||
use crate::syntax::{ErrorPos, Green, GreenData, GreenNode, NodeKind};
|
||||
use crate::util::EcoString;
|
||||
|
||||
/// Allows parser methods to use the try operator. Not exposed as the parser
|
||||
/// recovers from all errors.
|
||||
pub(crate) type ParseResult<T = ()> = Result<T, ()>;
|
||||
|
||||
/// A convenient token-based parser.
|
||||
pub struct Parser<'s> {
|
||||
/// An iterator over the source tokens.
|
||||
@ -121,7 +118,7 @@ impl<'s> Parser<'s> {
|
||||
if !eaten {
|
||||
self.expected_at(t.as_str());
|
||||
}
|
||||
if eaten { Ok(()) } else { Err(()) }
|
||||
if eaten { Ok(()) } else { Err(ParseError) }
|
||||
}
|
||||
|
||||
/// Eat, debug-asserting that the token is the given one.
|
||||
@ -448,3 +445,19 @@ pub enum Group {
|
||||
/// A group for import items, ended by a semicolon, line break or `from`.
|
||||
Imports,
|
||||
}
|
||||
|
||||
/// Allows parser methods to use the try operator. Never returned top-level
|
||||
/// because the parser recovers from all errors.
|
||||
pub type ParseResult<T = ()> = Result<T, ParseError>;
|
||||
|
||||
/// The error type for parsing.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct ParseError;
|
||||
|
||||
impl Display for ParseError {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad("failed to parse")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for ParseError {}
|
||||
|
@ -21,6 +21,7 @@ pub trait Pretty {
|
||||
}
|
||||
|
||||
/// A buffer into which items can be pretty printed.
|
||||
#[derive(Default)]
|
||||
pub struct Printer {
|
||||
buf: String,
|
||||
}
|
||||
@ -28,7 +29,7 @@ pub struct Printer {
|
||||
impl Printer {
|
||||
/// Create a new pretty printer.
|
||||
pub fn new() -> Self {
|
||||
Self { buf: String::new() }
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Push a character into the buffer.
|
||||
|
Loading…
x
Reference in New Issue
Block a user