use mlua::{Lua, MultiValue, Table, Value};
use retex_engine::Engine;
use retex_font::texfont::MathValue;
use crate::luaotfload::loaded_font;
use crate::with_engine;
fn font_arg(e: &Engine, v: &Value) -> Option<u32> {
let id = match v {
Value::Integer(n) => *n,
Value::Number(n) => *n as i64,
Value::String(s) => {
let cs = e.hash.lookup(&s.as_bytes())?;
let m = e.eqtb.meaning(cs);
if m.cmd != retex_engine::cmd::Cmd::SetFont {
return None;
}
i64::from(m.chr)
}
_ => return None,
};
(id >= 0 && e.font_exists(id as i32)).then_some(id as u32)
}
fn str_arg(v: Option<&Value>) -> String {
match v {
Some(Value::String(s)) => s.to_string_lossy(),
Some(Value::Integer(n)) => n.to_string(),
_ => String::new(),
}
}
pub fn install(lua: &Lua, native: &Table) -> mlua::Result<()> {
native.set(
"aux_provides_script",
lua.create_function(|lua, args: MultiValue| {
let a: Vec<Value> = args.into_iter().collect();
let script = str_arg(a.get(1));
with_engine(lua, |e| {
let f = a.first().and_then(|v| font_arg(e, v));
f.and_then(|f| loaded_font(e, f))
.is_some_and(|lf| lf.file.provides_script(&script))
})
})?,
)?;
native.set(
"aux_provides_language",
lua.create_function(|lua, args: MultiValue| {
let a: Vec<Value> = args.into_iter().collect();
let (script, lang) = (str_arg(a.get(1)), str_arg(a.get(2)));
with_engine(lua, |e| {
let f = a.first().and_then(|v| font_arg(e, v));
f.and_then(|f| loaded_font(e, f))
.is_some_and(|lf| lf.file.provides_language(&script, &lang))
})
})?,
)?;
native.set(
"aux_provides_feature",
lua.create_function(|lua, args: MultiValue| {
let a: Vec<Value> = args.into_iter().collect();
let (script, lang, feat) = (str_arg(a.get(1)), str_arg(a.get(2)), str_arg(a.get(3)));
let r = with_engine(lua, |e| {
let f = a.first().and_then(|v| font_arg(e, v));
match f.and_then(|f| loaded_font(e, f)) {
None => Some(false),
Some(lf) => lf
.file
.provides_feature(&script, &lang, &feat)
.then_some(true),
}
})?;
Ok(match r {
Some(b) => MultiValue::from_vec(vec![Value::Boolean(b)]),
None => MultiValue::new(),
})
})?,
)?;
native.set(
"aux_get_math_dimension",
lua.create_function(|lua, (font, name): (Value, Value)| {
let name = str_arg(Some(&name));
let v = with_engine(lua, |e| {
let f = font_arg(e, &font)?;
loaded_font(e, f)?.tex.math_constant(&name)
})?;
Ok(match v {
Some(MathValue::Percent(p)) => Value::Integer(i64::from(p)),
Some(MathValue::Scaled(x)) => Value::Number(x),
None => Value::Integer(0),
})
})?,
)?;
native.set(
"aux_font_has_glyph",
lua.create_function(|lua, (font, code): (Value, i64)| {
with_engine(lua, |e| {
font_arg(e, &font).is_some_and(|f| {
u32::try_from(code).is_ok_and(|c| e.font(f).chars.contains_key(&c))
})
})
})?,
)?;
native.set(
"aux_slot_of_name",
lua.create_function(|lua, (font, name): (Value, Value)| {
let name = str_arg(Some(&name));
let r = with_engine(lua, |e| {
let lf = loaded_font(e, font_arg(e, &font)?)?;
let g = lf.file.glyph_by_name(&name)?;
lf.tex.code_of_glyph(g)
})?;
Ok(r.map_or(Value::Boolean(false), |c| Value::Integer(i64::from(c))))
})?,
)?;
native.set(
"aux_gid_of_name",
lua.create_function(|lua, (font, name): (Value, Value)| {
let name = str_arg(Some(&name));
let r = with_engine(lua, |e| {
let lf = loaded_font(e, font_arg(e, &font)?)?;
lf.file.glyph_by_name(&name)
})?;
Ok(match r {
Some(g) => MultiValue::from_vec(vec![Value::Integer(i64::from(g))]),
None => MultiValue::new(),
})
})?,
)?;
Ok(())
}