Skip to content

Commit 40a8795

Browse files
committed
Round GlueSetRatio when converting from f64 -> i32
Rounding in TeX is a little inconsistent. For instance, doing ``` \dimen0=0.000029pt ``` will set `\dimen0` equal to 2 scaled points, which is about 0.00003, so the dimension value is clearly being rounded up. However, if I do ``` \dimen0=5sp \divide\dimen0 by2 ``` then `\dimen0` will now be equal to 2 scaled points, not 3, as it might be if it was rounded. So clearly, when doing integer operations, the values are floored, not rounded. It turns out that glue set ratios are similar to dimens, in that they are rounded to the nearest integer when they are initialized. (They aren't editable, so the flooring don't apply to them.) In Rust, converting from a floating point to an integer value will floor the value, so I have to explicitly round it in the code in order to achieve this same behavior. I noticed this because in the final stage test, one of the elements was exactly one sp off from the output that TeX gives. This was because when centering an element in a generalized fraction, we surround something with 2 `\hfil`, so the extra space that needs to be filled in gets divided by 2, and if that space is an odd number of sp, it should be rounded up instead of floored. I will eventually get around to fixing the issue of Dimens needing to be rounded as well.
1 parent bd9266b commit 40a8795

3 files changed

Lines changed: 109 additions & 3 deletions

File tree

examples/math.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@
1919
\mathcode`\,="613B
2020
\noindent $(a+b:1,0)$
2121

22-
\end
22+
\end

src/boxes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl GlueSetRatio {
3838
pub fn from(kind: GlueSetRatioKind, ratio: f64) -> GlueSetRatio {
3939
GlueSetRatio {
4040
kind,
41-
stretch: (ratio * 65536.0) as i32,
41+
stretch: (ratio * 65536.0).round() as i32,
4242
}
4343
}
4444

src/parser/boxes.rs

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ impl<'a> Parser<'a> {
326326
mod tests {
327327
use super::*;
328328

329-
use crate::dimension::{Dimen, Unit};
329+
use crate::dimension::{Dimen, FilDimen, FilKind, Unit};
330330
use crate::font::Font;
331331
use crate::testing::with_parser;
332332

@@ -808,4 +808,110 @@ mod tests {
808808
},
809809
);
810810
}
811+
812+
#[test]
813+
fn it_rounds_glue_set_ratio_to_the_nearest_65536th() {
814+
with_parser(
815+
&[
816+
r"\setbox0=\hbox to1sp{\hskip 0pt plus 2fil}%",
817+
r"\setbox1=\hbox to500sp{\hskip 0pt plus 1000fil}%",
818+
r"\setbox2=\hbox to500sp{\hskip 0pt plus 1001fil}%",
819+
r"\setbox3=\hbox to1500sp{\hskip 0pt plus 1000fil}%",
820+
],
821+
|parser| {
822+
parser.parse_assignment(None);
823+
parser.parse_assignment(None);
824+
parser.parse_assignment(None);
825+
parser.parse_assignment(None);
826+
827+
assert_eq!(
828+
parser.state.get_box(0),
829+
Some(TeXBox::HorizontalBox(HorizontalBox {
830+
height: Dimen::zero(),
831+
depth: Dimen::zero(),
832+
width: Dimen::from_unit(1.0, Unit::ScaledPoint),
833+
834+
list: vec![HorizontalListElem::HSkip(Glue {
835+
space: Dimen::zero(),
836+
stretch: SpringDimen::FilDimen(FilDimen::new(
837+
FilKind::Fil,
838+
2.0
839+
)),
840+
shrink: SpringDimen::Dimen(Dimen::zero()),
841+
}),],
842+
glue_set_ratio: Some(GlueSetRatio::from(
843+
GlueSetRatioKind::Fil,
844+
1.0 / 65536.0
845+
)),
846+
}))
847+
);
848+
849+
assert_eq!(
850+
parser.state.get_box(1),
851+
Some(TeXBox::HorizontalBox(HorizontalBox {
852+
height: Dimen::zero(),
853+
depth: Dimen::zero(),
854+
width: Dimen::from_unit(500.0, Unit::ScaledPoint),
855+
856+
list: vec![HorizontalListElem::HSkip(Glue {
857+
space: Dimen::zero(),
858+
stretch: SpringDimen::FilDimen(FilDimen::new(
859+
FilKind::Fil,
860+
1000.0
861+
)),
862+
shrink: SpringDimen::Dimen(Dimen::zero()),
863+
}),],
864+
glue_set_ratio: Some(GlueSetRatio::from(
865+
GlueSetRatioKind::Fil,
866+
1.0 / 65536.0
867+
)),
868+
}))
869+
);
870+
871+
assert_eq!(
872+
parser.state.get_box(2),
873+
Some(TeXBox::HorizontalBox(HorizontalBox {
874+
height: Dimen::zero(),
875+
depth: Dimen::zero(),
876+
width: Dimen::from_unit(500.0, Unit::ScaledPoint),
877+
878+
list: vec![HorizontalListElem::HSkip(Glue {
879+
space: Dimen::zero(),
880+
stretch: SpringDimen::FilDimen(FilDimen::new(
881+
FilKind::Fil,
882+
1001.0
883+
)),
884+
shrink: SpringDimen::Dimen(Dimen::zero()),
885+
}),],
886+
glue_set_ratio: Some(GlueSetRatio::from(
887+
GlueSetRatioKind::Fil,
888+
0.0
889+
)),
890+
}))
891+
);
892+
893+
assert_eq!(
894+
parser.state.get_box(3),
895+
Some(TeXBox::HorizontalBox(HorizontalBox {
896+
height: Dimen::zero(),
897+
depth: Dimen::zero(),
898+
width: Dimen::from_unit(1500.0, Unit::ScaledPoint),
899+
900+
list: vec![HorizontalListElem::HSkip(Glue {
901+
space: Dimen::zero(),
902+
stretch: SpringDimen::FilDimen(FilDimen::new(
903+
FilKind::Fil,
904+
1000.0
905+
)),
906+
shrink: SpringDimen::Dimen(Dimen::zero()),
907+
}),],
908+
glue_set_ratio: Some(GlueSetRatio::from(
909+
GlueSetRatioKind::Fil,
910+
2.0 / 65536.0
911+
)),
912+
}))
913+
);
914+
},
915+
);
916+
}
811917
}

0 commit comments

Comments
 (0)