summaryrefslogtreecommitdiff
path: root/library/src/math/fragment.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-07-02 19:59:52 +0200
committerLaurenz <laurmaedje@gmail.com>2023-07-02 20:07:43 +0200
commitebfdb1dafa430786db10dad2ef7d5467c1bdbed1 (patch)
tree2bbc24ddb4124c4bb14dec0e536129d4de37b056 /library/src/math/fragment.rs
parent3ab19185093d7709f824b95b979060ce125389d8 (diff)
Move everything into `crates/` directory
Diffstat (limited to 'library/src/math/fragment.rs')
-rw-r--r--library/src/math/fragment.rs414
1 files changed, 0 insertions, 414 deletions
diff --git a/library/src/math/fragment.rs b/library/src/math/fragment.rs
deleted file mode 100644
index 139ce07b..00000000
--- a/library/src/math/fragment.rs
+++ /dev/null
@@ -1,414 +0,0 @@
-use super::*;
-use ttf_parser::gsub::AlternateSet;
-
-#[derive(Debug, Clone)]
-pub enum MathFragment {
- Glyph(GlyphFragment),
- Variant(VariantFragment),
- Frame(FrameFragment),
- Spacing(Abs),
- Space(Abs),
- Linebreak,
- Align,
-}
-
-impl MathFragment {
- pub fn size(&self) -> Size {
- Size::new(self.width(), self.height())
- }
-
- pub fn width(&self) -> Abs {
- match self {
- Self::Glyph(glyph) => glyph.width,
- Self::Variant(variant) => variant.frame.width(),
- Self::Frame(fragment) => fragment.frame.width(),
- Self::Spacing(amount) => *amount,
- Self::Space(amount) => *amount,
- _ => Abs::zero(),
- }
- }
-
- pub fn height(&self) -> Abs {
- match self {
- Self::Glyph(glyph) => glyph.height(),
- Self::Variant(variant) => variant.frame.height(),
- Self::Frame(fragment) => fragment.frame.height(),
- _ => Abs::zero(),
- }
- }
-
- pub fn ascent(&self) -> Abs {
- match self {
- Self::Glyph(glyph) => glyph.ascent,
- Self::Variant(variant) => variant.frame.ascent(),
- Self::Frame(fragment) => fragment.frame.baseline(),
- _ => Abs::zero(),
- }
- }
-
- pub fn descent(&self) -> Abs {
- match self {
- Self::Glyph(glyph) => glyph.descent,
- Self::Variant(variant) => variant.frame.descent(),
- Self::Frame(fragment) => fragment.frame.descent(),
- _ => Abs::zero(),
- }
- }
-
- pub fn class(&self) -> Option<MathClass> {
- match self {
- Self::Glyph(glyph) => glyph.class,
- Self::Variant(variant) => variant.class,
- Self::Frame(fragment) => Some(fragment.class),
- _ => None,
- }
- }
-
- pub fn style(&self) -> Option<MathStyle> {
- match self {
- Self::Glyph(glyph) => Some(glyph.style),
- Self::Variant(variant) => Some(variant.style),
- Self::Frame(fragment) => Some(fragment.style),
- _ => None,
- }
- }
-
- pub fn font_size(&self) -> Option<Abs> {
- match self {
- Self::Glyph(glyph) => Some(glyph.font_size),
- Self::Variant(variant) => Some(variant.font_size),
- Self::Frame(fragment) => Some(fragment.font_size),
- _ => None,
- }
- }
-
- pub fn set_class(&mut self, class: MathClass) {
- match self {
- Self::Glyph(glyph) => glyph.class = Some(class),
- Self::Variant(variant) => variant.class = Some(class),
- Self::Frame(fragment) => fragment.class = class,
- _ => {}
- }
- }
-
- pub fn set_limits(&mut self, limits: Limits) {
- match self {
- Self::Glyph(glyph) => glyph.limits = limits,
- Self::Variant(variant) => variant.limits = limits,
- Self::Frame(fragment) => fragment.limits = limits,
- _ => {}
- }
- }
-
- pub fn is_spaced(&self) -> bool {
- match self {
- MathFragment::Frame(frame) => frame.spaced,
- _ => self.class() == Some(MathClass::Fence),
- }
- }
-
- pub fn italics_correction(&self) -> Abs {
- match self {
- Self::Glyph(glyph) => glyph.italics_correction,
- Self::Variant(variant) => variant.italics_correction,
- _ => Abs::zero(),
- }
- }
-
- pub fn into_frame(self) -> Frame {
- match self {
- Self::Glyph(glyph) => glyph.into_frame(),
- Self::Variant(variant) => variant.frame,
- Self::Frame(fragment) => fragment.frame,
- _ => Frame::new(self.size()),
- }
- }
-
- pub fn limits(&self) -> Limits {
- match self {
- MathFragment::Glyph(glyph) => glyph.limits,
- MathFragment::Variant(variant) => variant.limits,
- MathFragment::Frame(fragment) => fragment.limits,
- _ => Limits::Never,
- }
- }
-}
-
-impl From<GlyphFragment> for MathFragment {
- fn from(glyph: GlyphFragment) -> Self {
- Self::Glyph(glyph)
- }
-}
-
-impl From<VariantFragment> for MathFragment {
- fn from(variant: VariantFragment) -> Self {
- Self::Variant(variant)
- }
-}
-
-impl From<FrameFragment> for MathFragment {
- fn from(fragment: FrameFragment) -> Self {
- Self::Frame(fragment)
- }
-}
-
-#[derive(Clone)]
-pub struct GlyphFragment {
- pub id: GlyphId,
- pub c: char,
- pub font: Font,
- pub lang: Lang,
- pub fill: Paint,
- pub width: Abs,
- pub ascent: Abs,
- pub descent: Abs,
- pub italics_correction: Abs,
- pub style: MathStyle,
- pub font_size: Abs,
- pub class: Option<MathClass>,
- pub span: Span,
- pub meta: Vec<Meta>,
- pub limits: Limits,
-}
-
-impl GlyphFragment {
- pub fn new(ctx: &MathContext, c: char, span: Span) -> Self {
- let id = ctx.ttf.glyph_index(c).unwrap_or_default();
- Self::with_id(ctx, c, id, span)
- }
-
- pub fn try_new(ctx: &MathContext, c: char, span: Span) -> Option<Self> {
- let c = ctx.style.styled_char(c);
- let id = ctx.ttf.glyph_index(c)?;
- Some(Self::with_id(ctx, c, id, span))
- }
-
- pub fn with_id(ctx: &MathContext, c: char, id: GlyphId, span: Span) -> Self {
- let class = match c {
- ':' => Some(MathClass::Relation),
- _ => unicode_math_class::class(c),
- };
- let mut fragment = Self {
- id,
- c,
- font: ctx.font.clone(),
- lang: TextElem::lang_in(ctx.styles()),
- fill: TextElem::fill_in(ctx.styles()),
- style: ctx.style,
- font_size: ctx.size,
- width: Abs::zero(),
- ascent: Abs::zero(),
- descent: Abs::zero(),
- limits: Limits::for_char(c),
- italics_correction: Abs::zero(),
- class,
- span,
- meta: MetaElem::data_in(ctx.styles()),
- };
- fragment.set_id(ctx, id);
- fragment
- }
-
- /// Sets element id and boxes in appropriate way without changing other
- /// styles. This is used to replace the glyph with a stretch variant.
- pub fn set_id(&mut self, ctx: &MathContext, id: GlyphId) {
- let advance = ctx.ttf.glyph_hor_advance(id).unwrap_or_default();
- let italics = italics_correction(ctx, id).unwrap_or_default();
- let bbox = ctx.ttf.glyph_bounding_box(id).unwrap_or(Rect {
- x_min: 0,
- y_min: 0,
- x_max: 0,
- y_max: 0,
- });
-
- let mut width = advance.scaled(ctx);
- if !is_extended_shape(ctx, id) {
- width += italics;
- }
-
- self.id = id;
- self.width = width;
- self.ascent = bbox.y_max.scaled(ctx);
- self.descent = -bbox.y_min.scaled(ctx);
- self.italics_correction = italics;
- }
-
- pub fn height(&self) -> Abs {
- self.ascent + self.descent
- }
-
- pub fn into_variant(self) -> VariantFragment {
- VariantFragment {
- c: self.c,
- id: Some(self.id),
- style: self.style,
- font_size: self.font_size,
- italics_correction: self.italics_correction,
- class: self.class,
- span: self.span,
- limits: self.limits,
- frame: self.into_frame(),
- }
- }
-
- pub fn into_frame(self) -> Frame {
- let item = TextItem {
- font: self.font.clone(),
- size: self.font_size,
- fill: self.fill,
- lang: self.lang,
- text: self.c.into(),
- glyphs: vec![Glyph {
- id: self.id.0,
- x_advance: Em::from_length(self.width, self.font_size),
- x_offset: Em::zero(),
- range: 0..self.c.len_utf8() as u16,
- span: (self.span, 0),
- }],
- };
- let size = Size::new(self.width, self.ascent + self.descent);
- let mut frame = Frame::new(size);
- frame.set_baseline(self.ascent);
- frame.push(Point::with_y(self.ascent), FrameItem::Text(item));
- 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 {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- write!(f, "GlyphFragment({:?})", self.c)
- }
-}
-
-#[derive(Clone)]
-pub struct VariantFragment {
- pub c: char,
- pub id: Option<GlyphId>,
- pub italics_correction: Abs,
- pub frame: Frame,
- pub style: MathStyle,
- pub font_size: Abs,
- pub class: Option<MathClass>,
- pub span: Span,
- pub limits: Limits,
-}
-
-impl Debug for VariantFragment {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- write!(f, "VariantFragment({:?})", self.c)
- }
-}
-
-#[derive(Debug, Clone)]
-pub struct FrameFragment {
- pub frame: Frame,
- pub style: MathStyle,
- pub font_size: Abs,
- pub class: MathClass,
- pub limits: Limits,
- pub spaced: bool,
- pub base_ascent: Abs,
-}
-
-impl FrameFragment {
- pub fn new(ctx: &MathContext, mut frame: Frame) -> Self {
- let base_ascent = frame.ascent();
- frame.meta(ctx.styles(), false);
- Self {
- frame,
- font_size: ctx.size,
- style: ctx.style,
- class: MathClass::Normal,
- limits: Limits::Never,
- spaced: false,
- base_ascent,
- }
- }
-
- pub fn with_class(self, class: MathClass) -> Self {
- Self { class, ..self }
- }
-
- pub fn with_limits(self, limits: Limits) -> Self {
- Self { limits, ..self }
- }
-
- pub fn with_spaced(self, spaced: bool) -> Self {
- Self { spaced, ..self }
- }
-
- pub fn with_base_ascent(self, base_ascent: Abs) -> Self {
- Self { base_ascent, ..self }
- }
-}
-
-/// Look up the italics correction for a glyph.
-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
- .glyph_info
- .and_then(|info| info.extended_shapes)
- .and_then(|info| info.get(id))
- .is_some()
-}
-
-/// Look up a kerning value at a specific corner and height.
-///
-/// This can be integrated once we've found a font that actually provides this
-/// data.
-#[allow(unused)]
-fn kern_at_height(
- ctx: &MathContext,
- id: GlyphId,
- corner: Corner,
- height: Abs,
-) -> Option<Abs> {
- let kerns = ctx.table.glyph_info?.kern_infos?.get(id)?;
- let kern = match corner {
- Corner::TopLeft => kerns.top_left,
- Corner::TopRight => kerns.top_right,
- Corner::BottomRight => kerns.bottom_right,
- Corner::BottomLeft => kerns.bottom_left,
- }?;
-
- let mut i = 0;
- while i < kern.count() && height > kern.height(i)?.scaled(ctx) {
- i += 1;
- }
-
- Some(kern.kern(i)?.scaled(ctx))
-}