Fix bug in line layouter ✔

This commit is contained in:
Laurenz 2020-10-06 14:44:58 +02:00
parent ef410f6877
commit 985fe28166
4 changed files with 118 additions and 105 deletions

View File

@ -6,18 +6,60 @@ pub use kurbo::*;
use std::fmt::{self, Debug, Formatter};
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].
///
/// [sizes]: ../../kurbo/struct.Size.html
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
/// directions.
///
@ -43,20 +85,6 @@ pub trait SizeExt {
}
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 {
match dirs.main.axis() {
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.
///
/// This represents a function `f(x) = rel * x + abs`.

View File

@ -198,19 +198,17 @@ impl LineLayouter {
pub fn finish_line(&mut self) {
let mut layout = BoxLayout::new(self.run.size.specialized(self.ctx.dirs));
let aligns = self.run.aligns.unwrap_or_default();
let cross = self.ctx.dirs.cross;
let layouts = std::mem::take(&mut self.run.layouts);
for (offset, child) in layouts {
let x = match self.ctx.dirs.cross.is_positive() {
true => offset,
false => {
self.run.size.width
- offset
- child.size.get(self.ctx.dirs.cross.axis())
}
let mut pos = Point::ZERO;
*pos.get_mut(cross.axis()) = if cross.is_positive() {
offset
} else {
self.run.size.width - offset - child.size.get(cross.axis())
};
let pos = Point::new(x, 0.0);
layout.push_layout(pos, child);
}

View File

@ -14,7 +14,7 @@ pub use tree::*;
use crate::diag::Diag;
use crate::eval::{PageState, State, TextState};
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::syntax::{Deco, Spanned, SynTree};
use crate::{Feedback, Pass};

View File

@ -2,6 +2,50 @@
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.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
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.
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
pub struct Gen2<T> {
@ -127,17 +139,19 @@ impl<T> Gen2<T> {
pub fn new(main: T, cross: T) -> Self {
Self { main, cross }
}
}
/// Return the component for the specified generic axis.
pub fn get(self, axis: GenAxis) -> T {
impl<T> Get<GenAxis> for Gen2<T> {
type Component = T;
fn get(self, axis: GenAxis) -> T {
match axis {
GenAxis::Main => self.main,
GenAxis::Cross => self.cross,
}
}
/// Borrow the component for the specified generic axis mutably.
pub fn get_mut(&mut self, axis: GenAxis) -> &mut T {
fn get_mut(&mut self, axis: GenAxis) -> &mut T {
match axis {
GenAxis::Main => &mut self.main,
GenAxis::Cross => &mut self.cross,
@ -170,17 +184,19 @@ impl<T> Spec2<T> {
pub fn new(horizontal: T, vertical: T) -> Self {
Self { horizontal, vertical }
}
}
/// Return the component for the given specific axis.
pub fn get(self, axis: SpecAxis) -> T {
impl<T> Get<SpecAxis> for Spec2<T> {
type Component = T;
fn get(self, axis: SpecAxis) -> T {
match axis {
SpecAxis::Horizontal => self.horizontal,
SpecAxis::Vertical => self.vertical,
}
}
/// Borrow the component for the given specific axis mutably.
pub fn get_mut(&mut self, axis: SpecAxis) -> &mut T {
fn get_mut(&mut self, axis: SpecAxis) -> &mut T {
match axis {
SpecAxis::Horizontal => &mut self.horizontal,
SpecAxis::Vertical => &mut self.vertical,
@ -416,9 +432,12 @@ impl<T> Sides<T> {
bottom: value,
}
}
}
/// Return the component for the given side.
pub fn get(self, side: Side) -> T {
impl<T> Get<Side> for Sides<T> {
type Component = T;
fn get(self, side: Side) -> T {
match side {
Side::Left => self.left,
Side::Top => self.top,
@ -427,8 +446,7 @@ impl<T> Sides<T> {
}
}
/// Borrow the component for the given side mutably.
pub fn get_mut(&mut self, side: Side) -> &mut T {
fn get_mut(&mut self, side: Side) -> &mut T {
match side {
Side::Left => &mut self.left,
Side::Top => &mut self.top,