#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct F26Dot6(pub i32);
impl F26Dot6 {
pub const ZERO: F26Dot6 = F26Dot6(0);
pub const ONE: F26Dot6 = F26Dot6(64);
#[inline]
pub fn from_i32(v: i32) -> Self {
F26Dot6(v << 6)
}
#[inline]
pub fn from_bits(v: i32) -> Self {
F26Dot6(v)
}
#[inline]
pub fn to_bits(self) -> i32 {
self.0
}
#[inline]
pub fn to_i32(self) -> i32 {
self.0 >> 6
}
#[inline]
pub fn to_f64(self) -> f64 {
self.0 as f64 / 64.0
}
#[inline]
pub fn from_f64(v: f64) -> Self {
F26Dot6((v * 64.0) as i32)
}
#[inline]
pub fn from_funits(funits: i32, scale: i64) -> Self {
let mut s: i64 = 1;
let mut a = funits as i64;
let mut b = scale;
if a < 0 { a = -a; s = -s; }
if b < 0 { b = -b; s = -s; }
let c = (a * b + 0x8000) >> 16;
F26Dot6((if s > 0 { c } else { -c }) as i32)
}
#[inline]
pub fn floor(self) -> Self {
F26Dot6(self.0 & !63)
}
#[inline]
pub fn ceil(self) -> Self {
F26Dot6((self.0 + 63) & !63)
}
#[inline]
pub fn round(self) -> Self {
F26Dot6((self.0 + 32) & !63)
}
#[inline]
pub fn abs(self) -> Self {
F26Dot6(self.0.abs())
}
}
impl std::ops::Add for F26Dot6 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
F26Dot6(self.0 + rhs.0)
}
}
impl std::ops::Sub for F26Dot6 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
F26Dot6(self.0 - rhs.0)
}
}
impl std::ops::Neg for F26Dot6 {
type Output = Self;
#[inline]
fn neg(self) -> Self {
F26Dot6(-self.0)
}
}
impl std::ops::AddAssign for F26Dot6 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}
impl std::ops::SubAssign for F26Dot6 {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
self.0 -= rhs.0;
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct F2Dot14(pub i32);
impl F2Dot14 {
pub const ZERO: F2Dot14 = F2Dot14(0);
pub const ONE: F2Dot14 = F2Dot14(0x4000);
#[inline]
pub fn to_f64(self) -> f64 {
self.0 as f64 / 16384.0
}
#[inline]
pub fn from_f64(v: f64) -> Self {
F2Dot14((v * 16384.0) as i32)
}
#[inline]
pub fn from_bits(v: i32) -> Self {
F2Dot14(v)
}
#[inline]
pub fn to_bits(self) -> i32 {
self.0
}
}
#[inline]
pub fn mul_2dot14(a: F2Dot14, b: F2Dot14) -> F2Dot14 {
F2Dot14(((a.0 as i64 * b.0 as i64 + 0x2000) >> 14) as i32)
}
#[inline]
pub fn mul_f26dot6_by_f2dot14(a: F26Dot6, b: F2Dot14) -> F26Dot6 {
F26Dot6(((a.0 as i64 * b.0 as i64 + 0x2000) >> 14) as i32)
}
pub fn vec_length(x: F2Dot14, y: F2Dot14) -> F2Dot14 {
let x = x.0 as f64 / 16384.0;
let y = y.0 as f64 / 16384.0;
let len = (x * x + y * y).sqrt();
F2Dot14::from_f64(len)
}
pub fn compute_scale(ppem: u16, units_per_em: u16) -> i64 {
if units_per_em == 0 {
return 0;
}
let upem = units_per_em as i64;
(((ppem as i64) << 22) + (upem >> 1)) / upem
}