summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordamaxwell <damaxwell@alaska.edu>2023-06-26 03:51:27 -0800
committerGitHub <noreply@github.com>2023-06-26 13:51:27 +0200
commit9eb350d7deadd59efba50b0e33acfd0967b8d0a6 (patch)
treed3a96e090bca97fb207c583ea4991ed26e939de3
parent1861ceb1792d2a42979dff2fa721246ada922a42 (diff)
support optical sizes for script/scriptscript when available (#1580)
-rw-r--r--library/src/math/ctx.rs50
-rw-r--r--library/src/math/fragment.rs30
-rw-r--r--tests/ref/bugs/math-realize.pngbin21147 -> 21228 bytes
-rw-r--r--tests/ref/compiler/content-field.pngbin2502 -> 2423 bytes
-rw-r--r--tests/ref/layout/enum-numbering.pngbin18891 -> 19079 bytes
-rw-r--r--tests/ref/math/accent.pngbin7994 -> 8038 bytes
-rw-r--r--tests/ref/math/attach.pngbin28331 -> 28615 bytes
-rw-r--r--tests/ref/math/cancel.pngbin24698 -> 24765 bytes
-rw-r--r--tests/ref/math/cases.pngbin3134 -> 2947 bytes
-rw-r--r--tests/ref/math/content.pngbin8357 -> 7883 bytes
-rw-r--r--tests/ref/math/delimited.pngbin22993 -> 23111 bytes
-rw-r--r--tests/ref/math/frac.pngbin24197 -> 24117 bytes
-rw-r--r--tests/ref/math/matrix.pngbin25677 -> 25872 bytes
-rw-r--r--tests/ref/math/multiline.pngbin13698 -> 13479 bytes
-rw-r--r--tests/ref/math/numbering.pngbin12028 -> 12019 bytes
-rw-r--r--tests/ref/math/op.pngbin6817 -> 6730 bytes
-rw-r--r--tests/ref/math/opticalsize.pngbin0 -> 6897 bytes
-rw-r--r--tests/ref/math/root.pngbin12274 -> 12575 bytes
-rw-r--r--tests/ref/math/spacing.pngbin17618 -> 18271 bytes
-rw-r--r--tests/ref/math/style.pngbin27879 -> 23804 bytes
-rw-r--r--tests/ref/math/syntax.pngbin4850 -> 4977 bytes
-rw-r--r--tests/ref/math/unbalanced.pngbin2482 -> 2443 bytes
-rw-r--r--tests/ref/math/underover.pngbin4819 -> 4797 bytes
-rw-r--r--tests/ref/meta/figure.pngbin59579 -> 49894 bytes
-rw-r--r--tests/typ/math/op.typ1
-rw-r--r--tests/typ/math/opticalsize.typ30
26 files changed, 103 insertions, 8 deletions
diff --git a/library/src/math/ctx.rs b/library/src/math/ctx.rs
index a6487476..a1dc6cf4 100644
--- a/library/src/math/ctx.rs
+++ b/library/src/math/ctx.rs
@@ -31,6 +31,7 @@ pub struct MathContext<'a, 'b, 'v> {
pub ttf: &'a ttf_parser::Face<'a>,
pub table: ttf_parser::math::Table<'a>,
pub constants: ttf_parser::math::Constants<'a>,
+ pub ssty_table: Option<ttf_parser::gsub::AlternateSubstitution<'a>>,
pub space_width: Em,
pub fragments: Vec<MathFragment>,
pub local: Styles,
@@ -50,6 +51,27 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
) -> Self {
let table = font.ttf().tables().math.unwrap();
let constants = table.constants.unwrap();
+
+ let ssty_table = font
+ .ttf()
+ .tables()
+ .gsub
+ .and_then(|gsub| {
+ gsub.features
+ .find(ttf_parser::Tag::from_bytes(b"ssty"))
+ .and_then(|feature| feature.lookup_indices.get(0))
+ .and_then(|index| gsub.lookups.get(index))
+ })
+ .and_then(|ssty| {
+ ssty.subtables.get::<ttf_parser::gsub::SubstitutionSubtable>(0)
+ })
+ .and_then(|ssty| match ssty {
+ ttf_parser::gsub::SubstitutionSubtable::Alternate(alt_glyphs) => {
+ Some(alt_glyphs)
+ }
+ _ => None,
+ });
+
let size = TextElem::size_in(styles);
let ttf = font.ttf();
let space_width = ttf
@@ -66,6 +88,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
ttf: font.ttf(),
table,
constants,
+ ssty_table,
space_width,
fragments: vec![],
local: Styles::new(),
@@ -129,20 +152,31 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
let text = elem.text();
let span = elem.span();
let mut chars = text.chars();
- let fragment = if let Some(glyph) = chars
+ let fragment = if let Some(mut glyph) = chars
.next()
.filter(|_| chars.next().is_none())
.map(|c| self.style.styled_char(c))
.and_then(|c| GlyphFragment::try_new(self, c, span))
{
// A single letter that is available in the math font.
- if self.style.size == MathSize::Display
- && glyph.class == Some(MathClass::Large)
- {
- let height = scaled!(self, display_operator_min_height);
- glyph.stretch_vertical(self, height, Abs::zero()).into()
- } else {
- glyph.into()
+ match self.style.size {
+ MathSize::Display => {
+ if glyph.class == Some(MathClass::Large) {
+ let height = scaled!(self, display_operator_min_height);
+ glyph.stretch_vertical(self, height, Abs::zero()).into()
+ } else {
+ glyph.into()
+ }
+ }
+ MathSize::Script => {
+ glyph.make_scriptsize(self);
+ glyph.into()
+ }
+ MathSize::ScriptScript => {
+ glyph.make_scriptscriptsize(self);
+ glyph.into()
+ }
+ _ => glyph.into(),
}
} else if text.chars().all(|c| c.is_ascii_digit()) {
// Numbers aren't that difficult.
diff --git a/library/src/math/fragment.rs b/library/src/math/fragment.rs
index b70a3f7d..139ce07b 100644
--- a/library/src/math/fragment.rs
+++ b/library/src/math/fragment.rs
@@ -1,4 +1,5 @@
use super::*;
+use ttf_parser::gsub::AlternateSet;
#[derive(Debug, Clone)]
pub enum MathFragment {
@@ -272,6 +273,25 @@ impl GlyphFragment {
frame.meta_iter(self.meta);
frame
}
+
+ pub fn make_scriptsize(&mut self, ctx: &MathContext) {
+ let alt_id =
+ script_alternatives(ctx, self.id).and_then(|alts| alts.alternates.get(0));
+
+ if let Some(alt_id) = alt_id {
+ self.set_id(ctx, alt_id);
+ }
+ }
+
+ pub fn make_scriptscriptsize(&mut self, ctx: &MathContext) {
+ let alts = script_alternatives(ctx, self.id);
+ let alt_id = alts
+ .and_then(|alts| alts.alternates.get(1).or_else(|| alts.alternates.get(0)));
+
+ if let Some(alt_id) = alt_id {
+ self.set_id(ctx, alt_id);
+ }
+ }
}
impl Debug for GlyphFragment {
@@ -347,6 +367,16 @@ fn italics_correction(ctx: &MathContext, id: GlyphId) -> Option<Abs> {
Some(ctx.table.glyph_info?.italic_corrections?.get(id)?.scaled(ctx))
}
+/// Look up the script/scriptscript alternates for a glyph
+fn script_alternatives<'a>(
+ ctx: &MathContext<'a, '_, '_>,
+ id: GlyphId,
+) -> Option<AlternateSet<'a>> {
+ ctx.ssty_table.and_then(|ssty| {
+ ssty.coverage.get(id).and_then(|index| ssty.alternate_sets.get(index))
+ })
+}
+
/// Look up the italics correction for a glyph.
fn is_extended_shape(ctx: &MathContext, id: GlyphId) -> bool {
ctx.table
diff --git a/tests/ref/bugs/math-realize.png b/tests/ref/bugs/math-realize.png
index 4f5b887e..2a17f629 100644
--- a/tests/ref/bugs/math-realize.png
+++ b/tests/ref/bugs/math-realize.png
Binary files differ
diff --git a/tests/ref/compiler/content-field.png b/tests/ref/compiler/content-field.png
index d2f696b4..cef3274a 100644
--- a/tests/ref/compiler/content-field.png
+++ b/tests/ref/compiler/content-field.png
Binary files differ
diff --git a/tests/ref/layout/enum-numbering.png b/tests/ref/layout/enum-numbering.png
index 28755dcb..e1b2103b 100644
--- a/tests/ref/layout/enum-numbering.png
+++ b/tests/ref/layout/enum-numbering.png
Binary files differ
diff --git a/tests/ref/math/accent.png b/tests/ref/math/accent.png
index 11de9e28..5a963b38 100644
--- a/tests/ref/math/accent.png
+++ b/tests/ref/math/accent.png
Binary files differ
diff --git a/tests/ref/math/attach.png b/tests/ref/math/attach.png
index 894f553f..9d01e7bf 100644
--- a/tests/ref/math/attach.png
+++ b/tests/ref/math/attach.png
Binary files differ
diff --git a/tests/ref/math/cancel.png b/tests/ref/math/cancel.png
index 96b29c45..571edcc2 100644
--- a/tests/ref/math/cancel.png
+++ b/tests/ref/math/cancel.png
Binary files differ
diff --git a/tests/ref/math/cases.png b/tests/ref/math/cases.png
index c9eca24c..c824a801 100644
--- a/tests/ref/math/cases.png
+++ b/tests/ref/math/cases.png
Binary files differ
diff --git a/tests/ref/math/content.png b/tests/ref/math/content.png
index f7af513b..ce727e66 100644
--- a/tests/ref/math/content.png
+++ b/tests/ref/math/content.png
Binary files differ
diff --git a/tests/ref/math/delimited.png b/tests/ref/math/delimited.png
index e9f6e2c1..31d15b41 100644
--- a/tests/ref/math/delimited.png
+++ b/tests/ref/math/delimited.png
Binary files differ
diff --git a/tests/ref/math/frac.png b/tests/ref/math/frac.png
index a116c876..80327578 100644
--- a/tests/ref/math/frac.png
+++ b/tests/ref/math/frac.png
Binary files differ
diff --git a/tests/ref/math/matrix.png b/tests/ref/math/matrix.png
index d3d2681c..bf90e712 100644
--- a/tests/ref/math/matrix.png
+++ b/tests/ref/math/matrix.png
Binary files differ
diff --git a/tests/ref/math/multiline.png b/tests/ref/math/multiline.png
index ae847434..84dcb87d 100644
--- a/tests/ref/math/multiline.png
+++ b/tests/ref/math/multiline.png
Binary files differ
diff --git a/tests/ref/math/numbering.png b/tests/ref/math/numbering.png
index 6256310f..3952dea0 100644
--- a/tests/ref/math/numbering.png
+++ b/tests/ref/math/numbering.png
Binary files differ
diff --git a/tests/ref/math/op.png b/tests/ref/math/op.png
index 08d8b93b..15c7329d 100644
--- a/tests/ref/math/op.png
+++ b/tests/ref/math/op.png
Binary files differ
diff --git a/tests/ref/math/opticalsize.png b/tests/ref/math/opticalsize.png
new file mode 100644
index 00000000..9fec5520
--- /dev/null
+++ b/tests/ref/math/opticalsize.png
Binary files differ
diff --git a/tests/ref/math/root.png b/tests/ref/math/root.png
index 8a6a6e13..017582a4 100644
--- a/tests/ref/math/root.png
+++ b/tests/ref/math/root.png
Binary files differ
diff --git a/tests/ref/math/spacing.png b/tests/ref/math/spacing.png
index 2fd30e53..abcfae80 100644
--- a/tests/ref/math/spacing.png
+++ b/tests/ref/math/spacing.png
Binary files differ
diff --git a/tests/ref/math/style.png b/tests/ref/math/style.png
index 39ecc441..cec04ba5 100644
--- a/tests/ref/math/style.png
+++ b/tests/ref/math/style.png
Binary files differ
diff --git a/tests/ref/math/syntax.png b/tests/ref/math/syntax.png
index 3d09723d..028e21d6 100644
--- a/tests/ref/math/syntax.png
+++ b/tests/ref/math/syntax.png
Binary files differ
diff --git a/tests/ref/math/unbalanced.png b/tests/ref/math/unbalanced.png
index 5b4d7736..de0ee1db 100644
--- a/tests/ref/math/unbalanced.png
+++ b/tests/ref/math/unbalanced.png
Binary files differ
diff --git a/tests/ref/math/underover.png b/tests/ref/math/underover.png
index 5c825b18..24c96b21 100644
--- a/tests/ref/math/underover.png
+++ b/tests/ref/math/underover.png
Binary files differ
diff --git a/tests/ref/meta/figure.png b/tests/ref/meta/figure.png
index 524f6cfd..90f59d14 100644
--- a/tests/ref/meta/figure.png
+++ b/tests/ref/meta/figure.png
Binary files differ
diff --git a/tests/typ/math/op.typ b/tests/typ/math/op.typ
index 08395de0..2a0f84fc 100644
--- a/tests/typ/math/op.typ
+++ b/tests/typ/math/op.typ
@@ -11,6 +11,7 @@ $ &sin x + log_2 x \
---
// Test scripts vs limits.
+#set page(width: auto)
#set text(font: "New Computer Modern")
Discuss $lim_(n->oo) 1/n$ now.
$ lim_(n->infinity) 1/n = 0 $
diff --git a/tests/typ/math/opticalsize.typ b/tests/typ/math/opticalsize.typ
new file mode 100644
index 00000000..c96e4a32
--- /dev/null
+++ b/tests/typ/math/opticalsize.typ
@@ -0,0 +1,30 @@
+// test optical sized variants in sub/superscripts
+
+---
+
+// Test transition from script to scriptscript.
+#[
+#set text(size:20pt)
+$ e^(e^(e^(e))) $
+]
+A large number: $e^(e^(e^(e)))$.
+
+---
+// Test prime/double prime via scriptsize
+#let prime = [ \u{2032} ]
+#let dprime = [ \u{2033} ]
+#let tprime = [ \u{2034} ]
+$ y^dprime-2y^prime + y = 0 $
+$y^dprime-2y^prime + y = 0$
+$ y^tprime_3 + g^(prime 2) $
+
+---
+// Test prime superscript on large symbol
+$ scripts(sum_(k in NN))^prime 1/k^2 $
+$sum_(k in NN)^prime 1/k^2$
+
+---
+// Test script-script in a fraction.
+$ 1/(x^A) $
+#[#set text(size:18pt); $1/(x^A)$] vs. #[#set text(size:14pt); $x^A$]
+