diff options
Diffstat (limited to 'library/src')
| -rw-r--r-- | library/src/math/tex.rs | 151 |
1 files changed, 0 insertions, 151 deletions
diff --git a/library/src/math/tex.rs b/library/src/math/tex.rs deleted file mode 100644 index 60f00249..00000000 --- a/library/src/math/tex.rs +++ /dev/null @@ -1,151 +0,0 @@ -use rex::error::{Error, LayoutError}; -use rex::font::FontContext; -use rex::layout::{LayoutSettings, Style}; -use rex::parser::color::RGBA; -use rex::render::{Backend, Cursor, Renderer}; -use typst::font::Font; - -use crate::prelude::*; -use crate::text::{families, variant, TextNode}; - -/// Layout a TeX formula into a frame. -pub fn layout_tex( - vt: &Vt, - tex: &str, - display: bool, - styles: StyleChain, -) -> Result<Fragment, &'static str> { - // Load the font. - let variant = variant(styles); - let world = vt.world(); - let mut font = None; - for family in families(styles) { - font = world.book().select(family, variant).and_then(|id| world.font(id)); - if font.as_ref().map_or(false, |font| font.math().is_some()) { - break; - } - } - - // Prepare the font context. - let Some(font) = font else { return Err("failed to find suitable math font") }; - let Some(ctx) = font - .math() - .map(|math| FontContext::new(font.ttf(), math)) - else { - return Err("failed to create math font context"); - }; - - // Layout the formula. - let em = styles.get(TextNode::SIZE); - let style = if display { Style::Display } else { Style::Text }; - let settings = LayoutSettings::new(&ctx, em.to_pt(), style); - let renderer = Renderer::new(); - let Ok(layout) = renderer - .layout(&tex, settings) - .map_err(|err| match err { - Error::Parse(err) => err.to_string(), - Error::Layout(LayoutError::Font(err)) => err.to_string(), - }) - else { - return Err("failed to layout math"); - }; - - // Determine the metrics. - let (x0, y0, x1, y1) = renderer.size(&layout); - let width = Abs::pt(x1 - x0); - let mut top = Abs::pt(y1); - let mut bottom = Abs::pt(-y0); - if style != Style::Display { - let metrics = font.metrics(); - top = styles.get(TextNode::TOP_EDGE).resolve(styles, metrics); - bottom = -styles.get(TextNode::BOTTOM_EDGE).resolve(styles, metrics); - }; - - // Prepare a frame rendering backend. - let size = Size::new(width, top + bottom); - let mut backend = FrameBackend { - frame: { - let mut frame = Frame::new(size); - frame.set_baseline(top); - frame - }, - baseline: top, - font: font.clone(), - paint: styles.get(TextNode::FILL), - lang: styles.get(TextNode::LANG), - colors: vec![], - }; - - // Render into the frame. - renderer.render(&layout, &mut backend); - - Ok(Fragment::frame(backend.frame)) -} - -/// A ReX rendering backend that renders into a frame. -struct FrameBackend { - frame: Frame, - baseline: Abs, - font: Font, - paint: Paint, - lang: Lang, - colors: Vec<RGBA>, -} - -impl FrameBackend { - /// The currently active paint. - fn paint(&self) -> Paint { - self.colors - .last() - .map(|&RGBA(r, g, b, a)| RgbaColor::new(r, g, b, a).into()) - .unwrap_or(self.paint) - } - - /// Convert a cursor to a point. - fn transform(&self, cursor: Cursor) -> Point { - Point::new(Abs::pt(cursor.x), self.baseline + Abs::pt(cursor.y)) - } -} - -impl Backend for FrameBackend { - fn symbol(&mut self, pos: Cursor, gid: u16, scale: f64) { - self.frame.push( - self.transform(pos), - Element::Text(Text { - font: self.font.clone(), - size: Abs::pt(scale), - fill: self.paint(), - lang: self.lang, - glyphs: vec![Glyph { - id: gid, - x_advance: Em::new(0.0), - x_offset: Em::new(0.0), - c: ' ', - }], - }), - ); - } - - fn rule(&mut self, pos: Cursor, width: f64, height: f64) { - if height == 0.0 { - return; - } - - self.frame.push( - self.transform(pos) + Point::with_y(Abs::pt(height) / 2.0), - Element::Shape(Shape { - geometry: Geometry::Line(Point::new(Abs::pt(width), Abs::zero())), - fill: None, - stroke: Some(Stroke { paint: self.paint(), thickness: Abs::pt(height) }), - }), - ); - } - - fn begin_color(&mut self, color: RGBA) { - self.colors.push(color); - } - - fn end_color(&mut self) { - self.colors.pop(); - } -} |
