use crate::Pt;
use lopdf;
use lopdf::content::Operation;
#[derive(Debug, Copy, Clone)]
pub enum CurTransMat {
Translate(Pt, Pt),
Rotate(f32),
TranslateRotate(Pt, Pt, f32),
Scale(f32, f32),
Raw([f32; 6]),
Identity,
}
impl CurTransMat {
pub fn combine_matrix(a: [f32; 6], b: [f32; 6]) -> [f32; 6] {
let a = [
[a[0], a[1], 0.0, 0.0],
[a[2], a[3], 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[a[4], a[5], 0.0, 1.0],
];
let b = [
[b[0], b[1], 0.0, 0.0],
[b[2], b[3], 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[b[4], b[5], 0.0, 1.0],
];
let result = [
[
a[0][0].mul_add(
b[0][0],
a[0][1].mul_add(b[1][0], a[0][2].mul_add(b[2][0], a[0][3] * b[3][0])),
),
a[0][0].mul_add(
b[0][1],
a[0][1].mul_add(b[1][1], a[0][2].mul_add(b[2][1], a[0][3] * b[3][1])),
),
a[0][0].mul_add(
b[0][2],
a[0][1].mul_add(b[1][2], a[0][2].mul_add(b[2][2], a[0][3] * b[3][2])),
),
a[0][0].mul_add(
b[0][3],
a[0][1].mul_add(b[1][3], a[0][2].mul_add(b[2][3], a[0][3] * b[3][3])),
),
],
[
a[1][0].mul_add(
b[0][0],
a[1][1].mul_add(b[1][0], a[1][2].mul_add(b[2][0], a[1][3] * b[3][0])),
),
a[1][0].mul_add(
b[0][1],
a[1][1].mul_add(b[1][1], a[1][2].mul_add(b[2][1], a[1][3] * b[3][1])),
),
a[1][0].mul_add(
b[0][2],
a[1][1].mul_add(b[1][2], a[1][2].mul_add(b[2][2], a[1][3] * b[3][2])),
),
a[1][0].mul_add(
b[0][3],
a[1][1].mul_add(b[1][3], a[1][2].mul_add(b[2][3], a[1][3] * b[3][3])),
),
],
[
a[2][0].mul_add(
b[0][0],
a[2][1].mul_add(b[1][0], a[2][2].mul_add(b[2][0], a[2][3] * b[3][0])),
),
a[2][0].mul_add(
b[0][1],
a[2][1].mul_add(b[1][1], a[2][2].mul_add(b[2][1], a[2][3] * b[3][1])),
),
a[2][0].mul_add(
b[0][2],
a[2][1].mul_add(b[1][2], a[2][2].mul_add(b[2][2], a[2][3] * b[3][2])),
),
a[2][0].mul_add(
b[0][3],
a[2][1].mul_add(b[1][3], a[2][2].mul_add(b[2][3], a[2][3] * b[3][3])),
),
],
[
a[3][0].mul_add(
b[0][0],
a[3][1].mul_add(b[1][0], a[3][2].mul_add(b[2][0], a[3][3] * b[3][0])),
),
a[3][0].mul_add(
b[0][1],
a[3][1].mul_add(b[1][1], a[3][2].mul_add(b[2][1], a[3][3] * b[3][1])),
),
a[3][0].mul_add(
b[0][2],
a[3][1].mul_add(b[1][2], a[3][2].mul_add(b[2][2], a[3][3] * b[3][2])),
),
a[3][0].mul_add(
b[0][3],
a[3][1].mul_add(b[1][3], a[3][2].mul_add(b[2][3], a[3][3] * b[3][3])),
),
],
];
[
result[0][0],
result[0][1],
result[1][0],
result[1][1],
result[3][0],
result[3][1],
]
}
}
#[derive(Debug, Copy, Clone)]
pub enum TextMatrix {
Rotate(f32),
Translate(Pt, Pt),
TranslateRotate(Pt, Pt, f32),
Raw([f32; 6]),
}
impl From<TextMatrix> for [f32; 6] {
fn from(val: TextMatrix) -> Self {
use crate::TextMatrix::*;
match val {
Translate(x, y) => {
[1.0, 0.0, 0.0, 1.0, x.0, y.0]
}
Rotate(rot) => {
let rad = (360.0 - rot).to_radians();
[rad.cos(), -rad.sin(), rad.sin(), rad.cos(), 0.0, 0.0]
}
Raw(r) => r,
TranslateRotate(x, y, rot) => {
let rad = (360.0 - rot).to_radians();
[rad.cos(), -rad.sin(), rad.sin(), rad.cos(), x.0, y.0]
}
}
}
}
impl From<CurTransMat> for [f32; 6] {
fn from(val: CurTransMat) -> Self {
use crate::CurTransMat::*;
match val {
Translate(x, y) => {
[1.0, 0.0, 0.0, 1.0, x.0, y.0]
}
TranslateRotate(x, y, rot) => {
let rad = (360.0 - rot).to_radians();
[rad.cos(), -rad.sin(), rad.sin(), rad.cos(), x.0, y.0]
}
Rotate(rot) => {
let rad = (360.0 - rot).to_radians();
[rad.cos(), -rad.sin(), rad.sin(), rad.cos(), 0.0, 0.0]
}
Raw(r) => r,
Scale(x, y) => {
[x, 0.0, 0.0, y, 0.0, 0.0]
}
Identity => [1.0, 0.0, 0.0, 1.0, 0.0, 0.0],
}
}
}
impl From<CurTransMat> for Operation {
fn from(val: CurTransMat) -> Self {
use lopdf::Object::*;
let matrix_nums: [f32; 6] = val.into();
let matrix: Vec<lopdf::Object> = matrix_nums.iter().copied().map(Real).collect();
Operation::new("cm", matrix)
}
}
impl From<TextMatrix> for Operation {
fn from(val: TextMatrix) -> Self {
use lopdf::Object::*;
let matrix_nums: [f32; 6] = val.into();
let matrix: Vec<lopdf::Object> = matrix_nums.iter().copied().map(Real).collect();
Operation::new("Tm", matrix)
}
}
impl From<CurTransMat> for lopdf::Object {
fn from(val: CurTransMat) -> Self {
use lopdf::Object::*;
let matrix_nums: [f32; 6] = val.into();
Array(matrix_nums.iter().copied().map(Real).collect())
}
}
#[test]
fn test_ctm_translate() {
use self::*;
let ctm_trans = CurTransMat::Translate(Pt(150.0), Pt(50.0));
let ctm_trans_arr: [f32; 6] = ctm_trans.into();
assert_eq!([1.0_f32, 0.0, 0.0, 1.0, 150.0, 50.0], ctm_trans_arr);
let ctm_scale = CurTransMat::Scale(2.0, 4.0);
let ctm_scale_arr: [f32; 6] = ctm_scale.into();
assert_eq!([2.0_f32, 0.0, 0.0, 4.0, 0.0, 0.0], ctm_scale_arr);
let ctm_rot = CurTransMat::Rotate(30.0);
let ctm_rot_arr: [f32; 6] = ctm_rot.into();
assert_eq!(
[
0.8660253,
0.5000002,
-0.5000002,
0.8660253,
0.0,
0.0
],
ctm_rot_arr
);
}