mirror of
https://github.com/typst/typst
synced 2025-06-28 16:22:53 +08:00
Fix bug in line layouter ✔
This commit is contained in:
parent
ef410f6877
commit
985fe28166
101
src/geom.rs
101
src/geom.rs
@ -6,18 +6,60 @@ pub use kurbo::*;
|
|||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::ops::*;
|
use std::ops::*;
|
||||||
|
|
||||||
use crate::layout::primitive::{Dir, Gen2, GenAlign, Side, SpecAxis};
|
use crate::layout::primitive::{Dir, Gen2, GenAlign, Get, Side, SpecAxis};
|
||||||
|
|
||||||
|
macro_rules! impl_get_2d {
|
||||||
|
($t:ty, $x:ident, $y:ident) => {
|
||||||
|
impl Get<SpecAxis> for $t {
|
||||||
|
type Component = f64;
|
||||||
|
|
||||||
|
fn get(self, axis: SpecAxis) -> f64 {
|
||||||
|
match axis {
|
||||||
|
SpecAxis::Horizontal => self.$x,
|
||||||
|
SpecAxis::Vertical => self.$y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mut(&mut self, axis: SpecAxis) -> &mut f64 {
|
||||||
|
match axis {
|
||||||
|
SpecAxis::Horizontal => &mut self.$x,
|
||||||
|
SpecAxis::Vertical => &mut self.$y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_get_2d!(Point, x, y);
|
||||||
|
impl_get_2d!(Vec2, x, y);
|
||||||
|
impl_get_2d!(Size, width, height);
|
||||||
|
|
||||||
|
impl Get<Side> for Rect {
|
||||||
|
type Component = f64;
|
||||||
|
|
||||||
|
fn get(self, side: Side) -> f64 {
|
||||||
|
match side {
|
||||||
|
Side::Left => self.x0,
|
||||||
|
Side::Top => self.y0,
|
||||||
|
Side::Right => self.x1,
|
||||||
|
Side::Bottom => self.y1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mut(&mut self, side: Side) -> &mut f64 {
|
||||||
|
match side {
|
||||||
|
Side::Left => &mut self.x0,
|
||||||
|
Side::Top => &mut self.y0,
|
||||||
|
Side::Right => &mut self.x1,
|
||||||
|
Side::Bottom => &mut self.y1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Additional methods for [sizes].
|
/// Additional methods for [sizes].
|
||||||
///
|
///
|
||||||
/// [sizes]: ../../kurbo/struct.Size.html
|
/// [sizes]: ../../kurbo/struct.Size.html
|
||||||
pub trait SizeExt {
|
pub trait SizeExt {
|
||||||
/// Return the component for the specified axis.
|
|
||||||
fn get(self, axis: SpecAxis) -> f64;
|
|
||||||
|
|
||||||
/// Borrow the component for the specified axis mutably.
|
|
||||||
fn get_mut(&mut self, axis: SpecAxis) -> &mut f64;
|
|
||||||
|
|
||||||
/// Returns the generalized version of a `Size` based on the current
|
/// Returns the generalized version of a `Size` based on the current
|
||||||
/// directions.
|
/// directions.
|
||||||
///
|
///
|
||||||
@ -43,20 +85,6 @@ pub trait SizeExt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SizeExt for Size {
|
impl SizeExt for Size {
|
||||||
fn get(self, axis: SpecAxis) -> f64 {
|
|
||||||
match axis {
|
|
||||||
SpecAxis::Horizontal => self.width,
|
|
||||||
SpecAxis::Vertical => self.height,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_mut(&mut self, axis: SpecAxis) -> &mut f64 {
|
|
||||||
match axis {
|
|
||||||
SpecAxis::Horizontal => &mut self.width,
|
|
||||||
SpecAxis::Vertical => &mut self.height,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generalized(self, dirs: Gen2<Dir>) -> Self {
|
fn generalized(self, dirs: Gen2<Dir>) -> Self {
|
||||||
match dirs.main.axis() {
|
match dirs.main.axis() {
|
||||||
SpecAxis::Horizontal => Self::new(self.height, self.width),
|
SpecAxis::Horizontal => Self::new(self.height, self.width),
|
||||||
@ -90,37 +118,6 @@ impl SizeExt for Size {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods for [rectangles].
|
|
||||||
///
|
|
||||||
/// [rectangles]: ../../kurbo/struct.Rect.html
|
|
||||||
pub trait RectExt {
|
|
||||||
/// Return the value for the given side.
|
|
||||||
fn get(self, side: Side) -> f64;
|
|
||||||
|
|
||||||
/// Borrow the value for the given side mutably.
|
|
||||||
fn get_mut(&mut self, side: Side) -> &mut f64;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RectExt for Rect {
|
|
||||||
fn get(self, side: Side) -> f64 {
|
|
||||||
match side {
|
|
||||||
Side::Left => self.x0,
|
|
||||||
Side::Top => self.y0,
|
|
||||||
Side::Right => self.x1,
|
|
||||||
Side::Bottom => self.y1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_mut(&mut self, side: Side) -> &mut f64 {
|
|
||||||
match side {
|
|
||||||
Side::Left => &mut self.x0,
|
|
||||||
Side::Top => &mut self.y0,
|
|
||||||
Side::Right => &mut self.x1,
|
|
||||||
Side::Bottom => &mut self.y1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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`.
|
||||||
|
@ -198,19 +198,17 @@ impl LineLayouter {
|
|||||||
pub fn finish_line(&mut self) {
|
pub fn finish_line(&mut self) {
|
||||||
let mut layout = BoxLayout::new(self.run.size.specialized(self.ctx.dirs));
|
let mut layout = BoxLayout::new(self.run.size.specialized(self.ctx.dirs));
|
||||||
let aligns = self.run.aligns.unwrap_or_default();
|
let aligns = self.run.aligns.unwrap_or_default();
|
||||||
|
let cross = self.ctx.dirs.cross;
|
||||||
|
|
||||||
let layouts = std::mem::take(&mut self.run.layouts);
|
let layouts = std::mem::take(&mut self.run.layouts);
|
||||||
for (offset, child) in layouts {
|
for (offset, child) in layouts {
|
||||||
let x = match self.ctx.dirs.cross.is_positive() {
|
let mut pos = Point::ZERO;
|
||||||
true => offset,
|
*pos.get_mut(cross.axis()) = if cross.is_positive() {
|
||||||
false => {
|
offset
|
||||||
self.run.size.width
|
} else {
|
||||||
- offset
|
self.run.size.width - offset - child.size.get(cross.axis())
|
||||||
- child.size.get(self.ctx.dirs.cross.axis())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let pos = Point::new(x, 0.0);
|
|
||||||
layout.push_layout(pos, child);
|
layout.push_layout(pos, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ pub use tree::*;
|
|||||||
use crate::diag::Diag;
|
use crate::diag::Diag;
|
||||||
use crate::eval::{PageState, State, TextState};
|
use crate::eval::{PageState, State, TextState};
|
||||||
use crate::font::SharedFontLoader;
|
use crate::font::SharedFontLoader;
|
||||||
use crate::geom::{Insets, Point, Rect, RectExt, Size, SizeExt};
|
use crate::geom::{Insets, Point, Rect, Size, SizeExt};
|
||||||
use crate::shaping::Shaped;
|
use crate::shaping::Shaped;
|
||||||
use crate::syntax::{Deco, Spanned, SynTree};
|
use crate::syntax::{Deco, Spanned, SynTree};
|
||||||
use crate::{Feedback, Pass};
|
use crate::{Feedback, Pass};
|
||||||
|
@ -2,6 +2,50 @@
|
|||||||
|
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
/// Generic access to a structure's components.
|
||||||
|
pub trait Get<Index> {
|
||||||
|
/// The structure's component type.
|
||||||
|
type Component;
|
||||||
|
|
||||||
|
/// Return the component for the specified index.
|
||||||
|
fn get(self, index: Index) -> Self::Component;
|
||||||
|
|
||||||
|
/// Borrow the component for the specified index mutably.
|
||||||
|
fn get_mut(&mut self, index: Index) -> &mut Self::Component;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a type into its generic representation.
|
||||||
|
///
|
||||||
|
/// The generic representation deals with main and cross axes while the specific
|
||||||
|
/// representation deals with horizontal and vertical axes.
|
||||||
|
///
|
||||||
|
/// See also [`ToSpec`] for the inverse conversion.
|
||||||
|
///
|
||||||
|
/// [`ToSpec`]: trait.ToSpec.html
|
||||||
|
pub trait ToGen {
|
||||||
|
/// The generic version of this type.
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
/// The generic version of this type based on the current directions.
|
||||||
|
fn to_gen(self, dirs: Gen2<Dir>) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a type into its specific representation.
|
||||||
|
///
|
||||||
|
/// The specific representation deals with horizontal and vertical axes while
|
||||||
|
/// the generic representation deals with main and cross axes.
|
||||||
|
///
|
||||||
|
/// See also [`ToGen`] for the inverse conversion.
|
||||||
|
///
|
||||||
|
/// [`ToGen`]: trait.ToGen.html
|
||||||
|
pub trait ToSpec {
|
||||||
|
/// The specific version of this type.
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
/// The specific version of this type based on the current directions.
|
||||||
|
fn to_spec(self, dirs: Gen2<Dir>) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
/// 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)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum Dir {
|
pub enum Dir {
|
||||||
@ -81,38 +125,6 @@ impl Display for Dir {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a type into its generic representation.
|
|
||||||
///
|
|
||||||
/// The generic representation deals with main and cross axes while the specific
|
|
||||||
/// representation deals with horizontal and vertical axes.
|
|
||||||
///
|
|
||||||
/// See also [`ToSpec`] for the inverse conversion.
|
|
||||||
///
|
|
||||||
/// [`ToSpec`]: trait.ToSpec.html
|
|
||||||
pub trait ToGen {
|
|
||||||
/// The generic version of this type.
|
|
||||||
type Output;
|
|
||||||
|
|
||||||
/// The generic version of this type based on the current directions.
|
|
||||||
fn to_gen(self, dirs: Gen2<Dir>) -> Self::Output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert a type into its specific representation.
|
|
||||||
///
|
|
||||||
/// The specific representation deals with horizontal and vertical axes while
|
|
||||||
/// the generic representation deals with main and cross axes.
|
|
||||||
///
|
|
||||||
/// See also [`ToGen`] for the inverse conversion.
|
|
||||||
///
|
|
||||||
/// [`ToGen`]: trait.ToGen.html
|
|
||||||
pub trait ToSpec {
|
|
||||||
/// The specific version of this type.
|
|
||||||
type Output;
|
|
||||||
|
|
||||||
/// The specific version of this type based on the current directions.
|
|
||||||
fn to_spec(self, dirs: Gen2<Dir>) -> Self::Output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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)]
|
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
|
||||||
pub struct Gen2<T> {
|
pub struct Gen2<T> {
|
||||||
@ -127,17 +139,19 @@ impl<T> Gen2<T> {
|
|||||||
pub fn new(main: T, cross: T) -> Self {
|
pub fn new(main: T, cross: T) -> Self {
|
||||||
Self { main, cross }
|
Self { main, cross }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the component for the specified generic axis.
|
impl<T> Get<GenAxis> for Gen2<T> {
|
||||||
pub fn get(self, axis: GenAxis) -> T {
|
type Component = T;
|
||||||
|
|
||||||
|
fn get(self, axis: GenAxis) -> T {
|
||||||
match axis {
|
match axis {
|
||||||
GenAxis::Main => self.main,
|
GenAxis::Main => self.main,
|
||||||
GenAxis::Cross => self.cross,
|
GenAxis::Cross => self.cross,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow the component for the specified generic axis mutably.
|
fn get_mut(&mut self, axis: GenAxis) -> &mut T {
|
||||||
pub fn get_mut(&mut self, axis: GenAxis) -> &mut T {
|
|
||||||
match axis {
|
match axis {
|
||||||
GenAxis::Main => &mut self.main,
|
GenAxis::Main => &mut self.main,
|
||||||
GenAxis::Cross => &mut self.cross,
|
GenAxis::Cross => &mut self.cross,
|
||||||
@ -170,17 +184,19 @@ impl<T> Spec2<T> {
|
|||||||
pub fn new(horizontal: T, vertical: T) -> Self {
|
pub fn new(horizontal: T, vertical: T) -> Self {
|
||||||
Self { horizontal, vertical }
|
Self { horizontal, vertical }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the component for the given specific axis.
|
impl<T> Get<SpecAxis> for Spec2<T> {
|
||||||
pub fn get(self, axis: SpecAxis) -> T {
|
type Component = T;
|
||||||
|
|
||||||
|
fn get(self, axis: SpecAxis) -> T {
|
||||||
match axis {
|
match axis {
|
||||||
SpecAxis::Horizontal => self.horizontal,
|
SpecAxis::Horizontal => self.horizontal,
|
||||||
SpecAxis::Vertical => self.vertical,
|
SpecAxis::Vertical => self.vertical,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow the component for the given specific axis mutably.
|
fn get_mut(&mut self, axis: SpecAxis) -> &mut T {
|
||||||
pub fn get_mut(&mut self, axis: SpecAxis) -> &mut T {
|
|
||||||
match axis {
|
match axis {
|
||||||
SpecAxis::Horizontal => &mut self.horizontal,
|
SpecAxis::Horizontal => &mut self.horizontal,
|
||||||
SpecAxis::Vertical => &mut self.vertical,
|
SpecAxis::Vertical => &mut self.vertical,
|
||||||
@ -416,9 +432,12 @@ impl<T> Sides<T> {
|
|||||||
bottom: value,
|
bottom: value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the component for the given side.
|
impl<T> Get<Side> for Sides<T> {
|
||||||
pub fn get(self, side: Side) -> T {
|
type Component = T;
|
||||||
|
|
||||||
|
fn get(self, side: Side) -> T {
|
||||||
match side {
|
match side {
|
||||||
Side::Left => self.left,
|
Side::Left => self.left,
|
||||||
Side::Top => self.top,
|
Side::Top => self.top,
|
||||||
@ -427,8 +446,7 @@ impl<T> Sides<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow the component for the given side mutably.
|
fn get_mut(&mut self, side: Side) -> &mut T {
|
||||||
pub fn get_mut(&mut self, side: Side) -> &mut T {
|
|
||||||
match side {
|
match side {
|
||||||
Side::Left => &mut self.left,
|
Side::Left => &mut self.left,
|
||||||
Side::Top => &mut self.top,
|
Side::Top => &mut self.top,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user