Created
April 4, 2025 13:00
-
-
Save mkalte666/c3cf48972876d695237731507bfcd33e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// A helper struct to construct math text. Just wraps a &str, intended for ui.add() and similar situations. | |
pub struct MathText<'a>(pub &'a str); | |
impl<'a> Widget for MathText<'a> { | |
fn ui(self, ui: &mut Ui) -> Response { | |
ui.label(math_text(ui, self.0)) | |
} | |
} | |
/// Layout a math text using the style from the current ui. | |
pub fn math_text(ui: &Ui, text: &str) -> LayoutJob { | |
math_text_ctx(ui.ctx().clone(), ui.style().clone(), text) | |
} | |
/// Layout a Math text using context and style | |
pub fn math_text_ctx(ctx: egui::Context, style: Arc<Style>, text: &str) -> LayoutJob { | |
let color = style.visuals.text_color(); | |
let normal = TextStyle::Body.resolve(&style); | |
let subscript = TextStyle::Small.resolve(&style); | |
ctx.memory_mut(|mem| { | |
mem.caches | |
.cache::<MathTextCache>() | |
.get((text, &normal, &subscript, color)) | |
}) | |
} | |
/// Helper cache that stores layouted MathText | |
type MathTextCache = FrameCache<LayoutJob, MathTextGenerator>; | |
/// The generator struct needed to tokenize MathText | |
#[derive(Default)] | |
struct MathTextGenerator {} | |
impl MathTextGenerator { | |
/// Layout a MathText. | |
fn layout(&self, text: &str, normal: &FontId, small: &FontId, color: Color32) -> LayoutJob { | |
let sections = parse_math(text); | |
let mut job = LayoutJob::default(); | |
let normal = TextFormat::simple(normal.clone(), color); | |
let mut subscript = TextFormat::simple(small.clone(), color); | |
subscript.valign = Align::BOTTOM; | |
let mut superscript = TextFormat::simple(small.clone(), color); | |
superscript.valign = Align::TOP; | |
for section in sections { | |
match section { | |
MathSection::Normal(s) => { | |
job.append(s, 0.0, normal.clone()); | |
} | |
MathSection::Subscript(s) => { | |
job.append(s, 0.0, subscript.clone()); | |
} | |
MathSection::Superscript(s) => { | |
job.append(s, 0.0, superscript.clone()); | |
} | |
} | |
} | |
job | |
} | |
} | |
/// Helper to cache layout jobs for math drawing | |
impl ComputerMut<(&str, &FontId, &FontId, Color32), LayoutJob> for MathTextGenerator { | |
fn compute( | |
&mut self, | |
(text, normal, small, color): (&str, &FontId, &FontId, Color32), | |
) -> LayoutJob { | |
self.layout(text, normal, small, color) | |
} | |
} | |
/// Tokenize an input string for math drawing | |
fn parse_math(mut text: &str) -> Vec<MathSection> { | |
let mut sections = vec![]; | |
while !text.is_empty() { | |
if let Some(start) = text.find("_") { | |
let before = &text[0..start]; | |
if !before.is_empty() { | |
sections.push(MathSection::Normal(before)); | |
} | |
let sub_begin = start + 1; | |
text = &text[sub_begin..]; | |
let end = text | |
.find(|f: char| f == '_' || f == '^' || f.is_whitespace()) | |
.unwrap_or(text.len()); | |
let section = &text[..end]; | |
if !section.is_empty() { | |
sections.push(MathSection::Subscript(section)); | |
} | |
text = &text[end..]; | |
} else if let Some(start) = text.find("^") { | |
let before = &text[0..start]; | |
if !before.is_empty() { | |
sections.push(MathSection::Normal(before)); | |
} | |
let sub_begin = start + 1; | |
text = &text[sub_begin..]; | |
let end = text | |
.find(|f: char| f == '_' || f == '^' || f.is_whitespace()) | |
.unwrap_or(text.len()); | |
let section = &text[..end]; | |
if !section.is_empty() { | |
sections.push(MathSection::Superscript(section)); | |
} | |
text = &text[end..]; | |
} else { | |
sections.push(MathSection::Normal(text)); | |
text = &text[text.len()..]; | |
} | |
} | |
sections | |
} | |
/// A helper struct to tokenize the input string | |
enum MathSection<'a> { | |
Normal(&'a str), | |
Subscript(&'a str), | |
Superscript(&'a str), | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment