x-graphics 0.2.1

Graphics framework for X
Documentation
use std::ops::Mul;

use web_sys::{DomMatrix, DomPoint, DomPointInit};

use crate::{geometry::FRect, matrix::MatrixBackend, Float};

#[derive(Clone, Debug, PartialEq)]
pub struct WebMatrix {
    pub matrix: DomMatrix,
}

impl Mul for WebMatrix {
    type Output = Self;

    fn mul(self, rhs: Self) -> Self::Output {
        Self {
            matrix: self.matrix.multiply(&rhs.matrix),
        }
    }
}

impl MatrixBackend for WebMatrix {
    fn identity() -> Self {
        Self {
            matrix: DomMatrix::new().unwrap(),
        }
    }

    fn from_row(scx: Float, sky: Float, skx: Float, scy: Float, tx: Float, ty: Float) -> Self {
        let matrix = DomMatrix::new().unwrap();
        matrix.set_a(scx);
        matrix.set_b(sky);
        matrix.set_c(skx);
        matrix.set_d(scy);
        matrix.set_e(tx);
        matrix.set_f(ty);
        Self {
            matrix,
        }
    }

    fn from_translate(x: Float, y: Float) -> Self {
        let matrix = DomMatrix::new().unwrap();
        matrix.set_e(x);
        matrix.set_f(y);
        Self {
            matrix,
        }
    }

    fn from_scale(x: Float, y: Float) -> Self {
        let matrix = DomMatrix::new().unwrap();
        matrix.set_a(x);
        matrix.set_d(y);
        Self {
            matrix,
        }
    }

    fn from_rotate(angle: Float) -> Self {
        let matrix = DomMatrix::new().unwrap();
        matrix.rotate(angle.to_degrees());
        Self {
            matrix,
        }
    }

    fn pre_rotate(&mut self, angle: Float) {
        let matrix = DomMatrix::new().unwrap();
        matrix.rotate(angle.to_degrees());
        self.matrix.pre_multiply_self(&matrix);
    }

    fn pre_translate(&mut self, x: Float, y: Float) {
        let matrix = DomMatrix::new().unwrap();
        matrix.set_e(x);
        matrix.set_f(y);
        self.matrix.pre_multiply_self(&matrix);
    }

    fn pre_scale(&mut self, x: Float, y: Float) {
        let matrix = DomMatrix::new().unwrap();
        matrix.set_a(x);
        matrix.set_d(y);
        self.matrix.pre_multiply_self(&matrix);
    }

    fn post_rotate(&mut self, angle: Float) {
        let matrix = DomMatrix::new().unwrap();
        matrix.rotate(angle.to_degrees());
        self.matrix.multiply_self(&matrix);
    }

    fn post_scale(&mut self, x: Float, y: Float) {
        let matrix = DomMatrix::new().unwrap();
        matrix.set_a(x);
        matrix.set_d(y);
        self.matrix.multiply_self(&matrix);
    }

    fn post_translate(&mut self, x: Float, y: Float) {
        let matrix = DomMatrix::new().unwrap();
        matrix.set_e(x);
        matrix.set_f(y);
        self.matrix.multiply_self(&matrix);
    }

    fn map_rect(&self, rect: FRect) -> FRect {
        let point1 = self.map_point(rect.point.x, rect.point.y);
        let point2 = self.map_point(rect.point.x + rect.size.width, rect.point.y);
        let point3 = self.map_point(rect.point.x, rect.point.y + rect.size.height);
        let point4 = self.map_point(rect.point.x + rect.size.width, rect.point.y + rect.size.height);
        let min_x = point1.x().min(point2.x()).min(point3.x()).min(point4.x());
        let min_y = point1.y().min(point2.y()).min(point3.y()).min(point4.y());
        let max_x = point1.x().max(point2.x()).max(point3.x()).max(point4.x());
        let max_y = point1.y().max(point2.y()).max(point3.y()).max(point4.y());
        FRect::new(min_x, min_y, max_x - min_x, max_y - min_y)
    }
}

impl WebMatrix {
    pub(super) fn matrix(&self) -> &DomMatrix {
        &self.matrix
    }

    fn map_point(&self, x: Float, y: Float) -> DomPoint {
        let point = DomPointInit::new();
        point.set_x(x);
        point.set_y(y);
        self.matrix.transform_point_with_point(&point)
    }
}

impl From<DomMatrix> for WebMatrix {
    fn from(matrix: DomMatrix) -> Self {
        Self {
            matrix,
        }
    }
}