mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Shorter/clearer field name for geometry types
Size { width, height } => Size { w, h } Spec { horizontal, vertical } => Spec { x, y } Gen { cross, main } => Gen { inline, block }
This commit is contained in:
parent
0dd4ae0a7a
commit
c0377de653
@ -308,7 +308,7 @@ impl Builder {
|
|||||||
|
|
||||||
/// Push an inline node into the active paragraph.
|
/// Push an inline node into the active paragraph.
|
||||||
fn inline(&mut self, node: impl Into<LayoutNode>) {
|
fn inline(&mut self, node: impl Into<LayoutNode>) {
|
||||||
let align = self.state.aligns.cross;
|
let align = self.state.aligns.inline;
|
||||||
self.stack.par.push(ParChild::Any(node.into(), align));
|
self.stack.par.push(ParChild::Any(node.into(), align));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,11 +323,11 @@ impl Builder {
|
|||||||
/// Push spacing into the active paragraph or stack depending on the `axis`.
|
/// Push spacing into the active paragraph or stack depending on the `axis`.
|
||||||
fn spacing(&mut self, axis: GenAxis, amount: Linear) {
|
fn spacing(&mut self, axis: GenAxis, amount: Linear) {
|
||||||
match axis {
|
match axis {
|
||||||
GenAxis::Main => {
|
GenAxis::Block => {
|
||||||
self.stack.finish_par(&self.state);
|
self.stack.finish_par(&self.state);
|
||||||
self.stack.push_hard(StackChild::Spacing(amount));
|
self.stack.push_hard(StackChild::Spacing(amount));
|
||||||
}
|
}
|
||||||
GenAxis::Cross => {
|
GenAxis::Inline => {
|
||||||
self.stack.par.push_hard(ParChild::Spacing(amount));
|
self.stack.par.push_hard(ParChild::Spacing(amount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,7 +351,7 @@ impl Builder {
|
|||||||
fn make_text_node(&self, text: impl Into<EcoString>) -> ParChild {
|
fn make_text_node(&self, text: impl Into<EcoString>) -> ParChild {
|
||||||
ParChild::Text(
|
ParChild::Text(
|
||||||
text.into(),
|
text.into(),
|
||||||
self.state.aligns.cross,
|
self.state.aligns.inline,
|
||||||
Rc::clone(&self.state.font),
|
Rc::clone(&self.state.font),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -441,7 +441,7 @@ impl ParBuilder {
|
|||||||
fn new(state: &State) -> Self {
|
fn new(state: &State) -> Self {
|
||||||
Self {
|
Self {
|
||||||
aligns: state.aligns,
|
aligns: state.aligns,
|
||||||
dir: state.dirs.cross,
|
dir: state.dirs.inline,
|
||||||
line_spacing: state.line_spacing(),
|
line_spacing: state.line_spacing(),
|
||||||
children: vec![],
|
children: vec![],
|
||||||
last: Last::None,
|
last: Last::None,
|
||||||
|
@ -109,16 +109,16 @@ impl Walk for EnumNode {
|
|||||||
fn walk_item(ctx: &mut EvalContext, label: EcoString, body: Template) {
|
fn walk_item(ctx: &mut EvalContext, label: EcoString, body: Template) {
|
||||||
ctx.template += Template::from_block(move |state| {
|
ctx.template += Template::from_block(move |state| {
|
||||||
let label = ParNode {
|
let label = ParNode {
|
||||||
dir: state.dirs.cross,
|
dir: state.dirs.inline,
|
||||||
line_spacing: state.line_spacing(),
|
line_spacing: state.line_spacing(),
|
||||||
children: vec![ParChild::Text(
|
children: vec![ParChild::Text(
|
||||||
label.clone(),
|
label.clone(),
|
||||||
state.aligns.cross,
|
state.aligns.inline,
|
||||||
Rc::clone(&state.font),
|
Rc::clone(&state.font),
|
||||||
)],
|
)],
|
||||||
};
|
};
|
||||||
StackNode {
|
StackNode {
|
||||||
dirs: Gen::new(state.dirs.main, state.dirs.cross),
|
dirs: Gen::new(state.dirs.block, state.dirs.inline),
|
||||||
children: vec![
|
children: vec![
|
||||||
StackChild::Any(label.into(), Gen::default()),
|
StackChild::Any(label.into(), Gen::default()),
|
||||||
StackChild::Spacing((state.font.size / 2.0).into()),
|
StackChild::Spacing((state.font.size / 2.0).into()),
|
||||||
|
@ -122,8 +122,8 @@ impl<'a> PdfExporter<'a> {
|
|||||||
.media_box(Rect::new(
|
.media_box(Rect::new(
|
||||||
0.0,
|
0.0,
|
||||||
0.0,
|
0.0,
|
||||||
page.size.width.to_pt() as f32,
|
page.size.w.to_pt() as f32,
|
||||||
page.size.height.to_pt() as f32,
|
page.size.h.to_pt() as f32,
|
||||||
))
|
))
|
||||||
.contents(content_id);
|
.contents(content_id);
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ impl<'a> PdfExporter<'a> {
|
|||||||
|
|
||||||
for (pos, element) in page.elements() {
|
for (pos, element) in page.elements() {
|
||||||
let x = pos.x.to_pt() as f32;
|
let x = pos.x.to_pt() as f32;
|
||||||
let y = (page.size.height - pos.y).to_pt() as f32;
|
let y = (page.size.h - pos.y).to_pt() as f32;
|
||||||
|
|
||||||
match *element {
|
match *element {
|
||||||
Element::Text(ref shaped) => {
|
Element::Text(ref shaped) => {
|
||||||
@ -176,9 +176,9 @@ impl<'a> PdfExporter<'a> {
|
|||||||
content.save_state();
|
content.save_state();
|
||||||
|
|
||||||
match *geometry {
|
match *geometry {
|
||||||
Geometry::Rect(Size { width, height }) => {
|
Geometry::Rect(Size { w, h }) => {
|
||||||
let w = width.to_pt() as f32;
|
let w = w.to_pt() as f32;
|
||||||
let h = height.to_pt() as f32;
|
let h = h.to_pt() as f32;
|
||||||
if w > 0.0 && h > 0.0 {
|
if w > 0.0 && h > 0.0 {
|
||||||
write_fill(&mut content, paint);
|
write_fill(&mut content, paint);
|
||||||
content.rect(x, y - h, w, h, false, true);
|
content.rect(x, y - h, w, h, false, true);
|
||||||
@ -205,10 +205,10 @@ impl<'a> PdfExporter<'a> {
|
|||||||
content.restore_state();
|
content.restore_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
Element::Image(id, Size { width, height }) => {
|
Element::Image(id, Size { w, h }) => {
|
||||||
let name = format!("Im{}", self.image_map.map(id));
|
let name = format!("Im{}", self.image_map.map(id));
|
||||||
let w = width.to_pt() as f32;
|
let w = w.to_pt() as f32;
|
||||||
let h = height.to_pt() as f32;
|
let h = h.to_pt() as f32;
|
||||||
|
|
||||||
content.save_state();
|
content.save_state();
|
||||||
content.matrix(w, 0.0, 0.0, h, x, y - h);
|
content.matrix(w, 0.0, 0.0, h, x, y - h);
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// A container with a main and cross component.
|
/// A container with an inline and a block component.
|
||||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct Gen<T> {
|
pub struct Gen<T> {
|
||||||
/// The cross component.
|
/// The inline component.
|
||||||
pub cross: T,
|
pub inline: T,
|
||||||
/// The main component.
|
/// The block component.
|
||||||
pub main: T,
|
pub block: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Gen<T> {
|
impl<T> Gen<T> {
|
||||||
/// Create a new instance from the two components.
|
/// Create a new instance from the two components.
|
||||||
pub fn new(cross: T, main: T) -> Self {
|
pub fn new(inline: T, block: T) -> Self {
|
||||||
Self { cross, main }
|
Self { inline, block }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new instance with two equal components.
|
/// Create a new instance with two equal components.
|
||||||
@ -20,7 +20,7 @@ impl<T> Gen<T> {
|
|||||||
where
|
where
|
||||||
T: Clone,
|
T: Clone,
|
||||||
{
|
{
|
||||||
Self { cross: value.clone(), main: value }
|
Self { inline: value.clone(), block: value }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps the individual fields with `f`.
|
/// Maps the individual fields with `f`.
|
||||||
@ -28,14 +28,17 @@ impl<T> Gen<T> {
|
|||||||
where
|
where
|
||||||
F: FnMut(T) -> U,
|
F: FnMut(T) -> U,
|
||||||
{
|
{
|
||||||
Gen { cross: f(self.cross), main: f(self.main) }
|
Gen {
|
||||||
|
inline: f(self.inline),
|
||||||
|
block: f(self.block),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to the specific representation.
|
/// Convert to the specific representation, given the current block axis.
|
||||||
pub fn to_spec(self, main: SpecAxis) -> Spec<T> {
|
pub fn to_spec(self, block: SpecAxis) -> Spec<T> {
|
||||||
match main {
|
match block {
|
||||||
SpecAxis::Horizontal => Spec::new(self.main, self.cross),
|
SpecAxis::Horizontal => Spec::new(self.block, self.inline),
|
||||||
SpecAxis::Vertical => Spec::new(self.cross, self.main),
|
SpecAxis::Vertical => Spec::new(self.inline, self.block),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,19 +47,19 @@ impl Gen<Length> {
|
|||||||
/// The zero value.
|
/// The zero value.
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
Self {
|
Self {
|
||||||
main: Length::zero(),
|
inline: Length::zero(),
|
||||||
cross: Length::zero(),
|
block: Length::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to a point.
|
/// Convert to a point.
|
||||||
pub fn to_point(self, main: SpecAxis) -> Point {
|
pub fn to_point(self, block: SpecAxis) -> Point {
|
||||||
self.to_spec(main).to_point()
|
self.to_spec(block).to_point()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to a size.
|
/// Convert to a size.
|
||||||
pub fn to_size(self, main: SpecAxis) -> Size {
|
pub fn to_size(self, block: SpecAxis) -> Size {
|
||||||
self.to_spec(main).to_size()
|
self.to_spec(block).to_size()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,8 +67,8 @@ impl<T> Gen<Option<T>> {
|
|||||||
/// Unwrap the individual fields.
|
/// Unwrap the individual fields.
|
||||||
pub fn unwrap_or(self, other: Gen<T>) -> Gen<T> {
|
pub fn unwrap_or(self, other: Gen<T>) -> Gen<T> {
|
||||||
Gen {
|
Gen {
|
||||||
cross: self.cross.unwrap_or(other.cross),
|
inline: self.inline.unwrap_or(other.inline),
|
||||||
main: self.main.unwrap_or(other.main),
|
block: self.block.unwrap_or(other.block),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,40 +78,40 @@ impl<T> Get<GenAxis> for Gen<T> {
|
|||||||
|
|
||||||
fn get(self, axis: GenAxis) -> T {
|
fn get(self, axis: GenAxis) -> T {
|
||||||
match axis {
|
match axis {
|
||||||
GenAxis::Main => self.main,
|
GenAxis::Inline => self.inline,
|
||||||
GenAxis::Cross => self.cross,
|
GenAxis::Block => self.block,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_mut(&mut self, axis: GenAxis) -> &mut T {
|
fn get_mut(&mut self, axis: GenAxis) -> &mut T {
|
||||||
match axis {
|
match axis {
|
||||||
GenAxis::Main => &mut self.main,
|
GenAxis::Inline => &mut self.inline,
|
||||||
GenAxis::Cross => &mut self.cross,
|
GenAxis::Block => &mut self.block,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Debug> Debug for Gen<T> {
|
impl<T: Debug> Debug for Gen<T> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "Gen({:?}, {:?})", self.main, self.cross)
|
write!(f, "Gen({:?}, {:?})", self.inline, self.block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The two generic layouting axes.
|
/// The two generic layouting axes.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum GenAxis {
|
pub enum GenAxis {
|
||||||
/// The axis pages and paragraphs are set along.
|
|
||||||
Main,
|
|
||||||
/// The axis words and lines are set along.
|
/// The axis words and lines are set along.
|
||||||
Cross,
|
Inline,
|
||||||
|
/// The axis paragraphs and pages are set along.
|
||||||
|
Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenAxis {
|
impl GenAxis {
|
||||||
/// The other axis.
|
/// The other axis.
|
||||||
pub fn other(self) -> Self {
|
pub fn other(self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Main => Self::Cross,
|
Self::Inline => Self::Block,
|
||||||
Self::Cross => Self::Main,
|
Self::Block => Self::Inline,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,8 +119,8 @@ impl GenAxis {
|
|||||||
impl Display for GenAxis {
|
impl Display for GenAxis {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
f.pad(match self {
|
f.pad(match self {
|
||||||
Self::Main => "main",
|
Self::Inline => "inline",
|
||||||
Self::Cross => "cross",
|
Self::Block => "block",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ impl Path {
|
|||||||
/// Create a path that approximates an axis-aligned ellipse.
|
/// Create a path that approximates an axis-aligned ellipse.
|
||||||
pub fn ellipse(size: Size) -> Self {
|
pub fn ellipse(size: Size) -> Self {
|
||||||
// https://stackoverflow.com/a/2007782
|
// https://stackoverflow.com/a/2007782
|
||||||
let rx = size.width / 2.0;
|
let rx = size.w / 2.0;
|
||||||
let ry = size.height / 2.0;
|
let ry = size.h / 2.0;
|
||||||
let m = 0.551784;
|
let m = 0.551784;
|
||||||
let mx = m * rx;
|
let mx = m * rx;
|
||||||
let my = m * ry;
|
let my = m * ry;
|
||||||
|
@ -28,8 +28,8 @@ impl Point {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to the generic representation.
|
/// Convert to the generic representation.
|
||||||
pub fn to_gen(self, main: SpecAxis) -> Gen<Length> {
|
pub fn to_gen(self, block: SpecAxis) -> Gen<Length> {
|
||||||
match main {
|
match block {
|
||||||
SpecAxis::Horizontal => Gen::new(self.y, self.x),
|
SpecAxis::Horizontal => Gen::new(self.y, self.x),
|
||||||
SpecAxis::Vertical => Gen::new(self.x, self.y),
|
SpecAxis::Vertical => Gen::new(self.x, self.y),
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,10 @@ impl Sides<Linear> {
|
|||||||
/// Resolve the linear sides relative to the given `size`.
|
/// Resolve the linear sides relative to the given `size`.
|
||||||
pub fn resolve(self, size: Size) -> Sides<Length> {
|
pub fn resolve(self, size: Size) -> Sides<Length> {
|
||||||
Sides {
|
Sides {
|
||||||
left: self.left.resolve(size.width),
|
left: self.left.resolve(size.w),
|
||||||
top: self.top.resolve(size.height),
|
top: self.top.resolve(size.h),
|
||||||
right: self.right.resolve(size.width),
|
right: self.right.resolve(size.w),
|
||||||
bottom: self.bottom.resolve(size.height),
|
bottom: self.bottom.resolve(size.h),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,68 +6,65 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||||
pub struct Size {
|
pub struct Size {
|
||||||
/// The width.
|
/// The width.
|
||||||
pub width: Length,
|
pub w: Length,
|
||||||
/// The height.
|
/// The height.
|
||||||
pub height: Length,
|
pub h: Length,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Size {
|
impl Size {
|
||||||
/// The zero size.
|
/// The zero size.
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
Self {
|
Self { w: Length::zero(), h: Length::zero() }
|
||||||
width: Length::zero(),
|
|
||||||
height: Length::zero(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new size from width and height.
|
/// Create a new size from width and height.
|
||||||
pub fn new(width: Length, height: Length) -> Self {
|
pub fn new(w: Length, h: Length) -> Self {
|
||||||
Self { width, height }
|
Self { w, h }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an instance with two equal components.
|
/// Create an instance with two equal components.
|
||||||
pub fn splat(value: Length) -> Self {
|
pub fn splat(v: Length) -> Self {
|
||||||
Self { width: value, height: value }
|
Self { w: v, h: v }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Limit width and height at that of another size.
|
/// Limit width and height at that of another size.
|
||||||
pub fn cap(self, limit: Self) -> Self {
|
pub fn cap(self, limit: Self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
width: self.width.min(limit.width),
|
w: self.w.min(limit.w),
|
||||||
height: self.height.min(limit.height),
|
h: self.h.min(limit.h),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the other size fits into this one (smaller width and height).
|
/// Whether the other size fits into this one (smaller width and height).
|
||||||
pub fn fits(self, other: Self) -> bool {
|
pub fn fits(self, other: Self) -> bool {
|
||||||
self.width.fits(other.width) && self.height.fits(other.height)
|
self.w.fits(other.w) && self.h.fits(other.h)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether both components are finite.
|
/// Whether both components are finite.
|
||||||
pub fn is_finite(self) -> bool {
|
pub fn is_finite(self) -> bool {
|
||||||
self.width.is_finite() && self.height.is_finite()
|
self.w.is_finite() && self.h.is_finite()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether any of the two components is infinite.
|
/// Whether any of the two components is infinite.
|
||||||
pub fn is_infinite(self) -> bool {
|
pub fn is_infinite(self) -> bool {
|
||||||
self.width.is_infinite() || self.height.is_infinite()
|
self.w.is_infinite() || self.h.is_infinite()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to a point.
|
/// Convert to a point.
|
||||||
pub fn to_point(self) -> Point {
|
pub fn to_point(self) -> Point {
|
||||||
Point::new(self.width, self.height)
|
Point::new(self.w, self.h)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to a Spec.
|
/// Convert to a Spec.
|
||||||
pub fn to_spec(self) -> Spec<Length> {
|
pub fn to_spec(self) -> Spec<Length> {
|
||||||
Spec::new(self.width, self.height)
|
Spec::new(self.w, self.h)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to the generic representation.
|
/// Convert to the generic representation.
|
||||||
pub fn to_gen(self, main: SpecAxis) -> Gen<Length> {
|
pub fn to_gen(self, block: SpecAxis) -> Gen<Length> {
|
||||||
match main {
|
match block {
|
||||||
SpecAxis::Horizontal => Gen::new(self.height, self.width),
|
SpecAxis::Horizontal => Gen::new(self.h, self.w),
|
||||||
SpecAxis::Vertical => Gen::new(self.width, self.height),
|
SpecAxis::Vertical => Gen::new(self.w, self.h),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,22 +74,22 @@ impl Get<SpecAxis> for Size {
|
|||||||
|
|
||||||
fn get(self, axis: SpecAxis) -> Length {
|
fn get(self, axis: SpecAxis) -> Length {
|
||||||
match axis {
|
match axis {
|
||||||
SpecAxis::Horizontal => self.width,
|
SpecAxis::Horizontal => self.w,
|
||||||
SpecAxis::Vertical => self.height,
|
SpecAxis::Vertical => self.h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_mut(&mut self, axis: SpecAxis) -> &mut Length {
|
fn get_mut(&mut self, axis: SpecAxis) -> &mut Length {
|
||||||
match axis {
|
match axis {
|
||||||
SpecAxis::Horizontal => &mut self.width,
|
SpecAxis::Horizontal => &mut self.w,
|
||||||
SpecAxis::Vertical => &mut self.height,
|
SpecAxis::Vertical => &mut self.h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Size {
|
impl Debug for Size {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "Size({:?}, {:?})", self.width, self.height)
|
write!(f, "Size({:?}, {:?})", self.w, self.h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +97,7 @@ impl Neg for Size {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn neg(self) -> Self {
|
fn neg(self) -> Self {
|
||||||
Self { width: -self.width, height: -self.height }
|
Self { w: -self.w, h: -self.h }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,10 +105,7 @@ impl Add for Size {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn add(self, other: Self) -> Self {
|
fn add(self, other: Self) -> Self {
|
||||||
Self {
|
Self { w: self.w + other.w, h: self.h + other.h }
|
||||||
width: self.width + other.width,
|
|
||||||
height: self.height + other.height,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,10 +115,7 @@ impl Mul<f64> for Size {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn mul(self, other: f64) -> Self {
|
fn mul(self, other: f64) -> Self {
|
||||||
Self {
|
Self { w: self.w * other, h: self.h * other }
|
||||||
width: self.width * other,
|
|
||||||
height: self.height * other,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,10 +131,7 @@ impl Div<f64> for Size {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn div(self, other: f64) -> Self {
|
fn div(self, other: f64) -> Self {
|
||||||
Self {
|
Self { w: self.w / other, h: self.h / other }
|
||||||
width: self.width / other,
|
|
||||||
height: self.height / other,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,26 +4,23 @@ use super::*;
|
|||||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct Spec<T> {
|
pub struct Spec<T> {
|
||||||
/// The horizontal component.
|
/// The horizontal component.
|
||||||
pub horizontal: T,
|
pub x: T,
|
||||||
/// The vertical component.
|
/// The vertical component.
|
||||||
pub vertical: T,
|
pub y: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Spec<T> {
|
impl<T> Spec<T> {
|
||||||
/// Create a new instance from the two components.
|
/// Create a new instance from the two components.
|
||||||
pub fn new(horizontal: T, vertical: T) -> Self {
|
pub fn new(x: T, y: T) -> Self {
|
||||||
Self { horizontal, vertical }
|
Self { x, y }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new instance with two equal components.
|
/// Create a new instance with two equal components.
|
||||||
pub fn splat(value: T) -> Self
|
pub fn splat(v: T) -> Self
|
||||||
where
|
where
|
||||||
T: Clone,
|
T: Clone,
|
||||||
{
|
{
|
||||||
Self {
|
Self { x: v.clone(), y: v }
|
||||||
horizontal: value.clone(),
|
|
||||||
vertical: value,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps the individual fields with `f`.
|
/// Maps the individual fields with `f`.
|
||||||
@ -31,17 +28,14 @@ impl<T> Spec<T> {
|
|||||||
where
|
where
|
||||||
F: FnMut(T) -> U,
|
F: FnMut(T) -> U,
|
||||||
{
|
{
|
||||||
Spec {
|
Spec { x: f(self.x), y: f(self.y) }
|
||||||
horizontal: f(self.horizontal),
|
|
||||||
vertical: f(self.vertical),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to the generic representation.
|
/// Convert to the generic representation.
|
||||||
pub fn to_gen(self, main: SpecAxis) -> Gen<T> {
|
pub fn to_gen(self, block: SpecAxis) -> Gen<T> {
|
||||||
match main {
|
match block {
|
||||||
SpecAxis::Horizontal => Gen::new(self.vertical, self.horizontal),
|
SpecAxis::Horizontal => Gen::new(self.y, self.x),
|
||||||
SpecAxis::Vertical => Gen::new(self.horizontal, self.vertical),
|
SpecAxis::Vertical => Gen::new(self.x, self.y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,27 +45,24 @@ impl<T> Spec<T> {
|
|||||||
where
|
where
|
||||||
F: Fn(&T, &U) -> bool,
|
F: Fn(&T, &U) -> bool,
|
||||||
{
|
{
|
||||||
eq(&self.vertical, &other.vertical) && eq(&self.horizontal, &other.horizontal)
|
eq(&self.x, &other.x) && eq(&self.y, &other.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spec<Length> {
|
impl Spec<Length> {
|
||||||
/// The zero value.
|
/// The zero value.
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
Self {
|
Self { x: Length::zero(), y: Length::zero() }
|
||||||
horizontal: Length::zero(),
|
|
||||||
vertical: Length::zero(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to a point.
|
/// Convert to a point.
|
||||||
pub fn to_point(self) -> Point {
|
pub fn to_point(self) -> Point {
|
||||||
Point::new(self.horizontal, self.vertical)
|
Point::new(self.x, self.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to a size.
|
/// Convert to a size.
|
||||||
pub fn to_size(self) -> Size {
|
pub fn to_size(self) -> Size {
|
||||||
Size::new(self.horizontal, self.vertical)
|
Size::new(self.x, self.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +70,8 @@ impl<T> Spec<Option<T>> {
|
|||||||
/// Unwrap the individual fields.
|
/// Unwrap the individual fields.
|
||||||
pub fn unwrap_or(self, other: Spec<T>) -> Spec<T> {
|
pub fn unwrap_or(self, other: Spec<T>) -> Spec<T> {
|
||||||
Spec {
|
Spec {
|
||||||
horizontal: self.horizontal.unwrap_or(other.horizontal),
|
x: self.x.unwrap_or(other.x),
|
||||||
vertical: self.vertical.unwrap_or(other.vertical),
|
y: self.y.unwrap_or(other.y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,42 +81,42 @@ impl<T> Get<SpecAxis> for Spec<T> {
|
|||||||
|
|
||||||
fn get(self, axis: SpecAxis) -> T {
|
fn get(self, axis: SpecAxis) -> T {
|
||||||
match axis {
|
match axis {
|
||||||
SpecAxis::Horizontal => self.horizontal,
|
SpecAxis::Horizontal => self.x,
|
||||||
SpecAxis::Vertical => self.vertical,
|
SpecAxis::Vertical => self.y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_mut(&mut self, axis: SpecAxis) -> &mut T {
|
fn get_mut(&mut self, axis: SpecAxis) -> &mut T {
|
||||||
match axis {
|
match axis {
|
||||||
SpecAxis::Horizontal => &mut self.horizontal,
|
SpecAxis::Horizontal => &mut self.x,
|
||||||
SpecAxis::Vertical => &mut self.vertical,
|
SpecAxis::Vertical => &mut self.y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Debug> Debug for Spec<T> {
|
impl<T: Debug> Debug for Spec<T> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "Spec({:?}, {:?})", self.horizontal, self.vertical)
|
write!(f, "Spec({:?}, {:?})", self.x, self.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The two specific layouting axes.
|
/// The two specific layouting axes.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum SpecAxis {
|
pub enum SpecAxis {
|
||||||
/// The vertical layouting axis.
|
|
||||||
Vertical,
|
|
||||||
/// The horizontal layouting axis.
|
/// The horizontal layouting axis.
|
||||||
Horizontal,
|
Horizontal,
|
||||||
|
/// The vertical layouting axis.
|
||||||
|
Vertical,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecAxis {
|
impl SpecAxis {
|
||||||
/// The direction with the given positivity for this axis.
|
/// The direction with the given positivity for this axis.
|
||||||
pub fn dir(self, positive: bool) -> Dir {
|
pub fn dir(self, positive: bool) -> Dir {
|
||||||
match (self, positive) {
|
match (self, positive) {
|
||||||
(Self::Vertical, true) => Dir::TTB,
|
|
||||||
(Self::Vertical, false) => Dir::BTT,
|
|
||||||
(Self::Horizontal, true) => Dir::LTR,
|
(Self::Horizontal, true) => Dir::LTR,
|
||||||
(Self::Horizontal, false) => Dir::RTL,
|
(Self::Horizontal, false) => Dir::RTL,
|
||||||
|
(Self::Vertical, true) => Dir::TTB,
|
||||||
|
(Self::Vertical, false) => Dir::BTT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,8 +132,8 @@ impl SpecAxis {
|
|||||||
impl Display for SpecAxis {
|
impl Display for SpecAxis {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
f.pad(match self {
|
f.pad(match self {
|
||||||
Self::Vertical => "vertical",
|
|
||||||
Self::Horizontal => "horizontal",
|
Self::Horizontal => "horizontal",
|
||||||
|
Self::Vertical => "vertical",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,11 +52,11 @@ impl Constraints {
|
|||||||
/// Set the appropriate base constraints for linear width and height sizing.
|
/// Set the appropriate base constraints for linear width and height sizing.
|
||||||
pub fn set_base_if_linear(&mut self, base: Size, sizing: Spec<Option<Linear>>) {
|
pub fn set_base_if_linear(&mut self, base: Size, sizing: Spec<Option<Linear>>) {
|
||||||
// The full sizes need to be equal if there is a relative component in the sizes.
|
// The full sizes need to be equal if there is a relative component in the sizes.
|
||||||
if sizing.horizontal.map_or(false, |l| l.is_relative()) {
|
if sizing.x.map_or(false, |l| l.is_relative()) {
|
||||||
self.base.horizontal = Some(base.width);
|
self.base.x = Some(base.w);
|
||||||
}
|
}
|
||||||
if sizing.vertical.map_or(false, |l| l.is_relative()) {
|
if sizing.y.map_or(false, |l| l.is_relative()) {
|
||||||
self.base.vertical = Some(base.height);
|
self.base.y = Some(base.h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,24 +35,24 @@ impl Layout for FixedNode {
|
|||||||
// If the size for one axis isn't specified, the `current` size along
|
// If the size for one axis isn't specified, the `current` size along
|
||||||
// that axis needs to remain the same for the result to be reusable.
|
// that axis needs to remain the same for the result to be reusable.
|
||||||
if width.is_none() {
|
if width.is_none() {
|
||||||
constraints.exact.horizontal = Some(current.width);
|
constraints.exact.x = Some(current.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
if height.is_none() {
|
if height.is_none() {
|
||||||
constraints.exact.vertical = Some(current.height);
|
constraints.exact.y = Some(current.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the linears based on the current width and height.
|
// Resolve the linears based on the current width and height.
|
||||||
let mut size = Size::new(
|
let mut size = Size::new(
|
||||||
width.map_or(current.width, |w| w.resolve(base.width)),
|
width.map_or(current.w, |w| w.resolve(base.w)),
|
||||||
height.map_or(current.height, |h| h.resolve(base.height)),
|
height.map_or(current.h, |h| h.resolve(base.h)),
|
||||||
);
|
);
|
||||||
|
|
||||||
// If width or height aren't set for an axis, the base should be
|
// If width or height aren't set for an axis, the base should be
|
||||||
// inherited from the parent for that axis.
|
// inherited from the parent for that axis.
|
||||||
let base = Size::new(
|
let base = Size::new(
|
||||||
width.map_or(base.width, |_| size.width),
|
width.map_or(base.w, |_| size.w),
|
||||||
height.map_or(base.height, |_| size.height),
|
height.map_or(base.h, |_| size.h),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle the aspect ratio.
|
// Handle the aspect ratio.
|
||||||
@ -61,7 +61,7 @@ impl Layout for FixedNode {
|
|||||||
constraints.min = Spec::splat(None);
|
constraints.min = Spec::splat(None);
|
||||||
constraints.max = Spec::splat(None);
|
constraints.max = Spec::splat(None);
|
||||||
|
|
||||||
let width = size.width.min(aspect * size.height);
|
let width = size.w.min(aspect * size.h);
|
||||||
size = Size::new(width, width / aspect);
|
size = Size::new(width, width / aspect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ impl Layout for FixedNode {
|
|||||||
if let Some(aspect) = aspect {
|
if let Some(aspect) = aspect {
|
||||||
if width.is_none() && height.is_none() {
|
if width.is_none() && height.is_none() {
|
||||||
let needed = frames[0].item.size.cap(size);
|
let needed = frames[0].item.size.cap(size);
|
||||||
let width = needed.width.max(aspect * needed.height);
|
let width = needed.w.max(aspect * needed.h);
|
||||||
regions.current = Size::new(width, width / aspect);
|
regions.current = Size::new(width, width / aspect);
|
||||||
regions.expand = Spec::splat(true);
|
regions.expand = Spec::splat(true);
|
||||||
frames = self.child.layout(ctx, ®ions);
|
frames = self.child.layout(ctx, ®ions);
|
||||||
|
@ -3,10 +3,7 @@ use super::*;
|
|||||||
/// A node that arranges its children in a grid.
|
/// A node that arranges its children in a grid.
|
||||||
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub struct GridNode {
|
pub struct GridNode {
|
||||||
/// The `main` and `cross` directions of this grid.
|
/// The inline (columns) and block (rows) directions of this grid.
|
||||||
///
|
|
||||||
/// The rows go along the `main` direction and the columns along the `cross`
|
|
||||||
/// direction.
|
|
||||||
pub dirs: Gen<Dir>,
|
pub dirs: Gen<Dir>,
|
||||||
/// Defines sizing for content rows and columns.
|
/// Defines sizing for content rows and columns.
|
||||||
pub tracks: Gen<Vec<TrackSizing>>,
|
pub tracks: Gen<Vec<TrackSizing>>,
|
||||||
@ -52,10 +49,10 @@ impl From<GridNode> for LayoutNode {
|
|||||||
|
|
||||||
/// Performs grid layout.
|
/// Performs grid layout.
|
||||||
struct GridLayouter<'a> {
|
struct GridLayouter<'a> {
|
||||||
/// The axis of the cross direction.
|
/// The axis of the inline direction.
|
||||||
cross: SpecAxis,
|
inline: SpecAxis,
|
||||||
/// The axis of the main direction.
|
/// The axis of the block direction.
|
||||||
main: SpecAxis,
|
block: SpecAxis,
|
||||||
/// The original expand state of the target region.
|
/// The original expand state of the target region.
|
||||||
expand: Spec<bool>,
|
expand: Spec<bool>,
|
||||||
/// The column tracks including gutter tracks.
|
/// The column tracks including gutter tracks.
|
||||||
@ -68,9 +65,9 @@ struct GridLayouter<'a> {
|
|||||||
regions: Regions,
|
regions: Regions,
|
||||||
/// Resolved column sizes.
|
/// Resolved column sizes.
|
||||||
rcols: Vec<Length>,
|
rcols: Vec<Length>,
|
||||||
/// The full main size of the current region.
|
/// The full block size of the current region.
|
||||||
full: Length,
|
full: Length,
|
||||||
/// The used-up size of the current region. The cross size is determined
|
/// The used-up size of the current region. The inline size is determined
|
||||||
/// once after columns are resolved and not touched again.
|
/// once after columns are resolved and not touched again.
|
||||||
used: Gen<Length>,
|
used: Gen<Length>,
|
||||||
/// The sum of fractional ratios in the current region.
|
/// The sum of fractional ratios in the current region.
|
||||||
@ -99,13 +96,13 @@ impl<'a> GridLayouter<'a> {
|
|||||||
let mut rows = vec![];
|
let mut rows = vec![];
|
||||||
|
|
||||||
// Number of content columns: Always at least one.
|
// Number of content columns: Always at least one.
|
||||||
let c = grid.tracks.cross.len().max(1);
|
let c = grid.tracks.inline.len().max(1);
|
||||||
|
|
||||||
// Number of content rows: At least as many as given, but also at least
|
// Number of content rows: At least as many as given, but also at least
|
||||||
// as many as needed to place each item.
|
// as many as needed to place each item.
|
||||||
let r = {
|
let r = {
|
||||||
let len = grid.children.len();
|
let len = grid.children.len();
|
||||||
let given = grid.tracks.main.len();
|
let given = grid.tracks.block.len();
|
||||||
let needed = len / c + (len % c).clamp(0, 1);
|
let needed = len / c + (len % c).clamp(0, 1);
|
||||||
given.max(needed)
|
given.max(needed)
|
||||||
};
|
};
|
||||||
@ -118,32 +115,32 @@ impl<'a> GridLayouter<'a> {
|
|||||||
|
|
||||||
// Collect content and gutter columns.
|
// Collect content and gutter columns.
|
||||||
for x in 0 .. c {
|
for x in 0 .. c {
|
||||||
cols.push(get_or(&grid.tracks.cross, x, auto));
|
cols.push(get_or(&grid.tracks.inline, x, auto));
|
||||||
cols.push(get_or(&grid.gutter.cross, x, zero));
|
cols.push(get_or(&grid.gutter.inline, x, zero));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect content and gutter rows.
|
// Collect content and gutter rows.
|
||||||
for y in 0 .. r {
|
for y in 0 .. r {
|
||||||
rows.push(get_or(&grid.tracks.main, y, auto));
|
rows.push(get_or(&grid.tracks.block, y, auto));
|
||||||
rows.push(get_or(&grid.gutter.main, y, zero));
|
rows.push(get_or(&grid.gutter.block, y, zero));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove superfluous gutter tracks.
|
// Remove superfluous gutter tracks.
|
||||||
cols.pop();
|
cols.pop();
|
||||||
rows.pop();
|
rows.pop();
|
||||||
|
|
||||||
let cross = grid.dirs.cross.axis();
|
let inline = grid.dirs.inline.axis();
|
||||||
let main = grid.dirs.main.axis();
|
let block = grid.dirs.block.axis();
|
||||||
let full = regions.current.get(main);
|
let full = regions.current.get(block);
|
||||||
let rcols = vec![Length::zero(); cols.len()];
|
let rcols = vec![Length::zero(); cols.len()];
|
||||||
|
|
||||||
// We use the regions only for auto row measurement and constraints.
|
// We use the regions only for auto row measurement and constraints.
|
||||||
let expand = regions.expand;
|
let expand = regions.expand;
|
||||||
regions.expand = Gen::new(true, false).to_spec(main);
|
regions.expand = Gen::new(true, false).to_spec(block);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
cross,
|
inline,
|
||||||
main,
|
block,
|
||||||
cols,
|
cols,
|
||||||
rows,
|
rows,
|
||||||
children: &grid.children,
|
children: &grid.children,
|
||||||
@ -169,8 +166,8 @@ impl<'a> GridLayouter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generic version of current and base size.
|
// Generic version of current and base size.
|
||||||
let current = self.regions.current.to_gen(self.main);
|
let current = self.regions.current.to_gen(self.block);
|
||||||
let base = self.regions.base.to_gen(self.main);
|
let base = self.regions.base.to_gen(self.block);
|
||||||
|
|
||||||
// The different cases affecting constraints.
|
// The different cases affecting constraints.
|
||||||
let mut case = Case::PurelyLinear;
|
let mut case = Case::PurelyLinear;
|
||||||
@ -189,8 +186,8 @@ impl<'a> GridLayouter<'a> {
|
|||||||
case = Case::Fitting;
|
case = Case::Fitting;
|
||||||
}
|
}
|
||||||
TrackSizing::Linear(v) => {
|
TrackSizing::Linear(v) => {
|
||||||
self.constraints.base.set(self.cross, Some(base.cross));
|
self.constraints.base.set(self.inline, Some(base.inline));
|
||||||
let resolved = v.resolve(base.cross);
|
let resolved = v.resolve(base.inline);
|
||||||
*rcol = resolved;
|
*rcol = resolved;
|
||||||
linear += resolved;
|
linear += resolved;
|
||||||
}
|
}
|
||||||
@ -202,7 +199,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Size that is not used by fixed-size columns.
|
// Size that is not used by fixed-size columns.
|
||||||
let available = current.cross - linear;
|
let available = current.inline - linear;
|
||||||
if available >= Length::zero() {
|
if available >= Length::zero() {
|
||||||
// Determine size of auto columns.
|
// Determine size of auto columns.
|
||||||
let (auto, count) = self.measure_auto_columns(ctx, available);
|
let (auto, count) = self.measure_auto_columns(ctx, available);
|
||||||
@ -226,13 +223,19 @@ impl<'a> GridLayouter<'a> {
|
|||||||
// Set constraints depending on the case we hit.
|
// Set constraints depending on the case we hit.
|
||||||
match case {
|
match case {
|
||||||
Case::PurelyLinear => {}
|
Case::PurelyLinear => {}
|
||||||
Case::Fitting => self.constraints.min.set(self.cross, Some(self.used.cross)),
|
Case::Fitting => {
|
||||||
Case::Exact => self.constraints.exact.set(self.cross, Some(current.cross)),
|
self.constraints.min.set(self.inline, Some(self.used.inline));
|
||||||
Case::Overflowing => self.constraints.max.set(self.cross, Some(linear)),
|
}
|
||||||
|
Case::Exact => {
|
||||||
|
self.constraints.exact.set(self.inline, Some(current.inline));
|
||||||
|
}
|
||||||
|
Case::Overflowing => {
|
||||||
|
self.constraints.max.set(self.inline, Some(linear));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sum up the resolved column sizes once here.
|
// Sum up the resolved column sizes once here.
|
||||||
self.used.cross = self.rcols.iter().sum();
|
self.used.inline = self.rcols.iter().sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Measure the size that is available to auto columns.
|
/// Measure the size that is available to auto columns.
|
||||||
@ -253,10 +256,10 @@ impl<'a> GridLayouter<'a> {
|
|||||||
|
|
||||||
let mut resolved = Length::zero();
|
let mut resolved = Length::zero();
|
||||||
for node in (0 .. self.rows.len()).filter_map(|y| self.cell(x, y)) {
|
for node in (0 .. self.rows.len()).filter_map(|y| self.cell(x, y)) {
|
||||||
let size = Gen::new(available, Length::inf()).to_size(self.main);
|
let size = Gen::new(available, Length::inf()).to_size(self.block);
|
||||||
let regions = Regions::one(size, size, Spec::splat(false));
|
let regions = Regions::one(size, size, Spec::splat(false));
|
||||||
let frame = node.layout(ctx, ®ions).remove(0).item;
|
let frame = node.layout(ctx, ®ions).remove(0).item;
|
||||||
resolved.set_max(frame.size.get(self.cross));
|
resolved.set_max(frame.size.get(self.inline));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.rcols[x] = resolved;
|
self.rcols[x] = resolved;
|
||||||
@ -317,9 +320,9 @@ impl<'a> GridLayouter<'a> {
|
|||||||
self.layout_auto_row(ctx, y);
|
self.layout_auto_row(ctx, y);
|
||||||
}
|
}
|
||||||
TrackSizing::Linear(v) => {
|
TrackSizing::Linear(v) => {
|
||||||
let base = self.regions.base.get(self.main);
|
let base = self.regions.base.get(self.block);
|
||||||
if v.is_relative() {
|
if v.is_relative() {
|
||||||
self.constraints.base.set(self.main, Some(base));
|
self.constraints.base.set(self.block, Some(base));
|
||||||
}
|
}
|
||||||
let resolved = v.resolve(base);
|
let resolved = v.resolve(base);
|
||||||
let frame = self.layout_single_row(ctx, resolved, y);
|
let frame = self.layout_single_row(ctx, resolved, y);
|
||||||
@ -327,7 +330,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
}
|
}
|
||||||
TrackSizing::Fractional(v) => {
|
TrackSizing::Fractional(v) => {
|
||||||
self.fr += v;
|
self.fr += v;
|
||||||
self.constraints.exact.set(self.main, Some(self.full));
|
self.constraints.exact.set(self.block, Some(self.full));
|
||||||
self.lrows.push(Row::Fr(v, y));
|
self.lrows.push(Row::Fr(v, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -337,7 +340,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
self.finished
|
self.finished
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Layout a row with automatic size along the main axis. Such a row may
|
/// Layout a row with automatic size along the block axis. Such a row may
|
||||||
/// break across multiple regions.
|
/// break across multiple regions.
|
||||||
fn layout_auto_row(&mut self, ctx: &mut LayoutContext, y: usize) {
|
fn layout_auto_row(&mut self, ctx: &mut LayoutContext, y: usize) {
|
||||||
let mut first = Length::zero();
|
let mut first = Length::zero();
|
||||||
@ -346,13 +349,13 @@ impl<'a> GridLayouter<'a> {
|
|||||||
// Determine the size for each region of the row.
|
// Determine the size for each region of the row.
|
||||||
for (x, &rcol) in self.rcols.iter().enumerate() {
|
for (x, &rcol) in self.rcols.iter().enumerate() {
|
||||||
if let Some(node) = self.cell(x, y) {
|
if let Some(node) = self.cell(x, y) {
|
||||||
let cross = self.cross;
|
let inline = self.inline;
|
||||||
self.regions.mutate(|size| size.set(cross, rcol));
|
self.regions.mutate(|size| size.set(inline, rcol));
|
||||||
|
|
||||||
let mut sizes = node
|
let mut sizes = node
|
||||||
.layout(ctx, &self.regions)
|
.layout(ctx, &self.regions)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|frame| frame.item.size.get(self.main));
|
.map(|frame| frame.item.size.get(self.block));
|
||||||
|
|
||||||
if let Some(size) = sizes.next() {
|
if let Some(size) = sizes.next() {
|
||||||
first.set_max(size);
|
first.set_max(size);
|
||||||
@ -375,14 +378,14 @@ impl<'a> GridLayouter<'a> {
|
|||||||
let len = frames.len();
|
let len = frames.len();
|
||||||
for (i, frame) in frames.into_iter().enumerate() {
|
for (i, frame) in frames.into_iter().enumerate() {
|
||||||
if i + 1 < len {
|
if i + 1 < len {
|
||||||
self.constraints.exact.set(self.main, Some(self.full));
|
self.constraints.exact.set(self.block, Some(self.full));
|
||||||
}
|
}
|
||||||
self.push_row(ctx, frame);
|
self.push_row(ctx, frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Layout a row with a fixed size along the main axis.
|
/// Layout a row with a fixed size along the block axis.
|
||||||
fn layout_single_row(
|
fn layout_single_row(
|
||||||
&self,
|
&self,
|
||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
@ -390,18 +393,18 @@ impl<'a> GridLayouter<'a> {
|
|||||||
y: usize,
|
y: usize,
|
||||||
) -> Frame {
|
) -> Frame {
|
||||||
let size = self.to_size(length);
|
let size = self.to_size(length);
|
||||||
let mut output = Frame::new(size, size.height);
|
let mut output = Frame::new(size, size.h);
|
||||||
let mut pos = Gen::zero();
|
let mut pos = Gen::zero();
|
||||||
|
|
||||||
for (x, &rcol) in self.rcols.iter().enumerate() {
|
for (x, &rcol) in self.rcols.iter().enumerate() {
|
||||||
if let Some(node) = self.cell(x, y) {
|
if let Some(node) = self.cell(x, y) {
|
||||||
let size = Gen::new(rcol, length).to_size(self.main);
|
let size = Gen::new(rcol, length).to_size(self.block);
|
||||||
let regions = Regions::one(size, size, Spec::splat(true));
|
let regions = Regions::one(size, size, Spec::splat(true));
|
||||||
let frame = node.layout(ctx, ®ions).remove(0);
|
let frame = node.layout(ctx, ®ions).remove(0);
|
||||||
output.push_frame(pos.to_point(self.main), frame.item);
|
output.push_frame(pos.to_point(self.block), frame.item);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos.cross += rcol;
|
pos.inline += rcol;
|
||||||
}
|
}
|
||||||
|
|
||||||
output
|
output
|
||||||
@ -419,7 +422,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
let mut outputs: Vec<_> = std::iter::once(first)
|
let mut outputs: Vec<_> = std::iter::once(first)
|
||||||
.chain(rest.iter().copied())
|
.chain(rest.iter().copied())
|
||||||
.map(|v| self.to_size(v))
|
.map(|v| self.to_size(v))
|
||||||
.map(|size| Frame::new(size, size.height))
|
.map(|size| Frame::new(size, size.h))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Prepare regions.
|
// Prepare regions.
|
||||||
@ -432,16 +435,16 @@ impl<'a> GridLayouter<'a> {
|
|||||||
let mut pos = Gen::zero();
|
let mut pos = Gen::zero();
|
||||||
for (x, &rcol) in self.rcols.iter().enumerate() {
|
for (x, &rcol) in self.rcols.iter().enumerate() {
|
||||||
if let Some(node) = self.cell(x, y) {
|
if let Some(node) = self.cell(x, y) {
|
||||||
regions.mutate(|size| size.set(self.cross, rcol));
|
regions.mutate(|size| size.set(self.inline, rcol));
|
||||||
|
|
||||||
// Push the layouted frames into the individual output frames.
|
// Push the layouted frames into the individual output frames.
|
||||||
let frames = node.layout(ctx, ®ions);
|
let frames = node.layout(ctx, ®ions);
|
||||||
for (output, frame) in outputs.iter_mut().zip(frames) {
|
for (output, frame) in outputs.iter_mut().zip(frames) {
|
||||||
output.push_frame(pos.to_point(self.main), frame.item);
|
output.push_frame(pos.to_point(self.block), frame.item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos.cross += rcol;
|
pos.inline += rcol;
|
||||||
}
|
}
|
||||||
|
|
||||||
outputs
|
outputs
|
||||||
@ -450,34 +453,34 @@ impl<'a> GridLayouter<'a> {
|
|||||||
/// Push a row frame into the current or next fitting region, finishing
|
/// Push a row frame into the current or next fitting region, finishing
|
||||||
/// regions (including layouting fractional rows) if necessary.
|
/// regions (including layouting fractional rows) if necessary.
|
||||||
fn push_row(&mut self, ctx: &mut LayoutContext, frame: Frame) {
|
fn push_row(&mut self, ctx: &mut LayoutContext, frame: Frame) {
|
||||||
let length = frame.size.get(self.main);
|
let length = frame.size.get(self.block);
|
||||||
|
|
||||||
// Skip to fitting region.
|
// Skip to fitting region.
|
||||||
while !self.regions.current.get(self.main).fits(length)
|
while !self.regions.current.get(self.block).fits(length)
|
||||||
&& !self.regions.in_full_last()
|
&& !self.regions.in_full_last()
|
||||||
{
|
{
|
||||||
self.constraints.max.set(self.main, Some(self.used.main + length));
|
self.constraints.max.set(self.block, Some(self.used.block + length));
|
||||||
self.finish_region(ctx);
|
self.finish_region(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
*self.regions.current.get_mut(self.main) -= length;
|
*self.regions.current.get_mut(self.block) -= length;
|
||||||
self.used.main += length;
|
self.used.block += length;
|
||||||
self.lrows.push(Row::Frame(frame));
|
self.lrows.push(Row::Frame(frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finish rows for one region.
|
/// Finish rows for one region.
|
||||||
fn finish_region(&mut self, ctx: &mut LayoutContext) {
|
fn finish_region(&mut self, ctx: &mut LayoutContext) {
|
||||||
// Determine the size of the region.
|
// Determine the size of the region.
|
||||||
let length = if self.fr.is_zero() { self.used.main } else { self.full };
|
let length = if self.fr.is_zero() { self.used.block } else { self.full };
|
||||||
let size = self.to_size(length);
|
let size = self.to_size(length);
|
||||||
self.constraints.min.set(self.main, Some(length));
|
self.constraints.min.set(self.block, Some(length));
|
||||||
|
|
||||||
// The frame for the region.
|
// The frame for the region.
|
||||||
let mut output = Frame::new(size, size.height);
|
let mut output = Frame::new(size, size.h);
|
||||||
let mut pos = Gen::zero();
|
let mut pos = Gen::zero();
|
||||||
|
|
||||||
// Determine the remaining size for fractional rows.
|
// Determine the remaining size for fractional rows.
|
||||||
let remaining = self.full - self.used.main;
|
let remaining = self.full - self.used.block;
|
||||||
|
|
||||||
// Place finished rows and layout fractional rows.
|
// Place finished rows and layout fractional rows.
|
||||||
for row in std::mem::take(&mut self.lrows) {
|
for row in std::mem::take(&mut self.lrows) {
|
||||||
@ -494,14 +497,14 @@ impl<'a> GridLayouter<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let main = frame.size.get(self.main);
|
let point = pos.to_point(self.block);
|
||||||
output.merge_frame(pos.to_point(self.main), frame);
|
pos.block += frame.size.get(self.block);
|
||||||
pos.main += main;
|
output.merge_frame(point, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.regions.next();
|
self.regions.next();
|
||||||
self.full = self.regions.current.get(self.main);
|
self.full = self.regions.current.get(self.block);
|
||||||
self.used.main = Length::zero();
|
self.used.block = Length::zero();
|
||||||
self.fr = Fractional::zero();
|
self.fr = Fractional::zero();
|
||||||
self.finished.push(output.constrain(self.constraints));
|
self.finished.push(output.constrain(self.constraints));
|
||||||
self.constraints = Constraints::new(self.expand);
|
self.constraints = Constraints::new(self.expand);
|
||||||
@ -523,9 +526,9 @@ impl<'a> GridLayouter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a size where the cross axis spans the whole grid and the main
|
/// Return a size where the inline axis spans the whole grid and the block
|
||||||
/// axis the given length.
|
/// axis the given length.
|
||||||
fn to_size(&self, main_size: Length) -> Size {
|
fn to_size(&self, block: Length) -> Size {
|
||||||
Gen::new(self.used.cross, main_size).to_size(self.main)
|
Gen::new(self.used.inline, block).to_size(self.block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,8 @@ impl Layout for ImageNode {
|
|||||||
let mut constraints = Constraints::new(expand);
|
let mut constraints = Constraints::new(expand);
|
||||||
constraints.set_base_if_linear(base, Spec::new(self.width, self.height));
|
constraints.set_base_if_linear(base, Spec::new(self.width, self.height));
|
||||||
|
|
||||||
let width = self.width.map(|w| w.resolve(base.width));
|
let width = self.width.map(|w| w.resolve(base.w));
|
||||||
let height = self.height.map(|w| w.resolve(base.height));
|
let height = self.height.map(|w| w.resolve(base.h));
|
||||||
|
|
||||||
let dimensions = ctx.images.get(self.id).buf.dimensions();
|
let dimensions = ctx.images.get(self.id).buf.dimensions();
|
||||||
let pixel_width = dimensions.0 as f64;
|
let pixel_width = dimensions.0 as f64;
|
||||||
@ -38,12 +38,12 @@ impl Layout for ImageNode {
|
|||||||
(None, None) => {
|
(None, None) => {
|
||||||
constraints.exact = current.to_spec().map(Some);
|
constraints.exact = current.to_spec().map(Some);
|
||||||
|
|
||||||
let ratio = current.width / current.height;
|
let ratio = current.w / current.h;
|
||||||
if ratio < pixel_ratio && current.width.is_finite() {
|
if ratio < pixel_ratio && current.w.is_finite() {
|
||||||
Size::new(current.width, current.width / pixel_ratio)
|
Size::new(current.w, current.w / pixel_ratio)
|
||||||
} else if current.height.is_finite() {
|
} else if current.h.is_finite() {
|
||||||
// TODO: Fix issue with line spacing.
|
// TODO: Fix issue with line spacing.
|
||||||
Size::new(current.height * pixel_ratio, current.height)
|
Size::new(current.h * pixel_ratio, current.h)
|
||||||
} else {
|
} else {
|
||||||
// Totally unbounded region, we have to make up something.
|
// Totally unbounded region, we have to make up something.
|
||||||
Size::new(Length::pt(pixel_width), Length::pt(pixel_height))
|
Size::new(Length::pt(pixel_width), Length::pt(pixel_height))
|
||||||
@ -51,7 +51,7 @@ impl Layout for ImageNode {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut frame = Frame::new(size, size.height);
|
let mut frame = Frame::new(size, size.h);
|
||||||
frame.push(Point::zero(), Element::Image(self.id, size));
|
frame.push(Point::zero(), Element::Image(self.id, size));
|
||||||
vec![frame.constrain(constraints)]
|
vec![frame.constrain(constraints)]
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ impl Layout for PadNode {
|
|||||||
// Solve for the size `padded` that satisfies (approximately):
|
// Solve for the size `padded` that satisfies (approximately):
|
||||||
// `padded - padding.resolve(padded).size() == size`
|
// `padded - padding.resolve(padded).size() == size`
|
||||||
let padded = Size::new(
|
let padded = Size::new(
|
||||||
solve_axis(frame.size.width, self.padding.left + self.padding.right),
|
solve_axis(frame.size.w, self.padding.left + self.padding.right),
|
||||||
solve_axis(frame.size.height, self.padding.top + self.padding.bottom),
|
solve_axis(frame.size.h, self.padding.top + self.padding.bottom),
|
||||||
);
|
);
|
||||||
|
|
||||||
let padding = self.padding.resolve(padded);
|
let padding = self.padding.resolve(padded);
|
||||||
@ -39,27 +39,27 @@ impl Layout for PadNode {
|
|||||||
|
|
||||||
// Inflate min and max contraints by the padding.
|
// Inflate min and max contraints by the padding.
|
||||||
for spec in [&mut constraints.min, &mut constraints.max] {
|
for spec in [&mut constraints.min, &mut constraints.max] {
|
||||||
if let Some(horizontal) = spec.horizontal.as_mut() {
|
if let Some(x) = spec.x.as_mut() {
|
||||||
*horizontal += padding.size().width;
|
*x += padding.size().w;
|
||||||
}
|
}
|
||||||
if let Some(vertical) = spec.vertical.as_mut() {
|
if let Some(y) = spec.y.as_mut() {
|
||||||
*vertical += padding.size().height;
|
*y += padding.size().h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set exact and base constraints if the child had them.
|
// Set exact and base constraints if the child had them.
|
||||||
constraints.exact.horizontal.and_set(Some(current.width));
|
constraints.exact.x.and_set(Some(current.w));
|
||||||
constraints.exact.vertical.and_set(Some(current.height));
|
constraints.exact.y.and_set(Some(current.h));
|
||||||
constraints.base.horizontal.and_set(Some(base.width));
|
constraints.base.x.and_set(Some(base.w));
|
||||||
constraints.base.vertical.and_set(Some(base.height));
|
constraints.base.y.and_set(Some(base.h));
|
||||||
|
|
||||||
// Also set base constraints if the padding is relative.
|
// Also set base constraints if the padding is relative.
|
||||||
if self.padding.left.is_relative() || self.padding.right.is_relative() {
|
if self.padding.left.is_relative() || self.padding.right.is_relative() {
|
||||||
constraints.base.horizontal = Some(base.width);
|
constraints.base.x = Some(base.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.padding.top.is_relative() || self.padding.bottom.is_relative() {
|
if self.padding.top.is_relative() || self.padding.bottom.is_relative() {
|
||||||
constraints.base.vertical = Some(base.height);
|
constraints.base.y = Some(base.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new larger frame and place the child's frame inside it.
|
// Create a new larger frame and place the child's frame inside it.
|
||||||
|
@ -122,7 +122,7 @@ impl<'a> ParLayouter<'a> {
|
|||||||
for (range, child) in par.ranges().zip(&par.children) {
|
for (range, child) in par.ranges().zip(&par.children) {
|
||||||
match *child {
|
match *child {
|
||||||
ParChild::Spacing(amount) => {
|
ParChild::Spacing(amount) => {
|
||||||
let resolved = amount.resolve(regions.current.width);
|
let resolved = amount.resolve(regions.current.w);
|
||||||
items.push(ParItem::Spacing(resolved));
|
items.push(ParItem::Spacing(resolved));
|
||||||
ranges.push(range);
|
ranges.push(range);
|
||||||
}
|
}
|
||||||
@ -179,81 +179,69 @@ impl<'a> ParLayouter<'a> {
|
|||||||
if !stack.regions.current.fits(line.size) {
|
if !stack.regions.current.fits(line.size) {
|
||||||
if let Some((last_line, last_end)) = last.take() {
|
if let Some((last_line, last_end)) = last.take() {
|
||||||
// The region must not fit this line for the result to be valid.
|
// The region must not fit this line for the result to be valid.
|
||||||
if !stack.regions.current.width.fits(line.size.width) {
|
if !stack.regions.current.w.fits(line.size.w) {
|
||||||
stack.constraints.max.horizontal.set_min(line.size.width);
|
stack.constraints.max.x.set_min(line.size.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !stack.regions.current.height.fits(line.size.height) {
|
if !stack.regions.current.h.fits(line.size.h) {
|
||||||
stack
|
stack.constraints.max.y.set_min(stack.size.h + line.size.h);
|
||||||
.constraints
|
|
||||||
.max
|
|
||||||
.vertical
|
|
||||||
.set_min(stack.size.height + line.size.height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stack.push(last_line);
|
stack.push(last_line);
|
||||||
stack.constraints.min.vertical = Some(stack.size.height);
|
stack.constraints.min.y = Some(stack.size.h);
|
||||||
start = last_end;
|
start = last_end;
|
||||||
line = LineLayout::new(ctx, &self, start .. end);
|
line = LineLayout::new(ctx, &self, start .. end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the line does not fit vertically, we start a new region.
|
// If the line does not fit vertically, we start a new region.
|
||||||
while !stack.regions.current.height.fits(line.size.height)
|
while !stack.regions.current.h.fits(line.size.h)
|
||||||
&& !stack.regions.in_full_last()
|
&& !stack.regions.in_full_last()
|
||||||
{
|
{
|
||||||
// Again, the line must not fit. It would if the space taken up
|
// Again, the line must not fit. It would if the space taken up
|
||||||
// plus the line height would fit, therefore the constraint
|
// plus the line height would fit, therefore the constraint
|
||||||
// below.
|
// below.
|
||||||
stack
|
stack.constraints.max.y.set_min(stack.size.h + line.size.h);
|
||||||
.constraints
|
|
||||||
.max
|
|
||||||
.vertical
|
|
||||||
.set_min(stack.size.height + line.size.height);
|
|
||||||
stack.finish_region(ctx);
|
stack.finish_region(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the line does not fit vertically, we start a new region.
|
// If the line does not fit vertically, we start a new region.
|
||||||
while !stack.regions.current.height.fits(line.size.height) {
|
while !stack.regions.current.h.fits(line.size.h) {
|
||||||
if stack.regions.in_full_last() {
|
if stack.regions.in_full_last() {
|
||||||
stack.overflowing = true;
|
stack.overflowing = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack
|
stack.constraints.max.y.set_min(stack.size.h + line.size.h);
|
||||||
.constraints
|
|
||||||
.max
|
|
||||||
.vertical
|
|
||||||
.set_min(stack.size.height + line.size.height);
|
|
||||||
stack.finish_region(ctx);
|
stack.finish_region(ctx);
|
||||||
}
|
}
|
||||||
// If the line does not fit horizontally or we have a mandatory
|
// If the line does not fit horizontally or we have a mandatory
|
||||||
// line break (i.e. due to "\n"), we push the line into the
|
// line break (i.e. due to "\n"), we push the line into the
|
||||||
// stack.
|
// stack.
|
||||||
if mandatory || !stack.regions.current.width.fits(line.size.width) {
|
if mandatory || !stack.regions.current.w.fits(line.size.w) {
|
||||||
stack.push(line);
|
stack.push(line);
|
||||||
start = end;
|
start = end;
|
||||||
last = None;
|
last = None;
|
||||||
|
|
||||||
stack.constraints.min.vertical = Some(stack.size.height);
|
stack.constraints.min.y = Some(stack.size.h);
|
||||||
|
|
||||||
// If there is a trailing line break at the end of the
|
// If there is a trailing line break at the end of the
|
||||||
// paragraph, we want to force an empty line.
|
// paragraph, we want to force an empty line.
|
||||||
if mandatory && end == self.bidi.text.len() {
|
if mandatory && end == self.bidi.text.len() {
|
||||||
stack.push(LineLayout::new(ctx, &self, end .. end));
|
stack.push(LineLayout::new(ctx, &self, end .. end));
|
||||||
stack.constraints.min.vertical = Some(stack.size.height);
|
stack.constraints.min.y = Some(stack.size.h);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, the line fits both horizontally and vertically
|
// Otherwise, the line fits both horizontally and vertically
|
||||||
// and we remember it.
|
// and we remember it.
|
||||||
stack.constraints.min.horizontal.set_max(line.size.width);
|
stack.constraints.min.x.set_max(line.size.w);
|
||||||
last = Some((line, end));
|
last = Some((line, end));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((line, _)) = last {
|
if let Some((line, _)) = last {
|
||||||
stack.push(line);
|
stack.push(line);
|
||||||
stack.constraints.min.vertical = Some(stack.size.height);
|
stack.constraints.min.y = Some(stack.size.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
stack.finish(ctx)
|
stack.finish(ctx)
|
||||||
@ -339,12 +327,12 @@ impl<'a> LineStack<'a> {
|
|||||||
|
|
||||||
/// Push a new line into the stack.
|
/// Push a new line into the stack.
|
||||||
fn push(&mut self, line: LineLayout<'a>) {
|
fn push(&mut self, line: LineLayout<'a>) {
|
||||||
self.regions.current.height -= line.size.height + self.line_spacing;
|
self.regions.current.h -= line.size.h + self.line_spacing;
|
||||||
|
|
||||||
self.size.width.set_max(line.size.width);
|
self.size.w.set_max(line.size.w);
|
||||||
self.size.height += line.size.height;
|
self.size.h += line.size.h;
|
||||||
if !self.lines.is_empty() {
|
if !self.lines.is_empty() {
|
||||||
self.size.height += self.line_spacing;
|
self.size.h += self.line_spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.lines.push(line);
|
self.lines.push(line);
|
||||||
@ -352,23 +340,23 @@ impl<'a> LineStack<'a> {
|
|||||||
|
|
||||||
/// Finish the frame for one region.
|
/// Finish the frame for one region.
|
||||||
fn finish_region(&mut self, ctx: &LayoutContext) {
|
fn finish_region(&mut self, ctx: &LayoutContext) {
|
||||||
if self.regions.expand.horizontal {
|
if self.regions.expand.x {
|
||||||
self.size.width = self.regions.current.width;
|
self.size.w = self.regions.current.w;
|
||||||
self.constraints.exact.horizontal = Some(self.regions.current.width);
|
self.constraints.exact.x = Some(self.regions.current.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.overflowing {
|
if self.overflowing {
|
||||||
self.constraints.min.vertical = None;
|
self.constraints.min.y = None;
|
||||||
self.constraints.max.vertical = None;
|
self.constraints.max.y = None;
|
||||||
self.constraints.exact = self.full.to_spec().map(Some);
|
self.constraints.exact = self.full.to_spec().map(Some);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut output = Frame::new(self.size, self.size.height);
|
let mut output = Frame::new(self.size, self.size.h);
|
||||||
let mut offset = Length::zero();
|
let mut offset = Length::zero();
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
|
|
||||||
for line in self.lines.drain(..) {
|
for line in self.lines.drain(..) {
|
||||||
let frame = line.build(ctx, self.size.width);
|
let frame = line.build(ctx, self.size.w);
|
||||||
|
|
||||||
let pos = Point::new(Length::zero(), offset);
|
let pos = Point::new(Length::zero(), offset);
|
||||||
if first {
|
if first {
|
||||||
@ -376,7 +364,7 @@ impl<'a> LineStack<'a> {
|
|||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += frame.size.height + self.line_spacing;
|
offset += frame.size.h + self.line_spacing;
|
||||||
output.merge_frame(pos, frame);
|
output.merge_frame(pos, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,9 +478,9 @@ impl<'a> LineLayout<'a> {
|
|||||||
for item in first.iter().chain(items).chain(&last) {
|
for item in first.iter().chain(items).chain(&last) {
|
||||||
let size = item.size();
|
let size = item.size();
|
||||||
let baseline = item.baseline();
|
let baseline = item.baseline();
|
||||||
width += size.width;
|
width += size.w;
|
||||||
top.set_max(baseline);
|
top.set_max(baseline);
|
||||||
bottom.set_max(size.height - baseline);
|
bottom.set_max(size.h - baseline);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -510,8 +498,8 @@ impl<'a> LineLayout<'a> {
|
|||||||
|
|
||||||
/// Build the line's frame.
|
/// Build the line's frame.
|
||||||
fn build(&self, ctx: &LayoutContext, width: Length) -> Frame {
|
fn build(&self, ctx: &LayoutContext, width: Length) -> Frame {
|
||||||
let size = Size::new(self.size.width.max(width), self.size.height);
|
let size = Size::new(self.size.w.max(width), self.size.h);
|
||||||
let free = size.width - self.size.width;
|
let free = size.w - self.size.w;
|
||||||
|
|
||||||
let mut output = Frame::new(size, self.baseline);
|
let mut output = Frame::new(size, self.baseline);
|
||||||
let mut offset = Length::zero();
|
let mut offset = Length::zero();
|
||||||
@ -539,7 +527,7 @@ impl<'a> LineLayout<'a> {
|
|||||||
self.baseline - frame.baseline,
|
self.baseline - frame.baseline,
|
||||||
);
|
);
|
||||||
|
|
||||||
offset += frame.size.width;
|
offset += frame.size.w;
|
||||||
output.push_frame(pos, frame);
|
output.push_frame(pos, frame);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@ use super::*;
|
|||||||
/// A node that stacks its children.
|
/// A node that stacks its children.
|
||||||
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub struct StackNode {
|
pub struct StackNode {
|
||||||
/// The `main` and `cross` directions of this stack.
|
/// The inline and block directions of this stack.
|
||||||
///
|
///
|
||||||
/// The children are stacked along the `main` direction. The `cross`
|
/// The children are stacked along the block direction. The inline direction
|
||||||
/// direction is required for aligning the children.
|
/// is required for aligning the children.
|
||||||
pub dirs: Gen<Dir>,
|
pub dirs: Gen<Dir>,
|
||||||
/// The nodes to be stacked.
|
/// The nodes to be stacked.
|
||||||
pub children: Vec<StackChild>,
|
pub children: Vec<StackChild>,
|
||||||
@ -41,8 +41,8 @@ impl From<StackNode> for LayoutNode {
|
|||||||
struct StackLayouter<'a> {
|
struct StackLayouter<'a> {
|
||||||
/// The stack node to layout.
|
/// The stack node to layout.
|
||||||
stack: &'a StackNode,
|
stack: &'a StackNode,
|
||||||
/// The axis of the main direction.
|
/// The axis of the block direction.
|
||||||
main: SpecAxis,
|
block: SpecAxis,
|
||||||
/// Whether the stack should expand to fill the region.
|
/// Whether the stack should expand to fill the region.
|
||||||
expand: Spec<bool>,
|
expand: Spec<bool>,
|
||||||
/// The region to layout into.
|
/// The region to layout into.
|
||||||
@ -68,16 +68,16 @@ struct StackLayouter<'a> {
|
|||||||
impl<'a> StackLayouter<'a> {
|
impl<'a> StackLayouter<'a> {
|
||||||
/// Create a new stack layouter.
|
/// Create a new stack layouter.
|
||||||
fn new(stack: &'a StackNode, mut regions: Regions) -> Self {
|
fn new(stack: &'a StackNode, mut regions: Regions) -> Self {
|
||||||
let main = stack.dirs.main.axis();
|
let block = stack.dirs.block.axis();
|
||||||
let full = regions.current;
|
let full = regions.current;
|
||||||
let expand = regions.expand;
|
let expand = regions.expand;
|
||||||
|
|
||||||
// Disable expansion on the main axis for children.
|
// Disable expansion along the block axis for children.
|
||||||
regions.expand.set(main, false);
|
regions.expand.set(block, false);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
stack,
|
stack,
|
||||||
main,
|
block,
|
||||||
expand,
|
expand,
|
||||||
regions,
|
regions,
|
||||||
full,
|
full,
|
||||||
@ -112,34 +112,34 @@ impl<'a> StackLayouter<'a> {
|
|||||||
self.finished
|
self.finished
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add main-axis spacing into the current region.
|
/// Add block-axis spacing into the current region.
|
||||||
fn space(&mut self, amount: Linear) {
|
fn space(&mut self, amount: Linear) {
|
||||||
// Resolve the linear.
|
// Resolve the linear.
|
||||||
let full = self.full.get(self.main);
|
let full = self.full.get(self.block);
|
||||||
let resolved = amount.resolve(full);
|
let resolved = amount.resolve(full);
|
||||||
|
|
||||||
// Cap the spacing to the remaining available space. This action does
|
// Cap the spacing to the remaining available space. This action does
|
||||||
// not directly affect the constraints because of the cap.
|
// not directly affect the constraints because of the cap.
|
||||||
let remaining = self.regions.current.get_mut(self.main);
|
let remaining = self.regions.current.get_mut(self.block);
|
||||||
let capped = resolved.min(*remaining);
|
let capped = resolved.min(*remaining);
|
||||||
|
|
||||||
// Grow our size and shrink the available space in the region.
|
// Grow our size and shrink the available space in the region.
|
||||||
self.used.main += capped;
|
self.used.block += capped;
|
||||||
*remaining -= capped;
|
*remaining -= capped;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push a frame into the current or next fitting region, finishing regions
|
/// Push a frame into the current or next fitting region, finishing regions
|
||||||
/// if necessary.
|
/// if necessary.
|
||||||
fn push_frame(&mut self, frame: Rc<Frame>, aligns: Gen<Align>) {
|
fn push_frame(&mut self, frame: Rc<Frame>, aligns: Gen<Align>) {
|
||||||
let size = frame.size.to_gen(self.main);
|
let size = frame.size.to_gen(self.block);
|
||||||
|
|
||||||
// Don't allow `Start` after `End` in the same region.
|
// Don't allow `Start` after `End` in the same region.
|
||||||
if aligns.main < self.ruler {
|
if aligns.block < self.ruler {
|
||||||
self.finish_region();
|
self.finish_region();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find a fitting region.
|
// Find a fitting region.
|
||||||
while !self.regions.current.get(self.main).fits(size.main) {
|
while !self.regions.current.get(self.block).fits(size.block) {
|
||||||
if self.regions.in_full_last() {
|
if self.regions.in_full_last() {
|
||||||
self.overflowing = true;
|
self.overflowing = true;
|
||||||
break;
|
break;
|
||||||
@ -147,20 +147,20 @@ impl<'a> StackLayouter<'a> {
|
|||||||
|
|
||||||
self.constraints
|
self.constraints
|
||||||
.max
|
.max
|
||||||
.get_mut(self.main)
|
.get_mut(self.block)
|
||||||
.set_min(self.used.main + size.main);
|
.set_min(self.used.block + size.block);
|
||||||
|
|
||||||
self.finish_region();
|
self.finish_region();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shrink available space in the region.
|
// Shrink available space in the region.
|
||||||
*self.regions.current.get_mut(self.main) -= size.main;
|
*self.regions.current.get_mut(self.block) -= size.block;
|
||||||
|
|
||||||
// Grow our size.
|
// Grow our size.
|
||||||
let offset = self.used.main;
|
let offset = self.used.block;
|
||||||
self.used.main += size.main;
|
self.used.block += size.block;
|
||||||
self.used.cross.set_max(size.cross);
|
self.used.inline.set_max(size.inline);
|
||||||
self.ruler = aligns.main;
|
self.ruler = aligns.block;
|
||||||
|
|
||||||
// Remember the frame with offset and alignment.
|
// Remember the frame with offset and alignment.
|
||||||
self.frames.push((offset, aligns, frame));
|
self.frames.push((offset, aligns, frame));
|
||||||
@ -169,60 +169,60 @@ impl<'a> StackLayouter<'a> {
|
|||||||
/// Finish the frame for one region.
|
/// Finish the frame for one region.
|
||||||
fn finish_region(&mut self) {
|
fn finish_region(&mut self) {
|
||||||
let expand = self.expand;
|
let expand = self.expand;
|
||||||
let used = self.used.to_size(self.main);
|
let used = self.used.to_size(self.block);
|
||||||
|
|
||||||
// Determine the stack's size dependening on whether the region is
|
// Determine the stack's size dependening on whether the region is
|
||||||
// fixed.
|
// fixed.
|
||||||
let size = Size::new(
|
let size = Size::new(
|
||||||
if expand.horizontal {
|
if expand.x {
|
||||||
self.constraints.exact.horizontal = Some(self.full.width);
|
self.constraints.exact.x = Some(self.full.w);
|
||||||
self.full.width
|
self.full.w
|
||||||
} else {
|
} else {
|
||||||
self.constraints.min.horizontal = Some(used.width);
|
self.constraints.min.x = Some(used.w);
|
||||||
used.width
|
used.w
|
||||||
},
|
},
|
||||||
if expand.vertical {
|
if expand.y {
|
||||||
self.constraints.exact.vertical = Some(self.full.height);
|
self.constraints.exact.y = Some(self.full.h);
|
||||||
self.full.height
|
self.full.h
|
||||||
} else {
|
} else {
|
||||||
self.constraints.min.vertical = Some(used.height);
|
self.constraints.min.y = Some(used.h);
|
||||||
used.height
|
used.h
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.overflowing {
|
if self.overflowing {
|
||||||
self.constraints.min.vertical = None;
|
self.constraints.min.y = None;
|
||||||
self.constraints.max.vertical = None;
|
self.constraints.max.y = None;
|
||||||
self.constraints.exact = self.full.to_spec().map(Some);
|
self.constraints.exact = self.full.to_spec().map(Some);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut output = Frame::new(size, size.height);
|
let mut output = Frame::new(size, size.h);
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
|
|
||||||
// Place all frames.
|
// Place all frames.
|
||||||
for (offset, aligns, frame) in self.frames.drain(..) {
|
for (offset, aligns, frame) in self.frames.drain(..) {
|
||||||
let stack_size = size.to_gen(self.main);
|
let stack_size = size.to_gen(self.block);
|
||||||
let child_size = frame.size.to_gen(self.main);
|
let child_size = frame.size.to_gen(self.block);
|
||||||
|
|
||||||
// Align along the cross axis.
|
// Align along the inline axis.
|
||||||
let cross = aligns.cross.resolve(
|
let inline = aligns.inline.resolve(
|
||||||
self.stack.dirs.cross,
|
self.stack.dirs.inline,
|
||||||
Length::zero() .. stack_size.cross - child_size.cross,
|
Length::zero() .. stack_size.inline - child_size.inline,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Align along the main axis.
|
// Align along the block axis.
|
||||||
let main = aligns.main.resolve(
|
let block = aligns.block.resolve(
|
||||||
self.stack.dirs.main,
|
self.stack.dirs.block,
|
||||||
if self.stack.dirs.main.is_positive() {
|
if self.stack.dirs.block.is_positive() {
|
||||||
offset .. stack_size.main - self.used.main + offset
|
offset .. stack_size.block - self.used.block + offset
|
||||||
} else {
|
} else {
|
||||||
let offset_with_self = offset + child_size.main;
|
let offset_with_self = offset + child_size.block;
|
||||||
self.used.main - offset_with_self
|
self.used.block - offset_with_self
|
||||||
.. stack_size.main - offset_with_self
|
.. stack_size.block - offset_with_self
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let pos = Gen::new(cross, main).to_point(self.main);
|
let pos = Gen::new(inline, block).to_point(self.block);
|
||||||
|
|
||||||
// The baseline of the stack is that of the first frame.
|
// The baseline of the stack is that of the first frame.
|
||||||
if first {
|
if first {
|
||||||
|
@ -35,8 +35,7 @@ impl PageRun {
|
|||||||
pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<Rc<Frame>> {
|
pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<Rc<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 Size { width, height } = self.size;
|
let expand = self.size.to_spec().map(Length::is_finite);
|
||||||
let expand = Spec::new(width.is_finite(), height.is_finite());
|
|
||||||
let regions = Regions::repeat(self.size, self.size, expand);
|
let regions = Regions::repeat(self.size, self.size, expand);
|
||||||
self.child.layout(ctx, ®ions).into_iter().map(|c| c.item).collect()
|
self.child.layout(ctx, ®ions).into_iter().map(|c| c.item).collect()
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,12 @@ pub fn page(ctx: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
|||||||
|
|
||||||
if let Some(width) = width {
|
if let Some(width) = width {
|
||||||
page.class = PaperClass::Custom;
|
page.class = PaperClass::Custom;
|
||||||
page.size.width = width;
|
page.size.w = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(height) = height {
|
if let Some(height) = height {
|
||||||
page.class = PaperClass::Custom;
|
page.class = PaperClass::Custom;
|
||||||
page.size.height = height;
|
page.size.h = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(margins) = margins {
|
if let Some(margins) = margins {
|
||||||
@ -60,7 +60,7 @@ pub fn page(ctx: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if flip.unwrap_or(false) {
|
if flip.unwrap_or(false) {
|
||||||
std::mem::swap(&mut page.size.width, &mut page.size.height);
|
std::mem::swap(&mut page.size.w, &mut page.size.h);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -78,14 +78,14 @@ pub fn pagebreak(ctx: &mut EvalContext, _: &mut Arguments) -> TypResult<Value> {
|
|||||||
/// `h`: Horizontal spacing.
|
/// `h`: Horizontal spacing.
|
||||||
pub fn h(ctx: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
pub fn h(ctx: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
||||||
let spacing = args.expect("spacing")?;
|
let spacing = args.expect("spacing")?;
|
||||||
ctx.template.spacing(GenAxis::Cross, spacing);
|
ctx.template.spacing(GenAxis::Inline, spacing);
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `v`: Vertical spacing.
|
/// `v`: Vertical spacing.
|
||||||
pub fn v(ctx: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
pub fn v(ctx: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
||||||
let spacing = args.expect("spacing")?;
|
let spacing = args.expect("spacing")?;
|
||||||
ctx.template.spacing(GenAxis::Main, spacing);
|
ctx.template.spacing(GenAxis::Block, spacing);
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,11 +113,11 @@ pub fn align(ctx: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
|||||||
let realign = |template: &mut Template| {
|
let realign = |template: &mut Template| {
|
||||||
template.modify(move |state| {
|
template.modify(move |state| {
|
||||||
if let Some(horizontal) = horizontal {
|
if let Some(horizontal) = horizontal {
|
||||||
state.aligns.cross = horizontal;
|
state.aligns.inline = horizontal;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(vertical) = vertical {
|
if let Some(vertical) = vertical {
|
||||||
state.aligns.main = vertical;
|
state.aligns.block = vertical;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -199,10 +199,10 @@ pub fn stack(_: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
|||||||
|
|
||||||
let mut dirs = Gen::new(None, dir).unwrap_or(state.dirs);
|
let mut dirs = Gen::new(None, dir).unwrap_or(state.dirs);
|
||||||
|
|
||||||
// If the directions become aligned, fix up the cross direction since
|
// If the directions become aligned, fix up the inline direction since
|
||||||
// that's the one that is not user-defined.
|
// that's the one that is not user-defined.
|
||||||
if dirs.main.axis() == dirs.cross.axis() {
|
if dirs.block.axis() == dirs.inline.axis() {
|
||||||
dirs.cross = state.dirs.main;
|
dirs.inline = state.dirs.block;
|
||||||
}
|
}
|
||||||
|
|
||||||
StackNode { dirs, children }
|
StackNode { dirs, children }
|
||||||
@ -239,17 +239,17 @@ pub fn grid(_: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
|||||||
// If the directions become aligned, try to fix up the direction which
|
// If the directions become aligned, try to fix up the direction which
|
||||||
// is not user-defined.
|
// is not user-defined.
|
||||||
let mut dirs = Gen::new(column_dir, row_dir).unwrap_or(state.dirs);
|
let mut dirs = Gen::new(column_dir, row_dir).unwrap_or(state.dirs);
|
||||||
if dirs.main.axis() == dirs.cross.axis() {
|
if dirs.block.axis() == dirs.inline.axis() {
|
||||||
let target = if column_dir.is_some() {
|
let target = if column_dir.is_some() {
|
||||||
&mut dirs.main
|
&mut dirs.block
|
||||||
} else {
|
} else {
|
||||||
&mut dirs.cross
|
&mut dirs.inline
|
||||||
};
|
};
|
||||||
|
|
||||||
*target = if target.axis() == state.dirs.cross.axis() {
|
*target = if target.axis() == state.dirs.inline.axis() {
|
||||||
state.dirs.main
|
state.dirs.block
|
||||||
} else {
|
} else {
|
||||||
state.dirs.cross
|
state.dirs.inline
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ pub fn lang(ctx: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(dir) = dir {
|
if let Some(dir) = dir {
|
||||||
ctx.template.modify(move |state| state.dirs.cross = dir);
|
ctx.template.modify(move |state| state.dirs.inline = dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.template.parbreak();
|
ctx.template.parbreak();
|
||||||
|
@ -113,11 +113,11 @@ fn print_diagnostics(
|
|||||||
|
|
||||||
for error in errors {
|
for error in errors {
|
||||||
// The main diagnostic.
|
// The main diagnostic.
|
||||||
let main = Diagnostic::error().with_message(error.message).with_labels(vec![
|
let diag = Diagnostic::error().with_message(error.message).with_labels(vec![
|
||||||
Label::primary(error.span.source, error.span.to_range()),
|
Label::primary(error.span.source, error.span.to_range()),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
term::emit(&mut writer, &config, sources, &main)?;
|
term::emit(&mut writer, &config, sources, &diag)?;
|
||||||
|
|
||||||
// Stacktrace-like helper diagnostics.
|
// Stacktrace-like helper diagnostics.
|
||||||
for point in error.trace {
|
for point in error.trace {
|
||||||
|
@ -380,9 +380,8 @@ fn print_error(source: &SourceFile, line: usize, error: &Error) {
|
|||||||
|
|
||||||
fn draw(ctx: &Context, frames: &[Rc<Frame>], dpi: f32) -> sk::Pixmap {
|
fn draw(ctx: &Context, frames: &[Rc<Frame>], dpi: f32) -> sk::Pixmap {
|
||||||
let pad = Length::pt(5.0);
|
let pad = Length::pt(5.0);
|
||||||
|
let width = 2.0 * pad + frames.iter().map(|l| l.size.w).max().unwrap_or_default();
|
||||||
let height = pad + frames.iter().map(|l| l.size.height + pad).sum::<Length>();
|
let height = pad + frames.iter().map(|l| l.size.h + pad).sum::<Length>();
|
||||||
let width = 2.0 * pad + frames.iter().map(|l| l.size.width).max().unwrap_or_default();
|
|
||||||
|
|
||||||
let pixel_width = (dpi * width.to_pt() as f32) as u32;
|
let pixel_width = (dpi * width.to_pt() as f32) as u32;
|
||||||
let pixel_height = (dpi * height.to_pt() as f32) as u32;
|
let pixel_height = (dpi * height.to_pt() as f32) as u32;
|
||||||
@ -405,8 +404,8 @@ fn draw(ctx: &Context, frames: &[Rc<Frame>], dpi: f32) -> sk::Pixmap {
|
|||||||
sk::Rect::from_xywh(
|
sk::Rect::from_xywh(
|
||||||
origin.x.to_pt() as f32,
|
origin.x.to_pt() as f32,
|
||||||
origin.y.to_pt() as f32,
|
origin.y.to_pt() as f32,
|
||||||
frame.size.width.to_pt() as f32,
|
frame.size.w.to_pt() as f32,
|
||||||
frame.size.height.to_pt() as f32,
|
frame.size.h.to_pt() as f32,
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
&paint,
|
&paint,
|
||||||
@ -432,7 +431,7 @@ fn draw(ctx: &Context, frames: &[Rc<Frame>], dpi: f32) -> sk::Pixmap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
origin.y += frame.size.height + pad;
|
origin.y += frame.size.h + pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas
|
canvas
|
||||||
@ -496,7 +495,7 @@ fn draw_geometry(
|
|||||||
let rule = sk::FillRule::default();
|
let rule = sk::FillRule::default();
|
||||||
|
|
||||||
match *geometry {
|
match *geometry {
|
||||||
Geometry::Rect(Size { width, height }) => {
|
Geometry::Rect(Size { w: width, h: height }) => {
|
||||||
let w = width.to_pt() as f32;
|
let w = width.to_pt() as f32;
|
||||||
let h = height.to_pt() as f32;
|
let h = height.to_pt() as f32;
|
||||||
let rect = sk::Rect::from_xywh(0.0, 0.0, w, h).unwrap();
|
let rect = sk::Rect::from_xywh(0.0, 0.0, w, h).unwrap();
|
||||||
@ -539,8 +538,8 @@ fn draw_image(
|
|||||||
*dest = sk::ColorU8::from_rgba(r, g, b, a).premultiply();
|
*dest = sk::ColorU8::from_rgba(r, g, b, a).premultiply();
|
||||||
}
|
}
|
||||||
|
|
||||||
let view_width = size.width.to_pt() as f32;
|
let view_width = size.w.to_pt() as f32;
|
||||||
let view_height = size.height.to_pt() as f32;
|
let view_height = size.h.to_pt() as f32;
|
||||||
let scale_x = view_width as f32 / pixmap.width() as f32;
|
let scale_x = view_width as f32 / pixmap.width() as f32;
|
||||||
let scale_y = view_height as f32 / pixmap.height() as f32;
|
let scale_y = view_height as f32 / pixmap.height() as f32;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user