///|
/// 2×2 matrix with 16.16 fixed-point entries.
/// Used for glyph transformations (scaling, rotation, skewing).
struct Matrix {
mut xx : Fixed
mut xy : Fixed
mut yx : Fixed
mut yy : Fixed
} derive(Eq, Show)
///|
/// Create a matrix with the given entries.
pub fn Matrix::new(xx : Fixed, xy : Fixed, yx : Fixed, yy : Fixed) -> Matrix {
{ xx, xy, yx, yy }
}
///|
/// Identity matrix.
pub fn Matrix::identity() -> Matrix {
{ xx: Fixed::one(), xy: Fixed::zero(), yx: Fixed::zero(), yy: Fixed::one() }
}
///|
pub fn Matrix::xx(self : Matrix) -> Fixed {
self.xx
}
///|
pub fn Matrix::xy(self : Matrix) -> Fixed {
self.xy
}
///|
pub fn Matrix::yx(self : Matrix) -> Fixed {
self.yx
}
///|
pub fn Matrix::yy(self : Matrix) -> Fixed {
self.yy
}
///|
pub fn Matrix::set_xx(self : Matrix, v : Fixed) -> Unit {
self.xx = v
}
///|
pub fn Matrix::set_xy(self : Matrix, v : Fixed) -> Unit {
self.xy = v
}
///|
pub fn Matrix::set_yx(self : Matrix, v : Fixed) -> Unit {
self.yx = v
}
///|
pub fn Matrix::set_yy(self : Matrix, v : Fixed) -> Unit {
self.yy = v
}
///|
/// Multiply matrix `a` into `self` (self = a * self).
/// Port of ftcalc.c FT_Matrix_Multiply.
pub fn Matrix::multiply(self : Matrix, a : Matrix) -> Unit {
let xx = mul_fix(a.xx, self.xx) + mul_fix(a.xy, self.yx)
let xy = mul_fix(a.xx, self.xy) + mul_fix(a.xy, self.yy)
let yx = mul_fix(a.yx, self.xx) + mul_fix(a.yy, self.yx)
let yy = mul_fix(a.yx, self.xy) + mul_fix(a.yy, self.yy)
self.xx = xx
self.xy = xy
self.yx = yx
self.yy = yy
}
///|
/// Invert this matrix in place.
/// Port of ftcalc.c FT_Matrix_Invert.
pub fn Matrix::invert(self : Matrix) -> Unit raise @error.FTError {
let delta = mul_fix(self.xx, self.yy) - mul_fix(self.xy, self.yx)
if delta.val == 0L {
raise @error.FTError::InvalidArgument
}
let xy = -div_fix(self.xy.val, delta.val)
let yx = -div_fix(self.yx.val, delta.val)
let xx = div_fix(self.yy.val, delta.val)
let yy = div_fix(self.xx.val, delta.val)
self.xx = xx
self.xy = xy
self.yx = yx
self.yy = yy
}
///|
/// Transform a vector (x, y) by this matrix.
/// Returns (xx*x + xy*y, yx*x + yy*y).
pub fn Matrix::transform(self : Matrix, x : Int64, y : Int64) -> (Int64, Int64) {
let rx = mul_fix(self.xx, { val: x }).val + mul_fix(self.xy, { val: y }).val
let ry = mul_fix(self.yx, { val: x }).val + mul_fix(self.yy, { val: y }).val
(rx, ry)
}