mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Streamline generic layouting primitives 🛫
This commit is contained in:
parent
93eaafb236
commit
5a7a32a9ba
@ -10,7 +10,7 @@ use std::str::FromStr;
|
|||||||
/// [page: background=#423abaff]
|
/// [page: background=#423abaff]
|
||||||
/// ^^^^^^^^
|
/// ^^^^^^^^
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
pub struct RgbaColor {
|
pub struct RgbaColor {
|
||||||
/// Red channel.
|
/// Red channel.
|
||||||
pub r: u8,
|
pub r: u8,
|
||||||
|
@ -17,7 +17,7 @@ pub struct Diag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// How severe / important a diagnostic is.
|
/// How severe / important a diagnostic is.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
|
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
|
||||||
pub enum Level {
|
pub enum Level {
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
use fontdock::{fallback, FallbackTree, FontStretch, FontStyle, FontVariant, FontWeight};
|
use fontdock::{fallback, FallbackTree, FontStretch, FontStyle, FontVariant, FontWeight};
|
||||||
|
|
||||||
use super::Scope;
|
use super::Scope;
|
||||||
use crate::geom::{Insets, Linear, Sides, Size};
|
use crate::geom::{Insets, Linear, Size};
|
||||||
use crate::layout::{Dir, GenAlign, LayoutAlign, LayoutSystem};
|
use crate::layout::{Dir, GenAlign, LayoutAlign, LayoutSystem, Sides};
|
||||||
use crate::length::Length;
|
use crate::length::Length;
|
||||||
use crate::paper::{Paper, PaperClass, PAPER_A4};
|
use crate::paper::{Paper, PaperClass, PAPER_A4};
|
||||||
|
|
||||||
|
128
src/geom.rs
128
src/geom.rs
@ -12,17 +12,11 @@ use crate::layout::primitive::{Dir, GenAlign, LayoutAlign, LayoutSystem, SpecAxi
|
|||||||
///
|
///
|
||||||
/// [sizes]: ../../kurbo/struct.Size.html
|
/// [sizes]: ../../kurbo/struct.Size.html
|
||||||
pub trait SizeExt {
|
pub trait SizeExt {
|
||||||
/// Return the primary component of this specialized size.
|
/// Return the component for the specified axis.
|
||||||
fn primary(self, sys: LayoutSystem) -> f64;
|
fn get(self, axis: SpecAxis) -> f64;
|
||||||
|
|
||||||
/// Borrow the primary component of this specialized size mutably.
|
/// Borrow the component for the specified axis mutably.
|
||||||
fn primary_mut(&mut self, sys: LayoutSystem) -> &mut f64;
|
fn get_mut(&mut self, axis: SpecAxis) -> &mut f64;
|
||||||
|
|
||||||
/// Return the secondary component of this specialized size.
|
|
||||||
fn secondary(self, sys: LayoutSystem) -> f64;
|
|
||||||
|
|
||||||
/// Borrow the secondary component of this specialized size mutably.
|
|
||||||
fn secondary_mut(&mut self, sys: LayoutSystem) -> &mut f64;
|
|
||||||
|
|
||||||
/// Returns the generalized version of a `Size` based on the layouting
|
/// Returns the generalized version of a `Size` based on the layouting
|
||||||
/// system, that is:
|
/// system, that is:
|
||||||
@ -38,44 +32,26 @@ pub trait SizeExt {
|
|||||||
/// values are smaller or equal.
|
/// values are smaller or equal.
|
||||||
fn fits(self, other: Self) -> bool;
|
fn fits(self, other: Self) -> bool;
|
||||||
|
|
||||||
/// The anchor position along the given axis for an item with the given
|
/// The anchor position for an object to be aligned according to `align` in
|
||||||
/// alignment in a container with this size.
|
/// a container with this size.
|
||||||
///
|
///
|
||||||
/// This assumes the size to be generalized such that `x` corresponds to the
|
/// This assumes the size to be generalized such that `width` corresponds to
|
||||||
/// primary axis.
|
/// the primary and `height` to the secondary axis.
|
||||||
fn anchor(self, align: LayoutAlign, sys: LayoutSystem) -> Point;
|
fn anchor(self, align: LayoutAlign, sys: LayoutSystem) -> Point;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SizeExt for Size {
|
impl SizeExt for Size {
|
||||||
fn primary(self, sys: LayoutSystem) -> f64 {
|
fn get(self, axis: SpecAxis) -> f64 {
|
||||||
if sys.primary.axis() == SpecAxis::Horizontal {
|
match axis {
|
||||||
self.width
|
SpecAxis::Horizontal => self.width,
|
||||||
} else {
|
SpecAxis::Vertical => self.height,
|
||||||
self.height
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn primary_mut(&mut self, sys: LayoutSystem) -> &mut f64 {
|
fn get_mut(&mut self, axis: SpecAxis) -> &mut f64 {
|
||||||
if sys.primary.axis() == SpecAxis::Horizontal {
|
match axis {
|
||||||
&mut self.width
|
SpecAxis::Horizontal => &mut self.width,
|
||||||
} else {
|
SpecAxis::Vertical => &mut self.height,
|
||||||
&mut self.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn secondary(self, sys: LayoutSystem) -> f64 {
|
|
||||||
if sys.primary.axis() == SpecAxis::Horizontal {
|
|
||||||
self.height
|
|
||||||
} else {
|
|
||||||
self.width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn secondary_mut(&mut self, sys: LayoutSystem) -> &mut f64 {
|
|
||||||
if sys.primary.axis() == SpecAxis::Horizontal {
|
|
||||||
&mut self.height
|
|
||||||
} else {
|
|
||||||
&mut self.width
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,8 +63,8 @@ impl SizeExt for Size {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn specialized(self, sys: LayoutSystem) -> Self {
|
fn specialized(self, sys: LayoutSystem) -> Self {
|
||||||
// In fact, generalized is its own inverse. For reasons of clarity
|
// Even though generalized is its own inverse, we still have this second
|
||||||
// at the call site, we still have this second function.
|
// function, for clarity at the call-site.
|
||||||
self.generalized(sys)
|
self.generalized(sys)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +73,7 @@ impl SizeExt for Size {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn anchor(self, align: LayoutAlign, sys: LayoutSystem) -> Point {
|
fn anchor(self, align: LayoutAlign, sys: LayoutSystem) -> Point {
|
||||||
fn length_anchor(length: f64, align: GenAlign, dir: Dir) -> f64 {
|
fn anchor(length: f64, align: GenAlign, dir: Dir) -> f64 {
|
||||||
match (dir.is_positive(), align) {
|
match (dir.is_positive(), align) {
|
||||||
(true, GenAlign::Start) | (false, GenAlign::End) => 0.0,
|
(true, GenAlign::Start) | (false, GenAlign::End) => 0.0,
|
||||||
(_, GenAlign::Center) => length / 2.0,
|
(_, GenAlign::Center) => length / 2.0,
|
||||||
@ -106,8 +82,8 @@ impl SizeExt for Size {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Point::new(
|
Point::new(
|
||||||
length_anchor(self.width, align.primary, sys.primary),
|
anchor(self.width, align.primary, sys.primary),
|
||||||
length_anchor(self.height, align.secondary, sys.secondary),
|
anchor(self.height, align.secondary, sys.secondary),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,7 +92,12 @@ impl SizeExt for Size {
|
|||||||
///
|
///
|
||||||
/// [rectangles]: ../../kurbo/struct.Rect.html
|
/// [rectangles]: ../../kurbo/struct.Rect.html
|
||||||
pub trait RectExt {
|
pub trait RectExt {
|
||||||
/// Get a mutable reference to the value for the specified direction at the
|
/// Return the side identified by direction and alignment.
|
||||||
|
///
|
||||||
|
/// Center alignment is treated the same as origin alignment.
|
||||||
|
fn get(&mut self, dir: Dir, align: GenAlign) -> f64;
|
||||||
|
|
||||||
|
/// Get a mutable reference to the side identified by direction and
|
||||||
/// alignment.
|
/// alignment.
|
||||||
///
|
///
|
||||||
/// Center alignment is treated the same as origin alignment.
|
/// Center alignment is treated the same as origin alignment.
|
||||||
@ -124,6 +105,15 @@ pub trait RectExt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RectExt for Rect {
|
impl RectExt for Rect {
|
||||||
|
fn get(&mut self, dir: Dir, align: GenAlign) -> f64 {
|
||||||
|
match if align == GenAlign::End { dir.inv() } else { dir } {
|
||||||
|
Dir::LTR => self.x0,
|
||||||
|
Dir::TTB => self.y0,
|
||||||
|
Dir::RTL => self.x1,
|
||||||
|
Dir::BTT => self.y1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_mut(&mut self, dir: Dir, align: GenAlign) -> &mut f64 {
|
fn get_mut(&mut self, dir: Dir, align: GenAlign) -> &mut f64 {
|
||||||
match if align == GenAlign::End { dir.inv() } else { dir } {
|
match if align == GenAlign::End { dir.inv() } else { dir } {
|
||||||
Dir::LTR => &mut self.x0,
|
Dir::LTR => &mut self.x0,
|
||||||
@ -134,52 +124,6 @@ impl RectExt for Rect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A generic container for `[left, top, right, bottom]` values.
|
|
||||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
|
|
||||||
pub struct Sides<T> {
|
|
||||||
/// The value for the left side.
|
|
||||||
pub left: T,
|
|
||||||
/// The value for the top side.
|
|
||||||
pub top: T,
|
|
||||||
/// The value for the right side.
|
|
||||||
pub right: T,
|
|
||||||
/// The value for the bottom side.
|
|
||||||
pub bottom: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Sides<T> {
|
|
||||||
/// Create a new box from four sizes.
|
|
||||||
pub fn new(left: T, top: T, right: T, bottom: T) -> Self {
|
|
||||||
Self { left, top, right, bottom }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create an instance with all four components set to the same `value`.
|
|
||||||
pub fn uniform(value: T) -> Self
|
|
||||||
where
|
|
||||||
T: Clone,
|
|
||||||
{
|
|
||||||
Self {
|
|
||||||
left: value.clone(),
|
|
||||||
top: value.clone(),
|
|
||||||
right: value.clone(),
|
|
||||||
bottom: value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a mutable reference to the value for the specified direction at the
|
|
||||||
/// alignment.
|
|
||||||
///
|
|
||||||
/// Center alignment is treated the same as origin alignment.
|
|
||||||
pub fn get_mut(&mut self, dir: Dir, align: GenAlign) -> &mut T {
|
|
||||||
match if align == GenAlign::End { dir.inv() } else { dir } {
|
|
||||||
Dir::LTR => &mut self.left,
|
|
||||||
Dir::RTL => &mut self.right,
|
|
||||||
Dir::TTB => &mut self.top,
|
|
||||||
Dir::BTT => &mut self.bottom,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A function that depends linearly on one value.
|
/// A function that depends linearly on one value.
|
||||||
///
|
///
|
||||||
/// This represents a function `f(x) = rel * x + abs`.
|
/// This represents a function `f(x) = rel * x + abs`.
|
||||||
|
@ -67,7 +67,7 @@ impl LineLayouter {
|
|||||||
} else if align.primary > prev.primary {
|
} else if align.primary > prev.primary {
|
||||||
let mut rest_run = LineRun::new();
|
let mut rest_run = LineRun::new();
|
||||||
|
|
||||||
let usable = self.stack.usable().primary(sys);
|
let usable = self.stack.usable().get(sys.primary.axis());
|
||||||
rest_run.usable = Some(match align.primary {
|
rest_run.usable = Some(match align.primary {
|
||||||
GenAlign::Start => unreachable!("start > x"),
|
GenAlign::Start => unreachable!("start > x"),
|
||||||
GenAlign::Center => usable - 2.0 * self.run.size.width,
|
GenAlign::Center => usable - 2.0 * self.run.size.width,
|
||||||
@ -181,7 +181,7 @@ impl LineLayouter {
|
|||||||
/// it will fit into this layouter's underlying stack.
|
/// it will fit into this layouter's underlying stack.
|
||||||
pub fn remaining(&self) -> Vec<LayoutSpace> {
|
pub fn remaining(&self) -> Vec<LayoutSpace> {
|
||||||
let mut spaces = self.stack.remaining();
|
let mut spaces = self.stack.remaining();
|
||||||
*spaces[0].size.secondary_mut(self.ctx.sys) -= self.run.size.height;
|
*spaces[0].size.get_mut(self.ctx.sys.secondary.axis()) -= self.run.size.height;
|
||||||
spaces
|
spaces
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +213,11 @@ impl LineLayouter {
|
|||||||
for (offset, child) in layouts {
|
for (offset, child) in layouts {
|
||||||
let x = match self.ctx.sys.primary.is_positive() {
|
let x = match self.ctx.sys.primary.is_positive() {
|
||||||
true => offset,
|
true => offset,
|
||||||
false => self.run.size.width - offset - child.size.primary(self.ctx.sys),
|
false => {
|
||||||
|
self.run.size.width
|
||||||
|
- offset
|
||||||
|
- child.size.get(self.ctx.sys.primary.axis())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let pos = Point::new(x, 0.0);
|
let pos = Point::new(x, 0.0);
|
||||||
|
@ -11,7 +11,7 @@ pub use primitive::*;
|
|||||||
pub use stack::*;
|
pub use stack::*;
|
||||||
pub use tree::*;
|
pub use tree::*;
|
||||||
|
|
||||||
use crate::geom::{Insets, Point, Rect, RectExt, Sides, Size, SizeExt};
|
use crate::geom::{Insets, Point, Rect, RectExt, Size, SizeExt};
|
||||||
|
|
||||||
use crate::diag::Diag;
|
use crate::diag::Diag;
|
||||||
use crate::eval::{PageState, State, TextState};
|
use crate::eval::{PageState, State, TextState};
|
||||||
|
@ -27,7 +27,7 @@ impl Default for LayoutAlign {
|
|||||||
pub type LayoutExpansion = Spec2<bool>;
|
pub type LayoutExpansion = Spec2<bool>;
|
||||||
|
|
||||||
/// The four directions into which content can be laid out.
|
/// The four directions into which content can be laid out.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum Dir {
|
pub enum Dir {
|
||||||
/// Left to right.
|
/// Left to right.
|
||||||
LTR,
|
LTR,
|
||||||
@ -40,26 +40,6 @@ pub enum Dir {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Dir {
|
impl Dir {
|
||||||
/// The side this direction starts at.
|
|
||||||
pub fn start(self) -> Side {
|
|
||||||
match self {
|
|
||||||
Self::LTR => Side::Left,
|
|
||||||
Self::RTL => Side::Right,
|
|
||||||
Self::TTB => Side::Top,
|
|
||||||
Self::BTT => Side::Bottom,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The side this direction ends at.
|
|
||||||
pub fn end(self) -> Side {
|
|
||||||
match self {
|
|
||||||
Self::LTR => Side::Right,
|
|
||||||
Self::RTL => Side::Left,
|
|
||||||
Self::TTB => Side::Bottom,
|
|
||||||
Self::BTT => Side::Top,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The specific axis this direction belongs to.
|
/// The specific axis this direction belongs to.
|
||||||
pub fn axis(self) -> SpecAxis {
|
pub fn axis(self) -> SpecAxis {
|
||||||
match self {
|
match self {
|
||||||
@ -95,6 +75,18 @@ impl Dir {
|
|||||||
Self::BTT => Self::TTB,
|
Self::BTT => Self::TTB,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The side of this direction the alignment identifies.
|
||||||
|
///
|
||||||
|
/// `Center` alignment is treated the same as `Start` alignment.
|
||||||
|
pub fn side(self, align: GenAlign) -> Side {
|
||||||
|
match if align == GenAlign::End { self.inv() } else { self } {
|
||||||
|
Self::LTR => Side::Left,
|
||||||
|
Self::RTL => Side::Right,
|
||||||
|
Self::TTB => Side::Top,
|
||||||
|
Self::BTT => Side::Bottom,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Dir {
|
impl Display for Dir {
|
||||||
@ -109,7 +101,7 @@ impl Display for Dir {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The two generic layouting axes.
|
/// The two generic layouting axes.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum GenAxis {
|
pub enum GenAxis {
|
||||||
/// The primary layouting direction into which text and lines flow.
|
/// The primary layouting direction into which text and lines flow.
|
||||||
Primary,
|
Primary,
|
||||||
@ -134,7 +126,7 @@ impl Display for GenAxis {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The two specific layouting axes.
|
/// The two specific layouting axes.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum SpecAxis {
|
pub enum SpecAxis {
|
||||||
/// The horizontal layouting axis.
|
/// The horizontal layouting axis.
|
||||||
Horizontal,
|
Horizontal,
|
||||||
@ -162,17 +154,8 @@ impl Display for SpecAxis {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A side of a container.
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub enum Side {
|
|
||||||
Left,
|
|
||||||
Top,
|
|
||||||
Right,
|
|
||||||
Bottom,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Where to align content along an axis in a generic context.
|
/// Where to align content along an axis in a generic context.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum GenAlign {
|
pub enum GenAlign {
|
||||||
Start,
|
Start,
|
||||||
Center,
|
Center,
|
||||||
@ -201,7 +184,7 @@ impl Display for GenAlign {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Where to align content along an axis in a specific context.
|
/// Where to align content along an axis in a specific context.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum SpecAlign {
|
pub enum SpecAlign {
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
@ -256,8 +239,29 @@ impl Display for SpecAlign {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A side of a container.
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub enum Side {
|
||||||
|
Left,
|
||||||
|
Top,
|
||||||
|
Right,
|
||||||
|
Bottom,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Side {
|
||||||
|
/// The opposite side.
|
||||||
|
pub fn inv(self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::Left => Self::Right,
|
||||||
|
Self::Top => Self::Bottom,
|
||||||
|
Self::Right => Self::Left,
|
||||||
|
Self::Bottom => Self::Top,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A generic container with two components for the two generic axes.
|
/// A generic container with two components for the two generic axes.
|
||||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
|
||||||
pub struct Gen2<T> {
|
pub struct Gen2<T> {
|
||||||
/// The primary component.
|
/// The primary component.
|
||||||
pub primary: T,
|
pub primary: T,
|
||||||
@ -279,14 +283,6 @@ impl<T> Gen2<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow the component for the specified generic axis.
|
|
||||||
pub fn get_ref(&mut self, axis: GenAxis) -> &T {
|
|
||||||
match axis {
|
|
||||||
GenAxis::Primary => &mut self.primary,
|
|
||||||
GenAxis::Secondary => &mut self.secondary,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Borrow the component for the specified generic axis mutably.
|
/// Borrow the component for the specified generic axis mutably.
|
||||||
pub fn get_mut(&mut self, axis: GenAxis) -> &mut T {
|
pub fn get_mut(&mut self, axis: GenAxis) -> &mut T {
|
||||||
match axis {
|
match axis {
|
||||||
@ -297,7 +293,7 @@ impl<T> Gen2<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A generic container with two components for the two specific axes.
|
/// A generic container with two components for the two specific axes.
|
||||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
|
||||||
pub struct Spec2<T> {
|
pub struct Spec2<T> {
|
||||||
/// The horizontal component.
|
/// The horizontal component.
|
||||||
pub horizontal: T,
|
pub horizontal: T,
|
||||||
@ -319,14 +315,6 @@ impl<T> Spec2<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow the component for the given specific axis.
|
|
||||||
pub fn get_ref(&mut self, axis: SpecAxis) -> &T {
|
|
||||||
match axis {
|
|
||||||
SpecAxis::Horizontal => &mut self.horizontal,
|
|
||||||
SpecAxis::Vertical => &mut self.vertical,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Borrow the component for the given specific axis mutably.
|
/// Borrow the component for the given specific axis mutably.
|
||||||
pub fn get_mut(&mut self, axis: SpecAxis) -> &mut T {
|
pub fn get_mut(&mut self, axis: SpecAxis) -> &mut T {
|
||||||
match axis {
|
match axis {
|
||||||
@ -335,3 +323,56 @@ impl<T> Spec2<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A generic container with left, top, right and bottom components.
|
||||||
|
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub struct Sides<T> {
|
||||||
|
/// The value for the left side.
|
||||||
|
pub left: T,
|
||||||
|
/// The value for the top side.
|
||||||
|
pub top: T,
|
||||||
|
/// The value for the right side.
|
||||||
|
pub right: T,
|
||||||
|
/// The value for the bottom side.
|
||||||
|
pub bottom: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Sides<T> {
|
||||||
|
/// Create a new box from four sizes.
|
||||||
|
pub fn new(left: T, top: T, right: T, bottom: T) -> Self {
|
||||||
|
Self { left, top, right, bottom }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an instance with all four components set to the same `value`.
|
||||||
|
pub fn uniform(value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Clone,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
left: value.clone(),
|
||||||
|
top: value.clone(),
|
||||||
|
right: value.clone(),
|
||||||
|
bottom: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the component for the given side.
|
||||||
|
pub fn get(self, side: Side) -> T {
|
||||||
|
match side {
|
||||||
|
Side::Left => self.left,
|
||||||
|
Side::Right => self.right,
|
||||||
|
Side::Top => self.top,
|
||||||
|
Side::Bottom => self.bottom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Borrow the component for the given side mutably.
|
||||||
|
pub fn get_mut(&mut self, side: Side) -> &mut T {
|
||||||
|
match side {
|
||||||
|
Side::Left => &mut self.left,
|
||||||
|
Side::Right => &mut self.right,
|
||||||
|
Side::Top => &mut self.top,
|
||||||
|
Side::Bottom => &mut self.bottom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -90,9 +90,10 @@ impl StackLayouter {
|
|||||||
// A hard space is simply an empty box.
|
// A hard space is simply an empty box.
|
||||||
SpacingKind::Hard => {
|
SpacingKind::Hard => {
|
||||||
// Reduce the spacing such that it definitely fits.
|
// Reduce the spacing such that it definitely fits.
|
||||||
spacing = spacing.min(self.space.usable.secondary(self.ctx.sys));
|
let axis = self.ctx.sys.secondary.axis();
|
||||||
let size = Size::new(0.0, spacing);
|
spacing = spacing.min(self.space.usable.get(axis));
|
||||||
|
|
||||||
|
let size = Size::new(0.0, spacing);
|
||||||
self.update_metrics(size);
|
self.update_metrics(size);
|
||||||
self.space.layouts.push((
|
self.space.layouts.push((
|
||||||
self.ctx.sys,
|
self.ctx.sys,
|
||||||
@ -133,29 +134,29 @@ impl StackLayouter {
|
|||||||
|
|
||||||
self.space.size = size.specialized(sys);
|
self.space.size = size.specialized(sys);
|
||||||
self.space.extra = extra.specialized(sys);
|
self.space.extra = extra.specialized(sys);
|
||||||
*self.space.usable.secondary_mut(sys) -= added.height;
|
*self.space.usable.get_mut(sys.secondary.axis()) -= added.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if a space break is necessary.
|
/// Returns true if a space break is necessary.
|
||||||
fn update_rulers(&mut self, align: LayoutAlign) -> bool {
|
fn update_rulers(&mut self, align: LayoutAlign) -> bool {
|
||||||
let allowed = self.is_fitting_alignment(align);
|
let allowed = self.is_fitting_alignment(align);
|
||||||
if allowed {
|
if allowed {
|
||||||
*self.space.rulers.get_mut(self.ctx.sys.secondary, GenAlign::Start) =
|
let side = self.ctx.sys.secondary.side(GenAlign::Start);
|
||||||
align.secondary;
|
*self.space.rulers.get_mut(side) = align.secondary;
|
||||||
}
|
}
|
||||||
allowed
|
allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether a layout with the given alignment can still be layouted into the
|
/// Whether a layout with the given alignment can still be layouted into the
|
||||||
/// active space or a space break is necessary.
|
/// active space or a space break is necessary.
|
||||||
pub(crate) fn is_fitting_alignment(&mut self, align: LayoutAlign) -> bool {
|
pub(crate) fn is_fitting_alignment(&self, align: LayoutAlign) -> bool {
|
||||||
self.is_fitting_axis(self.ctx.sys.primary, align.primary)
|
self.is_fitting_axis(self.ctx.sys.primary, align.primary)
|
||||||
&& self.is_fitting_axis(self.ctx.sys.secondary, align.secondary)
|
&& self.is_fitting_axis(self.ctx.sys.secondary, align.secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_fitting_axis(&mut self, dir: Dir, align: GenAlign) -> bool {
|
fn is_fitting_axis(&self, dir: Dir, align: GenAlign) -> bool {
|
||||||
align >= *self.space.rulers.get_mut(dir, GenAlign::Start)
|
align >= self.space.rulers.get(dir.side(GenAlign::Start))
|
||||||
&& align <= self.space.rulers.get_mut(dir, GenAlign::End).inv()
|
&& align <= self.space.rulers.get(dir.side(GenAlign::End)).inv()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the layouting system.
|
/// Update the layouting system.
|
||||||
@ -284,7 +285,7 @@ impl StackLayouter {
|
|||||||
// the usable space for following layouts at its origin by its
|
// the usable space for following layouts at its origin by its
|
||||||
// extent along the secondary axis.
|
// extent along the secondary axis.
|
||||||
*bound.get_mut(sys.secondary, GenAlign::Start) +=
|
*bound.get_mut(sys.secondary, GenAlign::Start) +=
|
||||||
sys.secondary.factor() * layout.size.secondary(*sys);
|
sys.secondary.factor() * layout.size.get(sys.secondary.axis());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------ //
|
// ------------------------------------------------------------------ //
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use crate::eval::Absolute;
|
use crate::eval::Absolute;
|
||||||
use crate::geom::{Linear, Sides};
|
use crate::geom::Linear;
|
||||||
use crate::paper::{Paper, PaperClass};
|
use crate::paper::{Paper, PaperClass};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! Predefined papers.
|
//! Predefined papers.
|
||||||
|
|
||||||
use crate::geom::{Linear, Sides, Size};
|
use crate::geom::{Linear, Size};
|
||||||
|
use crate::layout::Sides;
|
||||||
use crate::length::Length;
|
use crate::length::Length;
|
||||||
|
|
||||||
/// Specification of a paper.
|
/// Specification of a paper.
|
||||||
|
@ -19,7 +19,7 @@ pub struct Tokens<'s> {
|
|||||||
/// Whether to tokenize in header mode which yields expression, comma and
|
/// Whether to tokenize in header mode which yields expression, comma and
|
||||||
/// similar tokens or in body mode which yields text and star, underscore,
|
/// similar tokens or in body mode which yields text and star, underscore,
|
||||||
/// backtick tokens.
|
/// backtick tokens.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum TokenMode {
|
pub enum TokenMode {
|
||||||
Header,
|
Header,
|
||||||
Body,
|
Body,
|
||||||
|
@ -10,7 +10,7 @@ use unicode_xid::UnicodeXID;
|
|||||||
/// `-` and `_` as starting and continuing characters.
|
/// `-` and `_` as starting and continuing characters.
|
||||||
///
|
///
|
||||||
/// [Unicode Standard]: http://www.unicode.org/reports/tr31/
|
/// [Unicode Standard]: http://www.unicode.org/reports/tr31/
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub struct Ident(pub String);
|
pub struct Ident(pub String);
|
||||||
|
|
||||||
impl Ident {
|
impl Ident {
|
||||||
|
@ -12,7 +12,7 @@ pub use span::*;
|
|||||||
pub use token::*;
|
pub use token::*;
|
||||||
|
|
||||||
/// Decorations for semantic syntax highlighting.
|
/// Decorations for semantic syntax highlighting.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
|
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
|
||||||
pub enum Deco {
|
pub enum Deco {
|
||||||
|
@ -40,7 +40,7 @@ impl<T> Offset for SpanVec<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A value with the span it corresponds to in the source code.
|
/// A value with the span it corresponds to in the source code.
|
||||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
||||||
pub struct Spanned<T> {
|
pub struct Spanned<T> {
|
||||||
/// The spanned value.
|
/// The spanned value.
|
||||||
@ -108,7 +108,7 @@ impl<T: Debug> Debug for Spanned<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Locates a slice of source code.
|
/// Locates a slice of source code.
|
||||||
#[derive(Copy, Clone, Ord, PartialOrd, Hash)]
|
#[derive(Copy, Clone, Ord, PartialOrd)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
/// The inclusive start position.
|
/// The inclusive start position.
|
||||||
@ -209,7 +209,7 @@ impl Debug for Span {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A byte position in source code.
|
/// A byte position in source code.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
||||||
pub struct Pos(pub u32);
|
pub struct Pos(pub u32);
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ impl Debug for Pos {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A one-indexed line-column position in source code.
|
/// A one-indexed line-column position in source code.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
||||||
pub struct Location {
|
pub struct Location {
|
||||||
/// The one-indexed line.
|
/// The one-indexed line.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user