Remove baseline weirdness

This commit is contained in:
Laurenz 2021-12-02 14:48:12 +01:00
parent f3bdc9d3da
commit bfa9962632
16 changed files with 60 additions and 58 deletions

View File

@ -14,8 +14,9 @@ use crate::image::ImageId;
pub struct Frame {
/// The size of the frame.
pub size: Size,
/// The baseline of the frame measured from the top.
pub baseline: Length,
/// The baseline of the frame measured from the top. If this is `None`, the
/// frame's implicit baseline is at the bottom.
pub baseline: Option<Length>,
/// The elements composing this layout.
pub elements: Vec<(Point, Element)>,
}
@ -25,7 +26,12 @@ impl Frame {
#[track_caller]
pub fn new(size: Size) -> Self {
assert!(size.is_finite());
Self { size, baseline: size.y, elements: vec![] }
Self { size, baseline: None, elements: vec![] }
}
/// The baseline of the frame.
pub fn baseline(&self) -> Length {
self.baseline.unwrap_or(self.size.y)
}
/// Add an element at a position in the background.
@ -64,17 +70,21 @@ impl Frame {
aligns.y.resolve(target.y - self.size.y),
);
self.size = target;
self.baseline += offset.y;
self.translate(offset);
}
}
/// Move the contents of the frame by an offset.
/// Move the baseline and contents of the frame by an offset.
pub fn translate(&mut self, offset: Point) {
if !offset.is_zero() {
if let Some(baseline) = &mut self.baseline {
*baseline += offset.y;
}
for (point, _) in &mut self.elements {
*point += offset;
}
}
}
/// Arbitrarily transform the contents of the frame.
pub fn transform(&mut self, transform: Transform) {

View File

@ -35,12 +35,9 @@ impl Point {
Self { x: Length::zero(), y }
}
/// Convert to the generic representation.
pub const fn to_gen(self, main: SpecAxis) -> Gen<Length> {
match main {
SpecAxis::Horizontal => Gen::new(self.y, self.x),
SpecAxis::Vertical => Gen::new(self.x, self.y),
}
/// Whether both components are zero.
pub fn is_zero(self) -> bool {
self.x.is_zero() && self.y.is_zero()
}
/// Transform the point with the given transformation.

View File

@ -193,6 +193,11 @@ impl Size {
self.x.fits(other.x) && self.y.fits(other.y)
}
/// Whether both components are zero.
pub fn is_zero(self) -> bool {
self.x.is_zero() && self.y.is_zero()
}
/// Whether both components are finite.
pub fn is_finite(self) -> bool {
self.x.is_finite() && self.y.is_finite()

View File

@ -214,38 +214,28 @@ impl<'a> FlowLayouter<'a> {
}
let mut output = Frame::new(size);
let mut before = Length::zero();
let mut offset = Length::zero();
let mut ruler = Align::Top;
let mut first = true;
// Place all frames.
for item in self.items.drain(..) {
match item {
FlowItem::Absolute(v) => {
before += v;
offset += v;
}
FlowItem::Fractional(v) => {
before += v.resolve(self.fr, remaining);
offset += v.resolve(self.fr, remaining);
}
FlowItem::Frame(frame, aligns) => {
ruler = ruler.max(aligns.y);
// Align horizontally and vertically.
let x = aligns.x.resolve(size.x - frame.size.x);
let y = before + ruler.resolve(size.y - self.used.y);
let y = offset + ruler.resolve(size.y - self.used.y);
let pos = Point::new(x, y);
before += frame.size.y;
// The baseline of the flow is that of the first frame.
if first {
output.baseline = pos.y + frame.baseline;
first = false;
}
offset += frame.size.y;
output.push_frame(pos, frame);
}
FlowItem::Placed(frame) => {
output.push_frame(Point::with_y(before), frame);
output.push_frame(Point::with_y(offset), frame);
}
}
}

View File

@ -51,7 +51,6 @@ impl Layout for PadNode {
// Grow the frame and translate everything in the frame inwards.
let frame = Rc::make_mut(frame);
frame.size = padded;
frame.baseline += offset.y;
frame.translate(offset);
// Set exact and base constraints if the child had them. Also set

View File

@ -466,14 +466,18 @@ impl<'a> LineLayout<'a> {
// Measure the size of the line.
for item in first.iter().chain(items).chain(&last) {
match *item {
ParItem::Absolute(v) => width += v,
ParItem::Fractional(v) => fr += v,
ParItem::Text(ShapedText { size, baseline, .. })
| ParItem::Frame(Frame { size, baseline, .. }) => {
width += size.x;
top.set_max(baseline);
bottom.set_max(size.y - baseline);
match item {
ParItem::Absolute(v) => width += *v,
ParItem::Fractional(v) => fr += *v,
ParItem::Text(shaped) => {
width += shaped.size.x;
top.set_max(shaped.baseline);
bottom.set_max(shaped.size.y - shaped.baseline);
}
ParItem::Frame(frame) => {
width += frame.size.x;
top.set_max(frame.baseline());
bottom.set_max(frame.size.y - frame.baseline());
}
}
}
@ -496,9 +500,9 @@ impl<'a> LineLayout<'a> {
let size = Size::new(self.size.x.max(width), self.size.y);
let remaining = size.x - self.size.x;
let mut output = Frame::new(size);
let mut offset = Length::zero();
output.baseline = self.baseline;
let mut output = Frame::new(size);
output.baseline = Some(self.baseline);
for (range, item) in self.reordered() {
let mut position = |mut frame: Frame| {
@ -510,7 +514,7 @@ impl<'a> LineLayout<'a> {
}
let x = offset + self.par.align.resolve(remaining);
let y = self.baseline - frame.baseline;
let y = self.baseline - frame.baseline();
offset += frame.size.x;
// Add to the line's frame.
@ -633,17 +637,10 @@ impl<'a> LineStack<'a> {
let mut output = Frame::new(self.size);
let mut offset = Length::zero();
let mut first = true;
for line in self.lines.drain(..) {
let frame = line.build(ctx, self.size.x);
let pos = Point::with_y(offset);
if first {
output.baseline = pos.y + frame.baseline;
first = false;
}
offset += frame.size.y + self.leading;
output.merge_frame(pos, frame);
}

View File

@ -305,9 +305,9 @@ pub struct ShapedGlyph {
impl<'a> ShapedText<'a> {
/// Build the shaped text's frame.
pub fn build(&self) -> Frame {
let mut frame = Frame::new(self.size);
let mut offset = Length::zero();
frame.baseline = self.baseline;
let mut frame = Frame::new(self.size);
frame.baseline = Some(self.baseline);
for (face_id, group) in self.glyphs.as_ref().group_by_key(|g| g.face_id) {
let pos = Point::new(offset, self.baseline);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
tests/ref/text/baseline.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

View File

@ -42,6 +42,10 @@ Stuff \
Stuff
#image("../../res/rhino.png")
---
// Test baseline.
A #image("../../res/tiger.jpg", height: 1cm, width: 80%) B
---
// Error: 8-29 file not found
#image("path/does/not/exist")

View File

@ -11,14 +11,10 @@
---
// Test alignment in automatically sized square and circle.
#font(8pt)
#grid(
columns: 2,
gutter: 10pt,
square(padding: 4pt)[
#square(padding: 4pt)[
Hey there, #align(center + bottom, rotate(180deg, [you!]))
],
circle(align(center + horizon, [Hey.])),
)
]
#circle(align(center + horizon, [Hey.]))
---
// Test that maximum wins if both width and height are given.

View File

@ -0,0 +1,4 @@
// Test text baseline.
---
Hi #font(150%)[You], #font(75%)[how are you?]