#![allow(dead_code)]
mod table;
mod tag;
use super::parse::ReadData;
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
pub use table::*;
pub use tag::*;
pub type F2dot14 = i16;
pub type FWord = i16;
pub type UfWord = u16;
pub type GlyphId = u16;
pub type NormalizedCoord = F2dot14;
pub(crate) mod ops {
pub fn floor(x: i32) -> i32 {
x & !63
}
pub fn ceil(x: i32) -> i32 {
floor(x + 63)
}
pub fn round(x: i32) -> i32 {
floor(x + 32)
}
#[inline(always)]
pub fn mul(a: i32, b: i32) -> i32 {
let ab = a as i64 * b as i64;
((ab + 0x8000 - if ab < 0 { 1 } else { 0 }) >> 16) as i32
}
pub fn div(mut a: i32, mut b: i32) -> i32 {
let mut sign = 1;
if a < 0 {
a = -a;
sign = -1;
}
if b < 0 {
b = -b;
sign = -sign;
}
let q = if b == 0 {
0x7FFFFFFF
} else {
((((a as u64) << 16) + ((b as u64) >> 1)) / (b as u64)) as u32
};
if sign < 0 {
-(q as i32)
} else {
q as i32
}
}
pub fn muldiv(mut a: i32, mut b: i32, mut c: i32) -> i32 {
let mut sign = 1;
if a < 0 {
a = -a;
sign = -1;
}
if b < 0 {
b = -b;
sign = -sign;
}
if c < 0 {
c = -c;
sign = -sign;
}
let d = if c > 0 {
((a as i64) * (b as i64) + ((c as i64) >> 1)) / c as i64
} else {
0x7FFFFFFF
};
if sign < 0 {
-(d as i32)
} else {
d as i32
}
}
pub fn transform(x: i32, y: i32, xx: i32, xy: i32, yx: i32, yy: i32) -> (i32, i32) {
let scale = 0x10000;
(
muldiv(x, xx, scale) + muldiv(y, xy, scale),
muldiv(x, yx, scale) + muldiv(y, yy, scale),
)
}
}
pub(crate) use ops::*;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Debug)]
pub struct Fixed(pub i32);
impl Fixed {
pub const MIN: Self = Self(0x80000000u32 as i32);
pub const MAX: Self = Self(0x7FFFFFFF);
pub const EPSILON: Self = Self(1);
pub const ZERO: Self = Self(0);
pub const ONE: Self = Self(0x10000);
pub const fn from_i32(x: i32) -> Self {
Self(x << 16)
}
pub fn from_f32(x: f32) -> Self {
Self((x * 65536. + 0.5) as i32)
}
pub fn from_f2dot14(x: F2dot14) -> Self {
Self(x as i32 * 4)
}
pub fn round(self) -> Self {
Self(((self.0 as u32 + 0x8000) & 0xFFFF0000) as i32)
}
pub fn abs(self) -> Self {
Self(self.0.abs())
}
pub fn min(self, other: Self) -> Self {
Self(self.0.min(other.0))
}
pub fn max(self, other: Self) -> Self {
Self(self.0.max(other.0))
}
pub fn floor(self) -> Self {
Self((self.0 as u32 & 0xFFFF0000) as i32)
}
pub fn fract(self) -> Self {
Self(self.0 - self.floor().0)
}
pub fn to_i32(self) -> i32 {
(self.0 + 0x8000) >> 16
}
pub fn to_f32(self) -> f32 {
self.0 as f32 / 65536.
}
pub fn to_f2dot14(self) -> F2dot14 {
((self.0 + 2) >> 2) as F2dot14
}
}
impl Add for Fixed {
type Output = Self;
#[inline(always)]
fn add(self, other: Self) -> Self {
Self((self.0 as u32).wrapping_add(other.0 as u32) as i32)
}
}
impl AddAssign for Fixed {
fn add_assign(&mut self, other: Self) {
self.0 = self.0.wrapping_add(other.0);
}
}
impl Sub for Fixed {
type Output = Self;
#[inline(always)]
fn sub(self, other: Self) -> Self {
Self((self.0 as u32).wrapping_sub(other.0 as u32) as i32)
}
}
impl SubAssign for Fixed {
fn sub_assign(&mut self, other: Self) {
self.0 = self.0.wrapping_sub(other.0);
}
}
impl Mul for Fixed {
type Output = Self;
#[inline(always)]
fn mul(self, other: Self) -> Self {
Self(mul(self.0, other.0))
}
}
impl MulAssign for Fixed {
fn mul_assign(&mut self, other: Self) {
self.0 = mul(self.0, other.0);
}
}
impl Div for Fixed {
type Output = Self;
#[inline(always)]
fn div(self, other: Self) -> Self {
Self(div(self.0, other.0))
}
}
impl DivAssign for Fixed {
fn div_assign(&mut self, other: Self) {
self.0 = div(self.0, other.0);
}
}
impl Div<i32> for Fixed {
type Output = Self;
#[inline(always)]
fn div(self, other: i32) -> Self {
Self(self.0 / other)
}
}
impl Neg for Fixed {
type Output = Self;
fn neg(self) -> Self {
Self(-self.0)
}
}
impl ReadData for Fixed {
unsafe fn read_data_unchecked(buf: &[u8], offset: usize) -> Self {
Self(i32::read_data_unchecked(buf, offset))
}
}