use alloc::vec;
use alloc::vec::Vec;
use rt::fx::{cvtt, cvttd, sqrt};
use crate::outline::{Outline, OLT_CUBIC, OLT_ON};
use crate::ttf::{Tb, ERR_HDR, ERR_UNSUPPORTED};
use crate::var;
const FD_MAX: u32 = 256;
const CS_STACK: usize = 48;
const CS2_STACK: usize = 513; const CS2_DEFSTACK: i64 = 193; const CS2_REGIONS: usize = 512; const DICT2_STACK: usize = 513; const CS_DEPTH: u32 = 10;
const CS_BUDGET: i32 = 200_000;
const OPS_MAX: usize = 48; const F_INV65536: f32 = 0.000_015_258_789_062_5;
const F_INV8M: f32 = 0.000_000_119_209_29; const F_EPS: f32 = 0.000_001;
#[derive(Clone, Copy, Default)]
struct Index {
count: u32,
offsize: u32,
offs: u32,
data: u32,
}
pub struct Cff {
v2: bool,
cid: bool, cs: Index,
gs: Index,
ls: Index,
fdsel: u32, nfd: u32,
mat: [f32; 6],
hasmat: bool,
fdls: Vec<Index>,
fdvs: Vec<u16>,
vstore: u32,
maxstack: u32,
}
fn c8(t: Tb, off: u32) -> i32 {
t.u8(off)
}
fn c16(t: Tb, off: u32) -> i32 {
t.u16(off)
}
fn c_off(t: Tb, off: u32, size: u32) -> i64 {
if off as u64 + size as u64 > t.0.len() as u64 {
return -1;
}
let mut v = 0u32;
for i in 0..size {
v = (v << 8) | t.0[(off + i) as usize] as u32;
}
v as i64
}
fn ix_parse(t: Tb, pos: u32, ix: &mut Index) -> i64 {
let count = c16(t, pos);
if count < 0 {
ix.count = 0;
return -1;
}
ix.count = count as u32;
if count == 0 {
ix.offsize = 1;
ix.offs = pos.wrapping_add(2);
ix.data = ix.offs;
return ix.offs as i64;
}
let os = c8(t, pos.wrapping_add(2));
if !(1..=4).contains(&os) {
ix.count = 0;
return -1;
}
let os = os as u32;
ix.offsize = os;
ix.offs = pos.wrapping_add(3);
ix.data = ix.offs.wrapping_add((count as u32 + 1).wrapping_mul(os));
let last = c_off(t, (count as u32).wrapping_mul(os).wrapping_add(ix.offs), os);
if last <= 0 {
ix.count = 0;
return -1;
}
let end = ix.data as u64 + last as u64 - 1;
if end > t.0.len() as u64 {
ix.count = 0;
return -1;
}
end as u32 as i64
}
fn ix_get(t: Tb, ix: &Index, i: u32) -> Option<(u32, u32)> {
if i >= ix.count {
return None;
}
let a = c_off(t, i.wrapping_mul(ix.offsize).wrapping_add(ix.offs), ix.offsize);
if a <= 0 {
return None;
}
let b = c_off(t, (i + 1).wrapping_mul(ix.offsize).wrapping_add(ix.offs), ix.offsize);
if b <= 0 || b < a {
return None;
}
let len = (b - a) as u64;
let start = ix.data as u64 + a as u64 - 1;
if start + len > t.0.len() as u64 {
return None;
}
if start as u32 as i32 >= 0 { Some((start as u32, len as u32)) } else { None }
}
fn ix2_parse(t: Tb, pos: u32, ix: &mut Index) -> i64 {
ix.count = 0;
let count = c_off(t, pos, 4);
if count < 0 {
return -1;
}
let base = pos as u64 + 4; if count == 0 {
ix.offsize = 1;
ix.offs = base as u32;
ix.data = base as u32;
return base as i64;
}
let os = c8(t, base as u32);
if !(1..=4).contains(&os) {
return -1;
}
let os = os as u64;
let offs = base + 1;
let data = offs + (count as u64 + 1) * os;
if data > t.len() as u64 {
return -1;
}
let last = c_off(t, (offs + count as u64 * os) as u32, os as u32);
if last <= 0 {
return -1;
}
let end = data + last as u64 - 1;
if end > t.len() as u64 {
return -1;
}
ix.count = count as u32;
ix.offsize = os as u32;
ix.offs = offs as u32;
ix.data = data as u32;
end as i64
}
fn dict2_walk(t: Tb, start: u32, end: u32, regions: &dyn Fn(u32) -> Option<u32>, f: &mut dyn FnMut(u32, &[f64])) -> bool {
let mut st: Vec<f64> = Vec::new();
let mut vsi = 0u32;
let mut p = start;
while p < end {
let b = c8(t, p);
if b < 0 {
return false;
}
let v: f64;
if b <= 27 {
p += 1;
let mut o = b as u32;
if o == 12 {
let b2 = c8(t, p);
if b2 < 0 {
return false;
}
p += 1;
o = 1200 + b2 as u32;
}
if o == 23 {
let Some(nv) = st.pop() else { return false };
let n = cvttd(nv);
let Some(k) = regions(vsi) else { return false };
if n < 0 {
return false;
}
let need = n as u64 * (k as u64 + 1);
if need > st.len() as u64 {
return false;
}
let keep = st.len() - need as usize + n as usize;
st.truncate(keep);
continue;
}
if o == 22 {
match st.last().map(|&x| cvttd(x)) {
Some(i) if i >= 0 => vsi = i as u32,
_ => {}
}
}
f(o, &st);
st.clear();
continue;
} else if b == 28 {
let w = c16(t, p.wrapping_add(1));
if w < 0 {
return false;
}
v = (w as u16 as i16) as f64;
p += 3;
} else if b == 29 {
let w = c_off(t, p.wrapping_add(1), 4);
if w < 0 {
return false;
}
v = (w as u32 as i32) as f64;
p += 5;
} else if b == 30 {
p += 1;
v = dict_real(t, &mut p);
} else if b == 31 || b == 255 {
p += 1; st.clear();
continue;
} else if b <= 246 {
v = (b - 139) as f64;
p += 1;
} else {
let b2 = c8(t, p.wrapping_add(1));
if b2 < 0 {
return false;
}
p += 2;
v = if b <= 250 { ((b - 247) * 256 + b2 + 108) as f64 } else { (-((b - 251) * 256 + b2 + 108)) as f64 };
}
if st.len() >= DICT2_STACK {
return false;
}
st.push(v);
}
true
}
fn dict2_find(t: Tb, start: u32, end: u32, op: u32, regions: &dyn Fn(u32) -> Option<u32>, ops: &mut [f64; OPS_MAX]) -> i32 {
let mut found = -1i32;
dict2_walk(t, start, end, regions, &mut |o, a| {
if found < 0 && o == op {
let a = &a[a.len().saturating_sub(OPS_MAX)..];
ops[..a.len()].copy_from_slice(a);
found = a.len() as i32;
}
});
found
}
fn cf2_private(t: Tb, start: u32, end: u32, vstore: u32, ix: &mut Index, ops: &mut [f64; OPS_MAX]) -> u16 {
ix.count = 0;
let n = dict2_find(t, start, end, 18, &|_| None, ops);
if n < 2 {
return 0;
}
let size = cvttd(ops[n as usize - 2]);
let off = cvttd(ops[n as usize - 1]);
if size <= 0 || off <= 0 || off as u32 >= t.len() {
return 0;
}
let off = off as u32;
let e = off.saturating_add(size as u32).min(t.len());
let regions = |vsi: u32| if vstore == 0 { None } else { var::ivs_region_count(t, vstore, vsi) };
let (mut subrs, mut vsi) = (None, 0u16);
dict2_walk(t, off, e, ®ions, &mut |o, a| {
let last = a.last().map(|&v| cvttd(v));
match (o, last) {
(19, Some(s)) if subrs.is_none() => subrs = Some(s),
(22, Some(v)) if (0..=0xFFFF).contains(&v) => vsi = v as u16,
_ => {}
}
});
if let Some(s) = subrs
&& s > 0
&& let Some(pos) = (s as u32).checked_add(off)
{
ix2_parse(t, pos, ix); }
vsi
}
fn dict_find(t: Tb, start: u32, end: u32, op: u32, ops: &mut [f64; OPS_MAX]) -> i32 {
let mut p = start;
let mut n = 0usize;
while p < end {
let b = c8(t, p);
if b < 0 {
return -1;
}
let v: f64;
if b <= 21 {
p += 1;
let mut o = b as u32;
if o == 12 {
let b2 = c8(t, p);
if b2 < 0 {
return -1;
}
p += 1;
o = 1200 + b2 as u32;
}
if o == op {
return n as i32;
}
n = 0;
continue;
} else if b == 28 {
let w = c16(t, p.wrapping_add(1));
if w < 0 {
return -1;
}
v = (w as u16 as i16) as f64;
p = p.wrapping_add(3);
} else if b == 29 {
let w = c_off(t, p.wrapping_add(1), 4);
if w < 0 {
return -1;
}
v = (w as u32 as i32) as f64;
p = p.wrapping_add(5);
} else if b == 30 {
p += 1;
v = dict_real(t, &mut p);
} else if b < 32 {
p += 1;
n = 0;
continue;
} else if b <= 246 {
v = (b - 139) as f64;
p += 1;
} else if b <= 254 {
let b2 = c8(t, p.wrapping_add(1));
if b2 < 0 {
return -1;
}
p = p.wrapping_add(2);
v = if b <= 250 {
((b - 247) * 256 + b2 + 108) as f64
} else {
(-((b - 251) * 256 + b2 + 108)) as f64
};
} else {
p += 1;
n = 0;
continue;
}
if n < OPS_MAX {
ops[n] = v;
n += 1;
}
}
-1
}
fn dict_real(t: Tb, p: &mut u32) -> f64 {
let mut m = 0u64; let mut digits = 0i32; let mut fl = 0u32; let mut exp = 0i32;
'bytes: while (*p as usize) < t.0.len() {
let b = t.0[*p as usize] as u32;
*p += 1;
for nib in [b >> 4, b & 15] {
if nib <= 9 {
if fl & 4 != 0 {
if (exp as u32) < 1000 {
exp = exp * 10 + nib as i32;
}
} else if m >= 100_000_000_000_000_000 {
if fl & 2 == 0 {
digits -= 1; }
} else {
m = m * 10 + nib as u64;
if fl & 2 != 0 {
digits += 1;
}
}
continue;
}
match nib {
0xA => fl |= 2,
0xB => fl |= 4,
0xC => fl |= 4 | 8,
0xE => fl |= 1,
0xF => break 'bytes,
_ => {}
}
}
}
let mut v = m as i64 as f64;
if fl & 8 != 0 {
exp = exp.wrapping_neg();
}
let e = exp.wrapping_sub(digits);
if e > 0 {
if e as u32 > 400 {
return 0.0;
}
for _ in 0..e {
v = v * 10.0;
}
} else if e < 0 {
let mut c = e.wrapping_neg() as u32;
loop {
v = v / 10.0;
c -= 1;
if c == 0 {
break;
}
if c > 400 {
return 0.0;
}
}
}
if fl & 1 != 0 {
v = 0.0 - v;
}
v
}
fn cf_private(t: Tb, start: u32, end: u32, ix: &mut Index, ops: &mut [f64; OPS_MAX]) {
ix.count = 0;
let n = dict_find(t, start, end, 18, ops);
if n < 2 {
return;
}
let size = rt::fx::cvttd(ops[n as usize - 2]);
let off = rt::fx::cvttd(ops[n as usize - 1]);
if size <= 0 || off <= 0 || off as u32 >= t.len() {
return;
}
let off = off as u32;
let e = off.wrapping_add(size as u32).min(t.len());
let n = dict_find(t, off, e, 19, ops); if n < 1 {
return;
}
let s = rt::fx::cvttd(ops[n as usize - 1]);
if s <= 0 {
return;
}
let (pos, carry) = (s as u32).overflowing_add(off);
if carry {
return;
}
ix_parse(t, pos, ix);
}
impl Cff {
fn empty(v2: bool) -> Cff {
Cff {
v2,
cid: false,
cs: Index::default(),
gs: Index::default(),
ls: Index::default(),
fdsel: 0,
nfd: 0,
mat: [0.0; 6],
hasmat: false,
fdls: Vec::new(),
fdvs: Vec::new(),
vstore: 0,
maxstack: CS2_DEFSTACK as u32,
}
}
pub fn is_v2(&self) -> bool {
self.v2
}
pub fn varies(&self) -> bool {
self.v2 && self.vstore != 0
}
fn set_matrix(&mut self, m: &[f64], upem: u32) {
let u = upem as i32 as f64;
for (i, &v) in m.iter().take(6).enumerate() {
self.mat[i] = (v * u) as f32;
}
let abs = |v: f32| f32::from_bits(v.to_bits() & 0x7FFF_FFFF);
if abs(self.mat[0] - 1.0) > F_EPS || abs(self.mat[3] - 1.0) > F_EPS {
self.hasmat = true;
} else {
for i in [1, 2, 4, 5] {
if abs(self.mat[i]) > F_EPS {
self.hasmat = true;
break;
}
}
}
}
pub fn open(t: Tb, upem: u32) -> Result<Cff, i32> {
let mut ops = [0f64; OPS_MAX];
let mut c = Cff::empty(false);
if c8(t, 0) != 1 {
return Err(ERR_UNSUPPORTED);
}
let hs = c8(t, 2);
if hs < 0 {
return Err(ERR_HDR);
}
let mut top = Index::default();
let mut strs = Index::default();
let p = ix_parse(t, hs as u32, &mut top); if p < 0 {
return Err(ERR_HDR);
}
let p = ix_parse(t, p as u32, &mut top);
if p < 0 {
return Err(ERR_HDR);
}
let p = ix_parse(t, p as u32, &mut strs);
if p < 0 {
return Err(ERR_HDR);
}
if ix_parse(t, p as u32, &mut c.gs) < 0 {
return Err(ERR_HDR);
}
let Some((ds, dl)) = ix_get(t, &top, 0) else { return Err(ERR_HDR) };
let de = ds.wrapping_add(dl);
let n = dict_find(t, ds, de, 1206, &mut ops);
if n >= 1 && rt::fx::cvttd(ops[0]) != 2 {
return Err(ERR_UNSUPPORTED);
}
let n = dict_find(t, ds, de, 17, &mut ops);
if n < 1 {
return Err(ERR_HDR);
}
let o = rt::fx::cvttd(ops[n as usize - 1]);
if o <= 0 || ix_parse(t, o as u32, &mut c.cs) < 0 || c.cs.count == 0 {
return Err(ERR_HDR);
}
let n = dict_find(t, ds, de, 1207, &mut ops);
if n >= 6 {
let m = ops;
c.set_matrix(&m[..6], upem);
}
if dict_find(t, ds, de, 1230, &mut ops) >= 0 {
c.cid = true;
let n = dict_find(t, ds, de, 1236, &mut ops); if n < 1 {
return Err(ERR_HDR);
}
let o = rt::fx::cvttd(ops[n as usize - 1]);
if o <= 0 {
return Err(ERR_HDR);
}
let mut fda = Index::default();
if ix_parse(t, o as u32, &mut fda) < 0 {
return Err(ERR_HDR);
}
c.nfd = fda.count.min(FD_MAX);
let n = dict_find(t, ds, de, 1237, &mut ops); if n < 1 {
return Err(ERR_HDR);
}
let o = rt::fx::cvttd(ops[n as usize - 1]);
if o <= 0 || o as u32 >= t.len() {
return Err(ERR_HDR);
}
c.fdsel = o as u32;
c.fdls = vec![Index::default(); c.nfd as usize];
for fd in 0..c.nfd {
if let Some((s, l)) = ix_get(t, &fda, fd) {
cf_private(t, s, s.wrapping_add(l), &mut c.fdls[fd as usize], &mut ops);
}
}
} else {
cf_private(t, ds, de, &mut c.ls, &mut ops);
}
Ok(c)
}
pub fn open2(t: Tb, upem: u32) -> Result<Cff, i32> {
let mut ops = [0f64; OPS_MAX];
let mut c = Cff::empty(true);
if c8(t, 0) != 2 {
return Err(ERR_UNSUPPORTED);
}
let hs = c8(t, 2);
let tdl = c16(t, 3);
if hs < 5 || tdl < 0 {
return Err(ERR_HDR);
}
let ds = hs as u32;
let de = ds + tdl as u32;
if de > t.len() {
return Err(ERR_HDR);
}
let (mut cso, mut fda, mut fds, mut vst, mut maxst) = (None, None, None, None, None);
let mut mat: Option<[f64; 6]> = None;
dict2_walk(t, ds, de, &|_| None, &mut |op, a| {
let last = a.last().map(|&v| cvttd(v) as i64);
let slot = match op {
17 => &mut cso,
1236 => &mut fda,
1237 => &mut fds,
24 => &mut vst,
25 => &mut maxst,
1207 => {
if mat.is_none() && a.len() >= 6 {
mat = Some([a[0], a[1], a[2], a[3], a[4], a[5]]);
}
return;
}
_ => return,
};
if slot.is_none() {
*slot = last;
}
});
let len = t.len() as i64;
let pos = |o: Option<i64>| o.filter(|&o| o > 0 && o < len).map(|o| o as u32);
if ix2_parse(t, de, &mut c.gs) < 0 {
return Err(ERR_HDR);
}
match pos(cso) {
Some(o) if ix2_parse(t, o, &mut c.cs) >= 0 && c.cs.count != 0 => {}
_ => return Err(ERR_HDR),
}
if let Some(m) = mat {
c.set_matrix(&m, upem);
}
c.maxstack = maxst.unwrap_or(CS2_DEFSTACK).clamp(CS2_DEFSTACK, CS2_STACK as i64) as u32;
if let Some(o) = pos(vst)
&& o as u64 + 2 < t.len() as u64
{
c.vstore = o + 2;
}
let mut fdix = Index::default();
match pos(fda) {
Some(o) if ix2_parse(t, o, &mut fdix) >= 0 && fdix.count != 0 => {}
_ => return Err(ERR_HDR),
}
c.cid = true;
c.nfd = fdix.count.min(FD_MAX);
c.fdsel = pos(fds).unwrap_or(0);
c.fdls = vec![Index::default(); c.nfd as usize];
c.fdvs = vec![0; c.nfd as usize];
for fd in 0..c.nfd as usize {
if let Some((s, l)) = ix_get(t, &fdix, fd as u32) {
c.fdvs[fd] = cf2_private(t, s, s.wrapping_add(l), c.vstore, &mut c.fdls[fd], &mut ops);
}
}
Ok(c)
}
fn fdselect(&self, t: Tb, glyph: u32) -> i32 {
let fs = self.fdsel;
if fs == 0 {
return 0; }
match c8(t, fs) {
0 => c8(t, fs.wrapping_add(glyph).wrapping_add(1)),
3 => {
let n = c16(t, fs.wrapping_add(1));
if n <= 0 {
return -1;
}
let (mut lo, mut hi) = (0u32, n as u32);
while lo < hi {
let mid = lo + (hi - lo) / 2;
let first = c16(t, mid.wrapping_mul(3).wrapping_add(fs).wrapping_add(3));
if first < 0 {
return -1;
}
if first as u32 > glyph {
hi = mid;
} else {
lo = mid + 1;
}
}
if lo == 0 {
return -1;
}
c8(t, (lo - 1).wrapping_mul(3).wrapping_add(fs).wrapping_add(5))
}
4 if self.v2 => {
let n = c_off(t, fs.wrapping_add(1), 4);
if n <= 0 {
return -1;
}
let first = |k: u64| -> i64 {
let at = fs as u64 + 5 + k * 6;
if at + 6 > t.len() as u64 { -1 } else { c_off(t, at as u32, 4) }
};
let (mut lo, mut hi) = (0u64, n as u64);
while lo < hi {
let mid = lo + (hi - lo) / 2;
let f = first(mid);
if f < 0 {
return -1;
}
if f as u64 > glyph as u64 {
hi = mid;
} else {
lo = mid + 1;
}
}
if lo == 0 {
return -1;
}
c16(t, (fs as u64 + 5 + (lo - 1) * 6 + 4) as u32)
}
_ => -1,
}
}
pub fn outline(&self, t: Tb, glyph: u32, ol: &mut Outline) -> bool {
self.outline_var(t, glyph, &[], ol)
}
pub fn outline_var(&self, t: Tb, glyph: u32, coords: &[i16], ol: &mut Outline) -> bool {
if glyph >= self.cs.count {
return true;
}
let (ls, vsi) = if self.cid {
let fd = self.fdselect(t, glyph);
if fd as u32 >= self.nfd {
return false;
}
(self.fdls[fd as usize], self.fdvs.get(fd as usize).copied().unwrap_or(0))
} else {
(self.ls, 0)
};
let Some((s, l)) = ix_get(t, &self.cs, glyph) else { return false };
let mut cs = Cs {
t,
gs: self.gs,
ls,
st: [0.0; CS2_STACK],
sp: 0,
maxst: if self.v2 { self.maxstack as usize } else { CS_STACK },
x: 0.0,
y: 0.0,
px: 0.0,
py: 0.0,
d: [0.0; 6],
nstems: 0,
wd: self.v2, open: false,
budget: CS_BUDGET,
trans: [0.0; 32],
rand: 0,
v2: self.v2,
vstore: self.vstore,
vsi: vsi as u32,
coords,
sc: Vec::new(),
nreg: None,
blended: false,
ol,
};
if cs.run(s, s.wrapping_add(l), 0) < 0 {
return false;
}
let ol = cs.ol;
ol.close();
if self.hasmat {
let m = self.mat;
ol.transform(0, m[0], m[1], m[2], m[3]);
ol.translate(0, m[4], m[5]);
}
true
}
}
fn cs_bias(count: u32) -> i32 {
if count < 1240 {
107
} else if count < 33900 {
1131
} else {
32768
}
}
fn fabs(v: f32) -> f32 {
f32::from_bits(v.to_bits() & 0x7FFF_FFFF)
}
fn zf(a: f32, b: f32) -> bool {
!(a < b || a > b)
}
struct Cs<'a, 'o> {
t: Tb<'a>,
gs: Index,
ls: Index,
st: [f32; CS2_STACK],
sp: usize,
maxst: usize, x: f32,
y: f32,
px: f32,
py: f32,
d: [f32; 6],
nstems: u32,
wd: bool,
open: bool,
budget: i32,
trans: [f32; 32], rand: u32,
v2: bool,
vstore: u32,
vsi: u32,
coords: &'a [i16],
sc: Vec<f32>,
nreg: Option<usize>,
blended: bool,
ol: &'o mut Outline,
}
enum Flow {
Clear,
Loop,
Err,
Ret1,
}
impl Cs<'_, '_> {
fn arg(&self, i: usize) -> f32 {
if i < self.sp { self.st[i] } else { 0.0 }
}
fn point(&mut self, tag: u8) {
if !self.open {
self.open = true;
self.ol.point(self.px, self.py, OLT_ON);
}
self.ol.point(self.x, self.y, tag);
}
fn line(&mut self, dx: f32, dy: f32) {
self.px = self.x;
self.py = self.y;
self.x = dx + self.x;
self.y = dy + self.y;
self.point(OLT_ON);
}
fn curve(&mut self) {
self.px = self.x;
self.py = self.y;
for i in 0..3 {
self.x = self.d[i * 2] + self.x;
self.y = self.d[i * 2 + 1] + self.y;
self.point(if i == 2 { OLT_ON } else { OLT_CUBIC });
}
}
fn d6(&mut self, i: usize) {
for k in 0..6 {
self.d[k] = self.arg(i + k);
}
}
fn curve6(&mut self, i: usize) {
self.d6(i);
self.curve();
}
fn width(&mut self, expected: usize) -> usize {
if self.wd {
return 0;
}
self.wd = true;
(self.sp > expected) as usize
}
fn width_even(&mut self) -> u32 {
if self.wd {
return 0;
}
self.wd = true;
(self.sp & 1) as u32
}
fn moveto_begin(&mut self) {
if self.open {
self.ol.close();
self.open = false;
}
}
fn moveto_end(&mut self) {
self.open = true;
self.ol.point(self.x, self.y, OLT_ON);
}
fn push(&mut self, v: f32) -> Flow {
if self.sp >= self.maxst {
return Flow::Err;
}
self.st[self.sp] = v;
self.sp += 1;
Flow::Loop
}
fn top(&self) -> Option<f32> {
if self.sp == 0 { None } else { Some(self.st[self.sp - 1]) }
}
fn settop(&mut self, v: f32) -> Flow {
self.st[self.sp - 1] = v;
Flow::Loop
}
fn pop2(&mut self) -> Option<(f32, f32)> {
if self.sp < 2 {
return None;
}
self.sp -= 2;
Some((self.st[self.sp], self.st[self.sp + 1]))
}
fn roll(&mut self, num: i32, j: i32) {
let mut r = j % num;
if r < 0 {
r += num;
}
let first = self.sp - num as usize;
for _ in 0..r {
let top = self.st[self.sp - 1];
let mut k = self.sp - 1;
while k > first {
self.st[k] = self.st[k - 1];
k -= 1;
}
self.st[first] = top;
}
}
fn blend(&mut self) -> bool {
let Some(nv) = self.top() else { return false };
self.sp -= 1;
let n = cvtt(nv);
if n < 0 {
return false;
}
let k = match self.nreg {
Some(k) => k,
None => {
if var::ivs_scalars(self.t, self.vstore, self.vsi, self.coords, CS2_REGIONS, &mut self.sc).is_none() {
return false;
}
self.nreg = Some(self.sc.len());
self.sc.len()
}
};
let n = n as usize;
let Some(need) = n.checked_mul(k + 1) else { return false };
if need > self.sp {
return false;
}
let base = self.sp - need;
for i in 0..n {
let mut v = self.st[base + i];
let d = base + n + i * k;
for (r, &s) in self.sc[..k].iter().enumerate() {
if s != 0.0 {
v = v + self.st[d + r] * s;
}
}
self.st[base + i] = v;
}
self.sp = base + n;
self.blended = true;
true
}
fn run(&mut self, start: u32, end: u32, depth: u32) -> i32 {
if depth > CS_DEPTH {
return -1;
}
let t = self.t;
let mut p = start;
loop {
if p >= end {
return 0;
}
self.budget -= 1;
if self.budget < 0 {
return -1;
}
let b = t.0[p as usize] as u32;
p += 1;
let flow = if b >= 32 || b == 28 {
let v: f32;
if b == 28 {
if p + 2 > end {
return -1;
}
v = (u16::from_be_bytes([t.0[p as usize], t.0[p as usize + 1]]) as i16) as f32;
p += 2;
} else if b <= 246 {
v = (b as i32 - 139) as f32;
} else if b == 255 {
if p + 4 > end {
return -1;
}
let w = u32::from_be_bytes([
t.0[p as usize],
t.0[p as usize + 1],
t.0[p as usize + 2],
t.0[p as usize + 3],
]) as i32;
p += 4;
v = w as f32 * F_INV65536;
} else {
if p >= end {
return -1;
}
let b2 = t.0[p as usize] as i32;
p += 1;
v = if b <= 250 {
(((b as i32 - 247) << 8) + b2 + 108) as f32
} else {
(-(((b as i32 - 251) << 8) + b2 + 108)) as f32
};
}
self.push(v)
} else {
match b {
1 | 3 | 18 | 23 => {
let n = self.width_even();
self.nstems = self.nstems.wrapping_add((self.sp as u32 - n) >> 1);
Flow::Clear
}
19 | 20 => {
if self.sp != 0 {
let n = self.width_even(); self.nstems = self.nstems.wrapping_add((self.sp as u32 - n) >> 1);
}
self.wd = true;
p = p.wrapping_add(self.nstems.wrapping_add(7) >> 3);
Flow::Clear
}
21 => {
let i = self.width(2);
self.moveto_begin();
self.x = self.arg(i) + self.x;
self.y = self.arg(i + 1) + self.y;
self.moveto_end();
Flow::Clear
}
22 => {
let i = self.width(1);
self.moveto_begin();
self.x = self.arg(i) + self.x;
self.moveto_end();
Flow::Clear
}
4 => {
let i = self.width(1);
self.moveto_begin();
self.y = self.arg(i) + self.y;
self.moveto_end();
Flow::Clear
}
5 => {
let mut i = 0;
while i + 2 <= self.sp {
let (dx, dy) = (self.arg(i), self.arg(i + 1));
self.line(dx, dy);
i += 2;
}
Flow::Clear
}
6 | 7 => {
let mut vert = b == 7;
let mut i = 0;
while i < self.sp {
let v = self.arg(i);
if vert { self.line(0.0, v) } else { self.line(v, 0.0) }
vert = !vert;
i += 1;
}
Flow::Clear
}
8 => {
let mut i = 0;
while i + 6 <= self.sp {
self.curve6(i);
i += 6;
}
Flow::Clear
}
24 => {
let mut i = 0;
while i + 8 <= self.sp {
self.curve6(i);
i += 6;
}
if i + 2 <= self.sp {
let (dx, dy) = (self.arg(i), self.arg(i + 1));
self.line(dx, dy);
}
Flow::Clear
}
25 => {
let mut i = 0;
while i + 8 <= self.sp {
let (dx, dy) = (self.arg(i), self.arg(i + 1));
self.line(dx, dy);
i += 2;
}
if i + 6 <= self.sp {
self.curve6(i);
}
Flow::Clear
}
27 => {
let mut i = 0;
self.d[1] = 0.0;
if self.sp & 1 != 0 {
self.d[1] = self.arg(0);
i = 1;
}
while i + 4 <= self.sp {
self.d[0] = self.arg(i);
self.d[2] = self.arg(i + 1);
self.d[3] = self.arg(i + 2);
self.d[4] = self.arg(i + 3);
self.d[5] = 0.0;
self.curve();
self.d[1] = 0.0;
i += 4;
}
Flow::Clear
}
26 => {
let mut i = 0;
self.d[0] = 0.0;
if self.sp & 1 != 0 {
self.d[0] = self.arg(0);
i = 1;
}
while i + 4 <= self.sp {
self.d[1] = self.arg(i);
self.d[2] = self.arg(i + 1);
self.d[3] = self.arg(i + 2);
self.d[4] = 0.0;
self.d[5] = self.arg(i + 3);
self.curve();
self.d[0] = 0.0;
i += 4;
}
Flow::Clear
}
30 | 31 => {
let mut h = b == 31;
let mut i = 0;
while i + 4 <= self.sp {
let last = (self.sp - i == 5) as usize;
if h {
self.d[0] = self.arg(i);
self.d[1] = 0.0;
self.d[2] = self.arg(i + 1);
self.d[3] = self.arg(i + 2);
self.d[5] = self.arg(i + 3);
self.d[4] = 0.0;
if last != 0 {
self.d[4] = self.arg(i + 4);
}
} else {
self.d[0] = 0.0;
self.d[1] = self.arg(i);
self.d[2] = self.arg(i + 1);
self.d[3] = self.arg(i + 2);
self.d[4] = self.arg(i + 3);
self.d[5] = 0.0;
if last != 0 {
self.d[5] = self.arg(i + 4);
}
}
self.curve();
i += 4 + last;
h = !h;
}
Flow::Clear
}
10 | 29 => {
let ix = if b == 10 { self.ls } else { self.gs };
if self.sp == 0 {
return -1;
}
self.sp -= 1;
let idx = cvtt(self.st[self.sp]);
let i = cs_bias(ix.count).wrapping_add(idx);
if i < 0 {
return -1;
}
let Some((s, l)) = ix_get(t, &ix, i as u32) else { return -1 };
let r = self.run(s, s.wrapping_add(l), depth + 1);
if r < 0 {
return -1;
}
if r != 0 {
return 1; }
Flow::Loop
}
11 => return 0, 15 if self.v2 => {
let Some(v) = self.top() else { return -1 };
let i = cvtt(v);
if self.blended || i < 0 {
return -1;
}
self.vsi = i as u32;
self.nreg = None;
Flow::Clear
}
16 if self.v2 => {
if !self.blend() {
return -1;
}
Flow::Loop }
14 => {
self.wd = true;
self.moveto_begin();
Flow::Ret1
}
12 => {
if p >= end {
return -1;
}
let e = t.0[p as usize] as u32;
p += 1;
self.escape(e)
}
_ => Flow::Clear, }
};
match flow {
Flow::Clear => self.sp = 0,
Flow::Loop => {}
Flow::Err => return -1,
Flow::Ret1 => return 1,
}
}
}
fn escape(&mut self, e: u32) -> Flow {
match e {
35 => {
if self.sp < 12 {
return Flow::Clear;
}
self.d6(0);
self.curve();
self.d6(6);
self.curve();
Flow::Clear
}
34 => {
if self.sp < 7 {
return Flow::Clear;
}
let y0 = self.y;
self.d = [self.arg(0), 0.0, self.arg(1), self.arg(2), self.arg(3), 0.0];
self.curve();
self.d[0] = self.arg(4);
self.d[1] = 0.0;
self.d[2] = self.arg(5);
self.d[3] = y0 - self.y; self.d[4] = self.arg(6);
self.d[5] = 0.0;
self.curve();
Flow::Clear
}
36 => {
if self.sp < 9 {
return Flow::Clear;
}
let y0 = self.y;
self.d = [self.arg(0), self.arg(1), self.arg(2), self.arg(3), self.arg(4), 0.0];
self.curve();
self.d[0] = self.arg(5);
self.d[1] = 0.0;
self.d[2] = self.arg(6);
self.d[3] = self.arg(7);
self.d[4] = self.arg(8);
self.d[5] = (y0 - self.y) - self.d[3]; self.curve();
Flow::Clear
}
37 => {
if self.sp < 11 {
return Flow::Clear;
}
let (x0, y0) = (self.x, self.y);
let (mut sx, mut sy) = (0.0f32, 0.0f32);
for k in 0..5 {
sx = sx + self.st[k * 2];
sy = sy + self.st[k * 2 + 1];
}
let horiz = fabs(sx) > fabs(sy); self.d6(0);
self.curve();
self.d[0] = self.arg(6);
self.d[1] = self.arg(7);
self.d[2] = self.arg(8);
self.d[3] = self.arg(9);
let xx = (self.x + self.d[0]) + self.d[2];
let yy = (self.y + self.d[1]) + self.d[3];
let d6 = self.arg(10);
if horiz {
self.d[4] = d6;
self.d[5] = y0 - yy;
} else {
self.d[5] = d6;
self.d[4] = x0 - xx;
}
self.curve();
Flow::Clear
}
9 => match self.top() {
Some(v) => self.settop(fabs(v)),
None => Flow::Err,
},
14 => match self.top() {
Some(v) => self.settop(f32::from_bits(v.to_bits() ^ 0x8000_0000)),
None => Flow::Err,
},
26 => match self.top() {
Some(v) => self.settop(sqrt(fabs(v))),
None => Flow::Err,
},
5 => match self.top() {
Some(v) => self.settop(if zf(v, 0.0) { 1.0 } else { 0.0 }),
None => Flow::Err,
},
10 | 11 | 24 | 12 | 3 | 4 | 15 => {
let Some((a, b)) = self.pop2() else { return Flow::Err };
let r = match e {
10 => a + b,
11 => a - b,
24 => a * b,
12 => {
if zf(b, 0.0) {
0.0
} else {
a / b
}
}
3 => {
if zf(a, 0.0) || zf(b, 0.0) {
0.0
} else {
1.0
}
}
4 => {
if (a < 0.0 || a > 0.0) || (b < 0.0 || b > 0.0) {
1.0
} else {
0.0
}
}
_ => {
if zf(a, b) {
1.0
} else {
0.0
}
}
};
self.push(r)
}
18 => {
if self.sp == 0 {
return Flow::Err;
}
self.sp -= 1;
Flow::Loop
}
27 => match self.top() {
Some(v) => self.push(v),
None => Flow::Err,
},
28 => {
let Some((a, b)) = self.pop2() else { return Flow::Err };
self.st[self.sp] = b;
self.st[self.sp + 1] = a;
self.sp += 2;
Flow::Loop
}
29 => {
let Some(v) = self.top() else { return Flow::Err };
let mut i = cvtt(v);
if i < 0 {
i = 0;
}
let k = (self.sp as i32).wrapping_sub(2).wrapping_sub(i);
if k < 0 {
return Flow::Err;
}
let v = self.arg(k as usize);
self.settop(v)
}
30 => {
let Some((a, b)) = self.pop2() else { return Flow::Err };
let num = cvtt(a);
let j = cvtt(b);
if num <= 0 {
return Flow::Loop;
}
if num as usize > self.sp {
return Flow::Err;
}
self.roll(num, j);
Flow::Loop
}
20 => {
let Some((a, b)) = self.pop2() else { return Flow::Err };
let i = cvtt(b) as u32;
if i < 32 {
self.trans[i as usize] = a;
}
Flow::Loop
}
21 => {
let Some(v) = self.top() else { return Flow::Err };
let i = cvtt(v) as u32;
if i >= 32 {
return Flow::Err;
}
self.settop(self.trans[i as usize])
}
22 => {
if self.sp < 4 {
return Flow::Err;
}
self.sp -= 4;
let s = self.sp;
let v1 = self.st[s + 2];
let v2 = self.st[s + 3];
let r = if !(v1 > v2) { self.st[s] } else { self.st[s + 1] };
self.push(r)
}
23 => {
let r = self.rand.wrapping_mul(1_103_515_245).wrapping_add(12345);
self.rand = r;
let v = ((r >> 9) | 1) as i32 as f32 * F_INV8M; self.push(v)
}
_ => Flow::Clear, }
}
}