mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Remove directions from grid
This commit is contained in:
parent
6690bc2354
commit
c627847cb3
@ -4,12 +4,10 @@ use super::*;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
#[cfg_attr(feature = "layout-cache", derive(Hash))]
|
||||||
pub struct GridNode {
|
pub struct GridNode {
|
||||||
/// The inline (columns) and block (rows) directions of this grid.
|
|
||||||
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: Spec<Vec<TrackSizing>>,
|
||||||
/// Defines sizing of gutter rows and columns between content.
|
/// Defines sizing of gutter rows and columns between content.
|
||||||
pub gutter: Gen<Vec<TrackSizing>>,
|
pub gutter: Spec<Vec<TrackSizing>>,
|
||||||
/// The nodes to be arranged in a grid.
|
/// The nodes to be arranged in a grid.
|
||||||
pub children: Vec<LayoutNode>,
|
pub children: Vec<LayoutNode>,
|
||||||
}
|
}
|
||||||
@ -50,10 +48,6 @@ impl From<GridNode> for LayoutNode {
|
|||||||
|
|
||||||
/// Performs grid layout.
|
/// Performs grid layout.
|
||||||
struct GridLayouter<'a> {
|
struct GridLayouter<'a> {
|
||||||
/// The axis of the inline direction.
|
|
||||||
inline: SpecAxis,
|
|
||||||
/// The axis of the block direction.
|
|
||||||
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,15 +62,15 @@ struct GridLayouter<'a> {
|
|||||||
rcols: Vec<Length>,
|
rcols: Vec<Length>,
|
||||||
/// The full block 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 inline size is determined
|
/// The used-up size of the current region. The horizontal size is
|
||||||
/// once after columns are resolved and not touched again.
|
/// determined once after columns are resolved and not touched again.
|
||||||
used: Gen<Length>,
|
used: Size,
|
||||||
/// The sum of fractional ratios in the current region.
|
/// The sum of fractional ratios in the current region.
|
||||||
fr: Fractional,
|
fr: Fractional,
|
||||||
/// Rows in the current region.
|
/// Rows in the current region.
|
||||||
lrows: Vec<Row>,
|
lrows: Vec<Row>,
|
||||||
/// Constraints for the active region.
|
/// Constraints for the active region.
|
||||||
constraints: Constraints,
|
cts: Constraints,
|
||||||
/// Frames for finished regions.
|
/// Frames for finished regions.
|
||||||
finished: Vec<Constrained<Rc<Frame>>>,
|
finished: Vec<Constrained<Rc<Frame>>>,
|
||||||
}
|
}
|
||||||
@ -97,13 +91,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.inline.len().max(1);
|
let c = grid.tracks.x.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.block.len();
|
let given = grid.tracks.y.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)
|
||||||
};
|
};
|
||||||
@ -116,42 +110,38 @@ 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.inline, x, auto));
|
cols.push(get_or(&grid.tracks.x, x, auto));
|
||||||
cols.push(get_or(&grid.gutter.inline, x, zero));
|
cols.push(get_or(&grid.gutter.x, 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.block, y, auto));
|
rows.push(get_or(&grid.tracks.y, y, auto));
|
||||||
rows.push(get_or(&grid.gutter.block, y, zero));
|
rows.push(get_or(&grid.gutter.y, y, zero));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove superfluous gutter tracks.
|
// Remove superfluous gutter tracks.
|
||||||
cols.pop();
|
cols.pop();
|
||||||
rows.pop();
|
rows.pop();
|
||||||
|
|
||||||
let inline = grid.dirs.inline.axis();
|
let full = regions.current.h;
|
||||||
let block = grid.dirs.block.axis();
|
|
||||||
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(block);
|
regions.expand = Spec::new(true, false);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
inline,
|
|
||||||
block,
|
|
||||||
cols,
|
cols,
|
||||||
rows,
|
rows,
|
||||||
children: &grid.children,
|
children: &grid.children,
|
||||||
constraints: Constraints::new(expand),
|
cts: Constraints::new(expand),
|
||||||
regions,
|
regions,
|
||||||
expand,
|
expand,
|
||||||
rcols,
|
rcols,
|
||||||
lrows: vec![],
|
lrows: vec![],
|
||||||
full,
|
full,
|
||||||
used: Gen::zero(),
|
used: Size::zero(),
|
||||||
fr: Fractional::zero(),
|
fr: Fractional::zero(),
|
||||||
finished: vec![],
|
finished: vec![],
|
||||||
}
|
}
|
||||||
@ -166,10 +156,6 @@ impl<'a> GridLayouter<'a> {
|
|||||||
Overflowing,
|
Overflowing,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic version of current and base size.
|
|
||||||
let current = self.regions.current.get(self.inline);
|
|
||||||
let base = self.regions.base.get(self.inline);
|
|
||||||
|
|
||||||
// The different cases affecting constraints.
|
// The different cases affecting constraints.
|
||||||
let mut case = Case::PurelyLinear;
|
let mut case = Case::PurelyLinear;
|
||||||
|
|
||||||
@ -187,7 +173,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
case = Case::Fitting;
|
case = Case::Fitting;
|
||||||
}
|
}
|
||||||
TrackSizing::Linear(v) => {
|
TrackSizing::Linear(v) => {
|
||||||
let resolved = v.resolve(base);
|
let resolved = v.resolve(self.regions.base.w);
|
||||||
*rcol = resolved;
|
*rcol = resolved;
|
||||||
linear += resolved;
|
linear += resolved;
|
||||||
}
|
}
|
||||||
@ -199,7 +185,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 - linear;
|
let available = self.regions.current.w - 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);
|
||||||
@ -221,24 +207,18 @@ impl<'a> GridLayouter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Children could depend on base.
|
// Children could depend on base.
|
||||||
self.constraints.base = self.regions.base.to_spec().map(Some);
|
self.cts.base = self.regions.base.to_spec().map(Some);
|
||||||
|
|
||||||
// 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 => {
|
Case::Fitting => self.cts.min.x = Some(self.used.w),
|
||||||
self.constraints.min.set(self.inline, Some(self.used.inline));
|
Case::Exact => self.cts.exact.x = Some(self.regions.current.w),
|
||||||
}
|
Case::Overflowing => self.cts.max.x = Some(linear),
|
||||||
Case::Exact => {
|
|
||||||
self.constraints.exact.set(self.inline, Some(current));
|
|
||||||
}
|
|
||||||
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.inline = self.rcols.iter().sum();
|
self.used.w = self.rcols.iter().sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Measure the size that is available to auto columns.
|
/// Measure the size that is available to auto columns.
|
||||||
@ -247,8 +227,6 @@ impl<'a> GridLayouter<'a> {
|
|||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
available: Length,
|
available: Length,
|
||||||
) -> (Length, usize) {
|
) -> (Length, usize) {
|
||||||
let base = self.regions.base.get(self.block);
|
|
||||||
|
|
||||||
let mut auto = Length::zero();
|
let mut auto = Length::zero();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
@ -262,7 +240,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
let mut resolved = Length::zero();
|
let mut resolved = Length::zero();
|
||||||
for y in 0 .. self.rows.len() {
|
for y in 0 .. self.rows.len() {
|
||||||
if let Some(node) = self.cell(x, y) {
|
if let Some(node) = self.cell(x, y) {
|
||||||
let size = Gen::new(available, Length::inf()).to_size(self.block);
|
let size = Size::new(available, Length::inf());
|
||||||
let mut regions =
|
let mut regions =
|
||||||
Regions::one(size, self.regions.base, Spec::splat(false));
|
Regions::one(size, self.regions.base, Spec::splat(false));
|
||||||
|
|
||||||
@ -270,11 +248,11 @@ impl<'a> GridLayouter<'a> {
|
|||||||
// base, for auto it's already correct and for fr we could
|
// base, for auto it's already correct and for fr we could
|
||||||
// only guess anyway.
|
// only guess anyway.
|
||||||
if let TrackSizing::Linear(v) = self.rows[y] {
|
if let TrackSizing::Linear(v) = self.rows[y] {
|
||||||
regions.base.set(self.block, v.resolve(base));
|
regions.base.h = v.resolve(self.regions.base.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
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.inline));
|
resolved.set_max(frame.size.w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +314,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
TrackSizing::Linear(v) => self.layout_linear_row(ctx, v, y),
|
TrackSizing::Linear(v) => self.layout_linear_row(ctx, v, y),
|
||||||
TrackSizing::Fractional(v) => {
|
TrackSizing::Fractional(v) => {
|
||||||
self.fr += v;
|
self.fr += v;
|
||||||
self.constraints.exact.set(self.block, Some(self.full));
|
self.cts.exact.y = Some(self.full);
|
||||||
self.lrows.push(Row::Fr(v, y));
|
self.lrows.push(Row::Fr(v, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,27 +327,22 @@ impl<'a> GridLayouter<'a> {
|
|||||||
/// Layout a row with automatic size along the block 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 base = self.regions.base.get(self.inline);
|
|
||||||
let mut resolved: Vec<Length> = vec![];
|
let mut resolved: Vec<Length> = vec![];
|
||||||
|
|
||||||
// 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 inline = self.inline;
|
|
||||||
|
|
||||||
let mut regions = self.regions.clone();
|
let mut regions = self.regions.clone();
|
||||||
regions.mutate(|size| size.set(inline, rcol));
|
regions.mutate(|size| size.w = rcol);
|
||||||
|
|
||||||
// Set the inline base back to the parent region's inline base
|
// Set the horizontal base back to the parent region's base for
|
||||||
// for auto columns.
|
// auto columns.
|
||||||
if self.cols[x] == TrackSizing::Auto {
|
if self.cols[x] == TrackSizing::Auto {
|
||||||
regions.base.set(self.inline, base);
|
regions.base.w = self.regions.base.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut sizes = node
|
let mut sizes =
|
||||||
.layout(ctx, ®ions)
|
node.layout(ctx, ®ions).into_iter().map(|frame| frame.item.size.h);
|
||||||
.into_iter()
|
|
||||||
.map(|frame| frame.item.size.get(self.block));
|
|
||||||
|
|
||||||
for (target, size) in resolved.iter_mut().zip(&mut sizes) {
|
for (target, size) in resolved.iter_mut().zip(&mut sizes) {
|
||||||
target.set_max(size);
|
target.set_max(size);
|
||||||
@ -398,7 +371,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
for (target, (current, _)) in
|
for (target, (current, _)) in
|
||||||
resolved[.. len - 1].iter_mut().zip(self.regions.iter())
|
resolved[.. len - 1].iter_mut().zip(self.regions.iter())
|
||||||
{
|
{
|
||||||
target.set_max(current.get(self.block));
|
target.set_max(current.h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,7 +381,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
for (i, frame) in frames.into_iter().enumerate() {
|
for (i, frame) in frames.into_iter().enumerate() {
|
||||||
self.push_row(frame);
|
self.push_row(frame);
|
||||||
if i + 1 < len {
|
if i + 1 < len {
|
||||||
self.constraints.exact.set(self.block, Some(self.full));
|
self.cts.exact.y = Some(self.full);
|
||||||
self.finish_region(ctx);
|
self.finish_region(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -417,16 +390,13 @@ impl<'a> GridLayouter<'a> {
|
|||||||
/// Layout a row with linear sizing along the block axis. Such a row cannot
|
/// Layout a row with linear sizing along the block axis. Such a row cannot
|
||||||
/// break across multiple regions, but it may force a region break.
|
/// break across multiple regions, but it may force a region break.
|
||||||
fn layout_linear_row(&mut self, ctx: &mut LayoutContext, v: Linear, y: usize) {
|
fn layout_linear_row(&mut self, ctx: &mut LayoutContext, v: Linear, y: usize) {
|
||||||
let base = self.regions.base.get(self.block);
|
let resolved = v.resolve(self.regions.base.h);
|
||||||
let resolved = v.resolve(base);
|
|
||||||
let frame = self.layout_single_row(ctx, resolved, y);
|
let frame = self.layout_single_row(ctx, resolved, y);
|
||||||
|
|
||||||
// Skip to fitting region.
|
// Skip to fitting region.
|
||||||
let length = frame.size.get(self.block);
|
let length = frame.size.h;
|
||||||
while !self.regions.current.get(self.block).fits(length)
|
while !self.regions.current.h.fits(length) && !self.regions.in_full_last() {
|
||||||
&& !self.regions.in_full_last()
|
self.cts.max.y = Some(self.used.h + length);
|
||||||
{
|
|
||||||
self.constraints.max.set(self.block, Some(self.used.block + length));
|
|
||||||
self.finish_region(ctx);
|
self.finish_region(ctx);
|
||||||
|
|
||||||
// Don't skip multiple regions for gutter and don't push a row.
|
// Don't skip multiple regions for gutter and don't push a row.
|
||||||
@ -442,34 +412,31 @@ impl<'a> GridLayouter<'a> {
|
|||||||
fn layout_single_row(
|
fn layout_single_row(
|
||||||
&self,
|
&self,
|
||||||
ctx: &mut LayoutContext,
|
ctx: &mut LayoutContext,
|
||||||
block: Length,
|
height: Length,
|
||||||
y: usize,
|
y: usize,
|
||||||
) -> Frame {
|
) -> Frame {
|
||||||
let size = self.complete(block);
|
let mut output = Frame::new(Size::new(self.used.w, height), height);
|
||||||
|
let mut pos = Point::zero();
|
||||||
let mut output = Frame::new(size, size.h);
|
|
||||||
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, block).to_size(self.block);
|
let size = Size::new(rcol, height);
|
||||||
let mut base = self.regions.base;
|
|
||||||
|
|
||||||
// Set the base to the size for non-auto rows.
|
// Set the base to the size for non-auto rows.
|
||||||
let sizing = Gen::new(self.cols[x], self.rows[y]).to_spec(self.block);
|
let mut base = self.regions.base;
|
||||||
if sizing.x != TrackSizing::Auto {
|
if self.cols[x] != TrackSizing::Auto {
|
||||||
base.w = size.w;
|
base.w = size.w;
|
||||||
}
|
}
|
||||||
if sizing.y != TrackSizing::Auto {
|
if self.rows[y] != TrackSizing::Auto {
|
||||||
base.h = size.h;
|
base.h = size.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
let regions = Regions::one(size, base, Spec::splat(true));
|
let regions = Regions::one(size, base, 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.block), frame.item);
|
output.push_frame(pos, frame.item);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos.inline += rcol;
|
pos.x += rcol;
|
||||||
}
|
}
|
||||||
|
|
||||||
output
|
output
|
||||||
@ -482,44 +449,41 @@ impl<'a> GridLayouter<'a> {
|
|||||||
resolved: &[Length],
|
resolved: &[Length],
|
||||||
y: usize,
|
y: usize,
|
||||||
) -> Vec<Frame> {
|
) -> Vec<Frame> {
|
||||||
let base = self.regions.base.get(self.inline);
|
|
||||||
|
|
||||||
// Prepare frames.
|
// Prepare frames.
|
||||||
let mut outputs: Vec<_> = resolved
|
let mut outputs: Vec<_> = resolved
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&v| self.complete(v))
|
.map(|&h| Frame::new(Size::new(self.used.w, h), h))
|
||||||
.map(|size| Frame::new(size, size.h))
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Prepare regions.
|
// Prepare regions.
|
||||||
let size = self.complete(resolved[0]);
|
let size = Size::new(self.used.w, resolved[0]);
|
||||||
let mut regions = Regions::one(size, self.regions.base, Spec::splat(true));
|
let mut regions = Regions::one(size, self.regions.base, Spec::splat(true));
|
||||||
regions.backlog = resolved[1 ..]
|
regions.backlog = resolved[1 ..]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&v| self.complete(v))
|
.map(|&h| Size::new(self.used.w, h))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into_iter();
|
.into_iter();
|
||||||
|
|
||||||
// Layout the row.
|
// Layout the row.
|
||||||
let mut pos = Gen::zero();
|
let mut pos = Point::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.inline, rcol));
|
regions.mutate(|size| size.w = rcol);
|
||||||
|
|
||||||
// Set the inline base back to the parent region's inline base
|
// Set the horizontal base back to the parent region's base for
|
||||||
// for auto columns.
|
// auto columns.
|
||||||
if self.cols[x] == TrackSizing::Auto {
|
if self.cols[x] == TrackSizing::Auto {
|
||||||
regions.base.set(self.inline, base);
|
regions.base.w = self.regions.base.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.block), frame.item);
|
output.push_frame(pos, frame.item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos.inline += rcol;
|
pos.x += rcol;
|
||||||
}
|
}
|
||||||
|
|
||||||
outputs
|
outputs
|
||||||
@ -527,30 +491,28 @@ impl<'a> GridLayouter<'a> {
|
|||||||
|
|
||||||
/// Push a row frame into the current region.
|
/// Push a row frame into the current region.
|
||||||
fn push_row(&mut self, frame: Frame) {
|
fn push_row(&mut self, frame: Frame) {
|
||||||
let length = frame.size.get(self.block);
|
self.regions.current.h -= frame.size.h;
|
||||||
*self.regions.current.get_mut(self.block) -= length;
|
self.used.h += frame.size.h;
|
||||||
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 block size of the region.
|
// Determine the height of the region's frame.
|
||||||
let block = if self.fr.is_zero() || self.full.is_infinite() {
|
let height = if self.fr.is_zero() || self.full.is_infinite() {
|
||||||
self.used.block
|
self.used.h
|
||||||
} else {
|
} else {
|
||||||
self.full
|
self.full
|
||||||
};
|
};
|
||||||
|
|
||||||
let size = self.complete(block);
|
self.cts.min.y = Some(height);
|
||||||
self.constraints.min.set(self.block, Some(block));
|
|
||||||
|
|
||||||
// The frame for the region.
|
// The frame for the region.
|
||||||
let mut output = Frame::new(size, size.h);
|
let mut output = Frame::new(Size::new(self.used.w, height), height);
|
||||||
let mut pos = Gen::zero();
|
let mut pos = Point::zero();
|
||||||
|
|
||||||
// Determine the remaining size for fractional rows.
|
// Determine the size that remains for fractional rows.
|
||||||
let remaining = self.full - self.used.block;
|
let remaining = self.full - self.used.h;
|
||||||
|
|
||||||
// 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) {
|
||||||
@ -567,17 +529,17 @@ impl<'a> GridLayouter<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let point = pos.to_point(self.block);
|
let height = frame.size.h;
|
||||||
pos.block += frame.size.get(self.block);
|
output.merge_frame(pos, frame);
|
||||||
output.merge_frame(point, frame);
|
pos.y += height;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.regions.next();
|
self.regions.next();
|
||||||
self.full = self.regions.current.get(self.block);
|
self.full = self.regions.current.h;
|
||||||
self.used.block = Length::zero();
|
self.used.h = Length::zero();
|
||||||
self.fr = Fractional::zero();
|
self.fr = Fractional::zero();
|
||||||
self.finished.push(output.constrain(self.constraints));
|
self.finished.push(output.constrain(self.cts));
|
||||||
self.constraints = Constraints::new(self.expand);
|
self.cts = Constraints::new(self.expand);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the node in the cell in column `x` and row `y`.
|
/// Get the node in the cell in column `x` and row `y`.
|
||||||
@ -596,10 +558,4 @@ impl<'a> GridLayouter<'a> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a size where the inline axis spans the whole grid and the block
|
|
||||||
/// axis the given length.
|
|
||||||
fn complete(&self, block: Length) -> Size {
|
|
||||||
Gen::new(self.used.inline, block).to_size(self.block)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -266,49 +266,26 @@ pub fn grid(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|||||||
|
|
||||||
let columns = args.named("columns")?.unwrap_or_default();
|
let columns = args.named("columns")?.unwrap_or_default();
|
||||||
let rows = args.named("rows")?.unwrap_or_default();
|
let rows = args.named("rows")?.unwrap_or_default();
|
||||||
let tracks = Gen::new(columns, rows);
|
let tracks = Spec::new(columns, rows);
|
||||||
|
|
||||||
let base_gutter: Vec<TrackSizing> = args.named("gutter")?.unwrap_or_default();
|
let base_gutter: Vec<TrackSizing> = args.named("gutter")?.unwrap_or_default();
|
||||||
let column_gutter = args.named("column-gutter")?;
|
let column_gutter = args.named("column-gutter")?;
|
||||||
let row_gutter = args.named("row-gutter")?;
|
let row_gutter = args.named("row-gutter")?;
|
||||||
let gutter = Gen::new(
|
let gutter = Spec::new(
|
||||||
column_gutter.unwrap_or_else(|| base_gutter.clone()),
|
column_gutter.unwrap_or_else(|| base_gutter.clone()),
|
||||||
row_gutter.unwrap_or(base_gutter),
|
row_gutter.unwrap_or(base_gutter),
|
||||||
);
|
);
|
||||||
|
|
||||||
let column_dir = args.named("column-dir")?;
|
|
||||||
let row_dir = args.named("row-dir")?;
|
|
||||||
|
|
||||||
let children: Vec<Template> = args.all().collect();
|
let children: Vec<Template> = args.all().collect();
|
||||||
|
|
||||||
Ok(Value::Template(Template::from_block(move |style| {
|
Ok(Value::Template(Template::from_block(move |style| {
|
||||||
// If the directions become aligned, try to fix up the direction which
|
|
||||||
// is not user-defined.
|
|
||||||
let mut dirs =
|
|
||||||
Gen::new(column_dir.unwrap_or(style.dir), row_dir.unwrap_or(Dir::TTB));
|
|
||||||
|
|
||||||
if dirs.block.axis() == dirs.inline.axis() {
|
|
||||||
let target = if column_dir.is_some() {
|
|
||||||
&mut dirs.block
|
|
||||||
} else {
|
|
||||||
&mut dirs.inline
|
|
||||||
};
|
|
||||||
|
|
||||||
*target = if target.axis() == style.dir.axis() {
|
|
||||||
Dir::TTB
|
|
||||||
} else {
|
|
||||||
style.dir
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let children =
|
|
||||||
children.iter().map(|child| child.to_stack(&style).into()).collect();
|
|
||||||
|
|
||||||
GridNode {
|
GridNode {
|
||||||
dirs,
|
|
||||||
tracks: tracks.clone(),
|
tracks: tracks.clone(),
|
||||||
gutter: gutter.clone(),
|
gutter: gutter.clone(),
|
||||||
children,
|
children: children
|
||||||
|
.iter()
|
||||||
|
.map(|child| child.to_stack(&style).into())
|
||||||
|
.collect(),
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 3.2 KiB |
@ -32,19 +32,6 @@
|
|||||||
rect(width: 100%, fill: rgb("dddddd"))[aaa],
|
rect(width: 100%, fill: rgb("dddddd"))[aaa],
|
||||||
)
|
)
|
||||||
|
|
||||||
---
|
|
||||||
#page(height: 3cm, width: 2cm)
|
|
||||||
#grid(
|
|
||||||
columns: (1fr, 1cm, 1fr, 1fr),
|
|
||||||
column-dir: ttb,
|
|
||||||
rows: (auto, 1fr),
|
|
||||||
rect(height: 100%, fill: rgb("222222"))[foo],
|
|
||||||
rect(height: 100%, fill: rgb("547d0a"))[bar],
|
|
||||||
rect(height: 100%, fill: eastern)[hab],
|
|
||||||
rect(height: 100%, fill: conifer)[baz],
|
|
||||||
rect(height: 100%, width: 100%, fill: rgb("547d0a"))[bar],
|
|
||||||
)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
#page(height: 3cm, margins: 0pt)
|
#page(height: 3cm, margins: 0pt)
|
||||||
#align(center)
|
#align(center)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user