mirror of
https://github.com/typst/typst
synced 2025-05-17 02:25:27 +08:00
Rename run to line and add some explanatory comments ✏
The name run was a relict of the time where a line consisted of a set of runs with same alignment. While these runs still exist conceptually, they are all stored flatly together in what was now renamed from `run` to `line`.
This commit is contained in:
parent
a0de9aad07
commit
b2b8d37ce0
@ -16,9 +16,9 @@ impl Layout for NodeBackground {
|
|||||||
for frame in layouted.frames_mut() {
|
for frame in layouted.frames_mut() {
|
||||||
let element = Element::Geometry(Geometry {
|
let element = Element::Geometry(Geometry {
|
||||||
shape: Shape::Rect(frame.size),
|
shape: Shape::Rect(frame.size),
|
||||||
fill: self.fill.clone(),
|
fill: self.fill,
|
||||||
});
|
});
|
||||||
frame.elements.insert(0, (Point::ZERO, element))
|
frame.elements.insert(0, (Point::ZERO, element));
|
||||||
}
|
}
|
||||||
|
|
||||||
layouted
|
layouted
|
||||||
|
@ -229,15 +229,6 @@ pub enum Element {
|
|||||||
Geometry(Geometry),
|
Geometry(Geometry),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The kind of graphic fill to be applied to a [`Shape`].
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub enum Fill {
|
|
||||||
/// The fill is a color.
|
|
||||||
Color(Color),
|
|
||||||
/// The fill is an image.
|
|
||||||
Image(Image),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A shape with some kind of fill.
|
/// A shape with some kind of fill.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Geometry {
|
pub struct Geometry {
|
||||||
@ -258,8 +249,17 @@ pub enum Shape {
|
|||||||
Rect(Size),
|
Rect(Size),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The kind of graphic fill to be applied to a [`Shape`].
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
pub enum Fill {
|
||||||
|
/// The fill is a color.
|
||||||
|
Color(Color),
|
||||||
|
/// The fill is an image.
|
||||||
|
Image(Image),
|
||||||
|
}
|
||||||
|
|
||||||
/// An image element.
|
/// An image element.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub struct Image {
|
pub struct Image {
|
||||||
/// The image resource.
|
/// The image resource.
|
||||||
pub res: ResourceId,
|
pub res: ResourceId,
|
||||||
|
@ -51,9 +51,9 @@ struct ParLayouter<'a> {
|
|||||||
finished: Vec<Frame>,
|
finished: Vec<Frame>,
|
||||||
lines: Vec<(Length, Frame, Align)>,
|
lines: Vec<(Length, Frame, Align)>,
|
||||||
lines_size: Gen<Length>,
|
lines_size: Gen<Length>,
|
||||||
run: Vec<(Length, Frame, Align)>,
|
line: Vec<(Length, Frame, Align)>,
|
||||||
run_size: Gen<Length>,
|
line_size: Gen<Length>,
|
||||||
run_ruler: Align,
|
line_ruler: Align,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParLayouter<'a> {
|
impl<'a> ParLayouter<'a> {
|
||||||
@ -67,34 +67,54 @@ impl<'a> ParLayouter<'a> {
|
|||||||
finished: vec![],
|
finished: vec![],
|
||||||
lines: vec![],
|
lines: vec![],
|
||||||
lines_size: Gen::ZERO,
|
lines_size: Gen::ZERO,
|
||||||
run: vec![],
|
line: vec![],
|
||||||
run_size: Gen::ZERO,
|
line_size: Gen::ZERO,
|
||||||
run_ruler: Align::Start,
|
line_ruler: Align::Start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_spacing(&mut self, amount: Length) {
|
fn push_spacing(&mut self, amount: Length) {
|
||||||
let cross_max = self.areas.current.get(self.cross);
|
let cross_max = self.areas.current.get(self.cross);
|
||||||
self.run_size.cross = (self.run_size.cross + amount).min(cross_max);
|
self.line_size.cross = (self.line_size.cross + amount).min(cross_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_frame(&mut self, frame: Frame, align: Align) {
|
fn push_frame(&mut self, frame: Frame, align: Align) {
|
||||||
if self.run_ruler > align {
|
// When the alignment of the last pushed frame (stored in the "ruler")
|
||||||
self.finish_run();
|
// is further to the end than the new `frame`, we need a line break.
|
||||||
|
//
|
||||||
|
// For example
|
||||||
|
// ```
|
||||||
|
// #align(right)[First] #align(center)[Second]
|
||||||
|
// ```
|
||||||
|
// would be laid out as:
|
||||||
|
// +----------------------------+
|
||||||
|
// | First |
|
||||||
|
// | Second |
|
||||||
|
// +----------------------------+
|
||||||
|
if self.line_ruler > align {
|
||||||
|
self.finish_line();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find out whether the area still has enough space for this frame.
|
||||||
|
// Space occupied by previous lines is already removed from
|
||||||
|
// `areas.current`, but the cross-extent of the current line needs to be
|
||||||
|
// subtracted to make sure the frame fits.
|
||||||
let fits = {
|
let fits = {
|
||||||
let mut usable = self.areas.current;
|
let mut usable = self.areas.current;
|
||||||
*usable.get_mut(self.cross) -= self.run_size.cross;
|
*usable.get_mut(self.cross) -= self.line_size.cross;
|
||||||
usable.fits(frame.size)
|
usable.fits(frame.size)
|
||||||
};
|
};
|
||||||
|
|
||||||
if !fits {
|
if !fits {
|
||||||
self.finish_run();
|
self.finish_line();
|
||||||
|
|
||||||
|
// Here, we can directly check whether the frame fits into
|
||||||
|
// `areas.current` since we just called `finish_line`.
|
||||||
while !self.areas.current.fits(frame.size) {
|
while !self.areas.current.fits(frame.size) {
|
||||||
if self.areas.in_full_last() {
|
if self.areas.in_full_last() {
|
||||||
// TODO: Diagnose once the necessary spans exist.
|
// The frame fits nowhere.
|
||||||
|
// TODO: Should this be placed into the first area or the last?
|
||||||
|
// TODO: Produce diagnostic once the necessary spans exist.
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
self.finish_area();
|
self.finish_area();
|
||||||
@ -103,36 +123,39 @@ impl<'a> ParLayouter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let size = frame.size.switch(self.dirs);
|
let size = frame.size.switch(self.dirs);
|
||||||
self.run.push((self.run_size.cross, frame, align));
|
|
||||||
|
|
||||||
self.run_size.cross += size.cross;
|
// A line can contain frames with different alignments. They exact
|
||||||
self.run_size.main = self.run_size.main.max(size.main);
|
// positions are calculated later depending on the alignments.
|
||||||
self.run_ruler = align;
|
self.line.push((self.line_size.cross, frame, align));
|
||||||
|
|
||||||
|
self.line_size.cross += size.cross;
|
||||||
|
self.line_size.main = self.line_size.main.max(size.main);
|
||||||
|
self.line_ruler = align;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish_run(&mut self) {
|
fn finish_line(&mut self) {
|
||||||
let full_size = {
|
let full_size = {
|
||||||
let full = self.areas.full.switch(self.dirs);
|
let full = self.areas.full.switch(self.dirs);
|
||||||
Gen::new(
|
Gen::new(
|
||||||
self.run_size.main,
|
self.line_size.main,
|
||||||
self.par
|
self.par
|
||||||
.cross_expansion
|
.cross_expansion
|
||||||
.resolve(self.run_size.cross.min(full.cross), full.cross),
|
.resolve(self.line_size.cross.min(full.cross), full.cross),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut output = Frame::new(full_size.switch(self.dirs).to_size());
|
let mut output = Frame::new(full_size.switch(self.dirs).to_size());
|
||||||
|
|
||||||
for (before, frame, align) in std::mem::take(&mut self.run) {
|
for (before, frame, align) in std::mem::take(&mut self.line) {
|
||||||
let child_cross_size = frame.size.get(self.cross);
|
let child_cross_size = frame.size.get(self.cross);
|
||||||
|
|
||||||
// Position along the cross axis.
|
// Position along the cross axis.
|
||||||
let cross = align.resolve(if self.dirs.cross.is_positive() {
|
let cross = align.resolve(if self.dirs.cross.is_positive() {
|
||||||
let after_with_self = self.run_size.cross - before;
|
let after_with_self = self.line_size.cross - before;
|
||||||
before .. full_size.cross - after_with_self
|
before .. full_size.cross - after_with_self
|
||||||
} else {
|
} else {
|
||||||
let before_with_self = before + child_cross_size;
|
let before_with_self = before + child_cross_size;
|
||||||
let after = self.run_size.cross - (before + child_cross_size);
|
let after = self.line_size.cross - (before + child_cross_size);
|
||||||
full_size.cross - before_with_self .. after
|
full_size.cross - before_with_self .. after
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -140,23 +163,25 @@ impl<'a> ParLayouter<'a> {
|
|||||||
output.push_frame(pos, frame);
|
output.push_frame(pos, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.lines.push((self.lines_size.main, output, self.run_ruler));
|
// Update metrics of the whole paragraph.
|
||||||
|
self.lines.push((self.lines_size.main, output, self.line_ruler));
|
||||||
let main_offset = full_size.main + self.par.line_spacing;
|
self.lines_size.main += full_size.main;
|
||||||
*self.areas.current.get_mut(self.main) -= main_offset;
|
self.lines_size.main += self.par.line_spacing;
|
||||||
self.lines_size.main += main_offset;
|
|
||||||
self.lines_size.cross = self.lines_size.cross.max(full_size.cross);
|
self.lines_size.cross = self.lines_size.cross.max(full_size.cross);
|
||||||
|
*self.areas.current.get_mut(self.main) -= full_size.main;
|
||||||
|
*self.areas.current.get_mut(self.main) -= self.par.line_spacing;
|
||||||
|
|
||||||
self.run_size = Gen::ZERO;
|
// Reset metrics for the single line.
|
||||||
self.run_ruler = Align::Start;
|
self.line_size = Gen::ZERO;
|
||||||
|
self.line_ruler = Align::Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish_area(&mut self) {
|
fn finish_area(&mut self) {
|
||||||
let size = self.lines_size;
|
let size = self.lines_size;
|
||||||
let mut output = Frame::new(size.switch(self.dirs).to_size());
|
let mut output = Frame::new(size.switch(self.dirs).to_size());
|
||||||
|
|
||||||
for (before, run, cross_align) in std::mem::take(&mut self.lines) {
|
for (before, line, cross_align) in std::mem::take(&mut self.lines) {
|
||||||
let child_size = run.size.switch(self.dirs);
|
let child_size = line.size.switch(self.dirs);
|
||||||
|
|
||||||
// Position along the main axis.
|
// Position along the main axis.
|
||||||
let main = if self.dirs.main.is_positive() {
|
let main = if self.dirs.main.is_positive() {
|
||||||
@ -173,17 +198,18 @@ impl<'a> ParLayouter<'a> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let pos = Gen::new(main, cross).switch(self.dirs).to_point();
|
let pos = Gen::new(main, cross).switch(self.dirs).to_point();
|
||||||
output.push_frame(pos, run);
|
output.push_frame(pos, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.finished.push(output);
|
self.finished.push(output);
|
||||||
|
|
||||||
self.areas.next();
|
self.areas.next();
|
||||||
|
|
||||||
|
// Reset metrics for the whole paragraph.
|
||||||
self.lines_size = Gen::ZERO;
|
self.lines_size = Gen::ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(mut self) -> Vec<Frame> {
|
fn finish(mut self) -> Vec<Frame> {
|
||||||
self.finish_run();
|
self.finish_line();
|
||||||
self.finish_area();
|
self.finish_area();
|
||||||
self.finished
|
self.finished
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user