From a7fd7fae5f87c789c2edd7107655ccbad4fee148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Gazeel?= <171210953+mgazeel@users.noreply.github.com> Date: Mon, 5 May 2025 13:53:09 +0200 Subject: [PATCH] Fix stroking of glyphs in math mode (typst#6170) --- crates/typst-layout/src/math/fragment.rs | 42 +++++++++++++++++++++-- crates/typst-library/src/text/item.rs | 2 +- crates/typst-library/src/text/mod.rs | 2 +- tests/ref/issue-6170-equation-stroke.png | Bin 0 -> 1381 bytes tests/suite/math/equation.typ | 7 ++++ 5 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 tests/ref/issue-6170-equation-stroke.png diff --git a/crates/typst-layout/src/math/fragment.rs b/crates/typst-layout/src/math/fragment.rs index 1b508a349..6dfb8d1af 100644 --- a/crates/typst-layout/src/math/fragment.rs +++ b/crates/typst-layout/src/math/fragment.rs @@ -11,7 +11,7 @@ use typst_library::layout::{ }; use typst_library::math::{EquationElem, MathSize}; use typst_library::text::{Font, Glyph, Lang, Region, TextElem, TextItem}; -use typst_library::visualize::Paint; +use typst_library::visualize::{FixedStroke, Paint}; use typst_syntax::Span; use typst_utils::default_math_class; use unicode_math_class::MathClass; @@ -227,14 +227,51 @@ impl From for MathFragment { } } +/// A single glyph in math. #[derive(Clone)] pub struct GlyphFragment { + /// The id of the glyph in the font. pub id: GlyphId, + + /// The base character. pub c: char, + + /// A single OpenType font for this glyph. + /// + /// A show rule must be used to affect this. + /// + /// ```example + /// #show math.equation: set text(font: "Fira Math") + /// $ f i r a m a t h $ + /// ``` pub font: Font, + + /// An [ISO 639-1/2/3 language code.](https://en.wikipedia.org/wiki/ISO_639) + /// + /// See [TextElem] pub lang: Lang, + + /// An [ISO 3166-1 alpha-2 region code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) + /// + /// See [TextElem] pub region: Option, + + /// The glyph fill paint. + /// + /// ```example + /// #show math.equation: set text(fill: red) + /// $ r e d $ + /// ``` pub fill: Paint, + + /// How to stroke the text. + /// + /// ```example + /// #show math.equation: set text(stroke: red + 0.5pt) + /// $ r e d a g a i n $ + /// ``` + pub stroke: Option, + pub shift: Abs, pub width: Abs, pub ascent: Abs, @@ -286,6 +323,7 @@ impl GlyphFragment { lang: TextElem::lang_in(styles), region: TextElem::region_in(styles), fill: TextElem::fill_in(styles).as_decoration(), + stroke: TextElem::stroke_in(styles).map(|s| s.unwrap_or_default()), shift: TextElem::baseline_in(styles), font_size: TextElem::size_in(styles), math_size: EquationElem::size_in(styles), @@ -368,10 +406,10 @@ impl GlyphFragment { font: self.font.clone(), size: self.font_size, fill: self.fill, + stroke: self.stroke, lang: self.lang, region: self.region, text: self.c.into(), - stroke: None, glyphs: vec![Glyph { id: self.id.0, x_advance: Em::from_length(self.width, self.font_size), diff --git a/crates/typst-library/src/text/item.rs b/crates/typst-library/src/text/item.rs index ed559aec8..5a5346ce0 100644 --- a/crates/typst-library/src/text/item.rs +++ b/crates/typst-library/src/text/item.rs @@ -39,7 +39,7 @@ impl TextItem { impl Debug for TextItem { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.write_str("Text(")?; + f.write_str("TextItem(")?; self.text.fmt(f)?; f.write_str(")") } diff --git a/crates/typst-library/src/text/mod.rs b/crates/typst-library/src/text/mod.rs index 462d16060..dc4be7b7d 100644 --- a/crates/typst-library/src/text/mod.rs +++ b/crates/typst-library/src/text/mod.rs @@ -763,7 +763,7 @@ impl TextElem { impl Debug for TextElem { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "Text({})", self.text) + write!(f, "TextElem({})", self.text) } } diff --git a/tests/ref/issue-6170-equation-stroke.png b/tests/ref/issue-6170-equation-stroke.png new file mode 100644 index 0000000000000000000000000000000000000000..a375931b50514adcfc0800fc1d4ac51b08e1bf06 GIT binary patch literal 1381 zcmb7^ZA?>F7{`muxiJ}#Wunqiw>dj?SQRF?%B_l(p_A%-Y0R9}RmLWkRvFsDrPqnC zj2AZ}5J;)cOcsfB11&P}URcGVQtE=0nL;n6wFPV6q4e$ctYrJ(2fr+N&hvaZ=j6%% z|I7c}*6hsasQFPO5-B?C(+!`8r!ah0y!L9i$0hTQl1MW@%G$7QhcLq06?tjl?&`Zv zaLiWG+t+wxGq;(imH$`YmN!&yk~OSMe$VDR+IFz$>KS^Th9y_+1nhUUrfZ<-Jg-0l zcJ|8KpMfO@w0kCzw_AA4ek|(ADmKA6b*R26BwH_6A(z#GQkq#_O81_u2?!EJe*Ka7;dy=-RP1I+4-}ej)E()1+m_C{ljP~g$07A_Qv?3vQ zut0;%KcEdRC7a^x0R!c(8SBY)o$bjG=4ZK*kjXD$r3|K0o6{Bjo>j$}fuXKKc)UZr ztg6^=xOF4Vn1EQdz9&=u{iYR$Yapdp?qho!sG(TgtHk@8Bt;*fE){m(Y+n4J(Ot=z z$cNojI8t_tSQ&iUjk~Ve!JMG04a^wO_p*bYLDyxO@B2*txjl|eaxQ4OrT<|d7G1Kl|O_pilkQ#nHX0>MlG^>HWdror{H;H-8epczB`uM*%^nuL9l`at;i-B!`50@;naLu!>$@|u8MSR9V|`e>uu+|7p^11#bwOtQ z+>cvO!JUkJ;auGDHK#u^so-7*Y!A5RR|yLtn+7UhC{k0rYvq9?bo?E(t|_!RY&_F3 zq2a+^RtXvR9OWpZiNc^uf^|2FwYiP~X^=a#68kYg5PE}1Mgt_&#zo6&v_*@>z{W5s zu#qd?+8FPLkRwMI=41Ll&ToSr-xwpfW7!%5nd11wu1dhYe)vA8BoUb`K)RD;L@esj zV702hM^HUk>Q_pY!w5nh#GY4tvpknie^9S;orXv9&=@vRlOb3AF!FfPdgIX0@{USo zUps$|avS~UUj^>x8%d|hw|FJg%OsLw*RZk9mcl05*8XpvU%=lDx}><9-Pw1OmbFa} z;=*83Qj3hOi2DuEUA+|sUx?|TDvSj<$MRRGjhcK>j&3xLeLNNh7=0A*D)Z*i8 z@$YP74qr4+JYpB0bOQkm_r&47nS_z*d|V|e(AjfzrQphWo*Q|@f_!Fg8HHE^nM?P8<|FwxE*ii~qiPC{d($4w%uU{9qmb&qhp76<}0y z`YF74l(IGcBAf0jTjQ$BbRcu5*YYcFGYm<%<+`uOPORR0IFQqhucLpJn0ze?#7v8D ziGx~Fy^mzXZ1HF-QhTP4AF)poDfKi;l~nAxQt$`k9*CS4WNh4`6?V{y;vqM|sAxmS zx9m2RsewhdkDG27*!$GrLuQ2YBa_f?2WM$uSjM%O4Bxfh-+bqaZ;Tz-8ltR|tHA!L y*;9wbon7Z_X{i%~PB8mr>GXn|FAcLY@5Db-_9~SC literal 0 HcmV?d00001 diff --git a/tests/suite/math/equation.typ b/tests/suite/math/equation.typ index 148a49d02..189f6e6db 100644 --- a/tests/suite/math/equation.typ +++ b/tests/suite/math/equation.typ @@ -297,3 +297,10 @@ Looks at the @quadratic formula. #set page(width: 150pt) #set text(lang: "he") תהא סדרה $a_n$: $[a_n: 1, 1/2, 1/3, dots]$ + +--- issue-6170-equation-stroke --- +// In this bug stroke settings did not apply to math content. +// We expect all of these to have a green stroke. +#set text(stroke: green + 0.5pt) + +A $B^2$ $ grave(C)' $