diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-07-02 19:59:52 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-07-02 20:07:43 +0200 |
| commit | ebfdb1dafa430786db10dad2ef7d5467c1bdbed1 (patch) | |
| tree | 2bbc24ddb4124c4bb14dec0e536129d4de37b056 /library/src/math/fragment.rs | |
| parent | 3ab19185093d7709f824b95b979060ce125389d8 (diff) | |
Move everything into `crates/` directory
Diffstat (limited to 'library/src/math/fragment.rs')
| -rw-r--r-- | library/src/math/fragment.rs | 414 |
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)) -} |
