canvas/src/utils.rs

215 lines
4.7 KiB
Rust

#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
use winit;
use cgmath::{Vector3, Vector2};
//--Position struct---------------------------------------------------------------------------------
#[derive(Copy, Clone, Debug)]
pub struct Position {
pub x: i32,
pub y: i32,
}
impl Position {
pub fn origin() -> Self {
Position {
x: 0,
y: 0,
}
}
}
impl From<Position> for Vector3<f32> {
fn from(pos: Position) -> Self {
Self::new(pos.x as f32, pos.y as f32, 0.0)
}
}
impl From<Position> for Vector2<f32> {
fn from(pos: Position) -> Self {
Self::new(pos.x as f32, pos.y as f32)
}
}
impl std::ops::Add for Position {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Position {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl std::ops::Mul<f32> for Position {
type Output = Self;
fn mul(self, rhs: f32) -> Self::Output {
Position {
x: ((self.x as f32) * rhs) as i32,
y: ((self.y as f32) * rhs) as i32,
}
}
}
//--Size struct-------------------------------------------------------------------------------------
#[derive(Copy, Clone)]
pub struct Size {
pub w: u32,
pub h: u32,
}
impl From<Size> for winit::dpi::Size {
fn from(size: Size) -> Self {
winit::dpi::Size::Physical (
winit::dpi::PhysicalSize {
width: size.w,
height: size.h,
})
}
}
impl From<Size> for wgpu::Extent3d {
fn from(size: Size) -> Self {
wgpu::Extent3d {
width: size.w,
height: size.h,
depth_or_array_layers: 1,
}
}
}
impl From<winit::dpi::PhysicalSize<u32>> for Size {
fn from(size: winit::dpi::PhysicalSize<u32>) -> Self {
Self {
w: size.width,
h: size.height,
}
}
}
impl From<Size> for Vector2<f32> {
fn from(size: Size) -> Self {
Self::new(size.w as f32, size.h as f32)
}
}
//--Pixel struct------------------------------------------------------------------------------------
#[repr(packed, C)]
#[derive(Copy, Clone, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Pixel {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
impl From<Color> for Pixel {
fn from(value: Color) -> Self {
value.into_pixel()
}
}
impl Pixel {
pub const fn from_hex(hex: u32) -> Self {
let bytes = hex.to_be_bytes();
Self { r: bytes[0], g: bytes[1], b: bytes[2], a: bytes[3] }
}
}
//--Color values------------------------------------------------------------------------------------
#[non_exhaustive]
#[derive(Copy, Clone, PartialEq)]
pub struct Color {
r: f32,
g: f32,
b: f32,
a: f32,
}
impl From<Pixel> for Color {
fn from(value: Pixel) -> Self {
Self {
r: f32::from(value.r) / 255.0,
g: f32::from(value.g) / 255.0,
b: f32::from(value.b) / 255.0,
a: f32::from(value.a) / 255.0,
}
}
}
impl Color {
pub fn set_alpha(&mut self, a: u8) {
self.a = f32::from(a) / 255.0;
}
pub fn from_rgb(r: u8, g: u8, b: u8) -> Self {
Pixel { r, g, b, a: 255 }.into()
}
pub fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
Pixel { r, g, b, a }.into()
}
pub fn from_hex(hex: u32) -> Self {
Pixel::from_hex(hex).into()
}
pub fn into_pixel(self) -> Pixel {
//unsafe block is used here for "to_int_unchecked" since the struct's invariant garentees
//that the values are within [0.0, 1.0], meaning we won't ever overflow an u8
unsafe {
Pixel {
r: self.r.to_int_unchecked::<u8>() * 255,
g: self.g.to_int_unchecked::<u8>() * 255,
b: self.b.to_int_unchecked::<u8>() * 255,
a: self.a.to_int_unchecked::<u8>() * 255,
}
}
}
pub fn into_wgpu_color(self) -> wgpu::Color {
wgpu::Color {
r: f64::from(self.r),
g: f64::from(self.g),
b: f64::from(self.b),
a: f64::from(self.a),
}
}
pub fn alpha_blend(&self, other: &Self) -> Self {
//apply alpha compisting's "over" operator, see
//[https://en.wikipedia.org/wiki/Alpha_compositing] for more detail
let a = self.a + other.a * (1.0 - self.a);
Self {
r: (self.r * self.a + other.r * other.a * (1.0 - self.a)) / a,
g: (self.g * self.a + other.g * other.a * (1.0 - self.a)) / a,
b: (self.b * self.a + other.b * other.a * (1.0 - self.a)) / a,
a,
}
}
pub const NONE: Self = Self {r: 0.0, g: 0.0, b: 0.0, a: 0.0};
pub const WHITE: Self = Self {r: 1.0, g: 1.0, b: 1.0, a: 1.0};
pub const BLACK: Self = Self {r: 0.0, g: 0.0, b: 0.0, a: 1.0};
pub const RED: Self = Self {r: 1.0, g: 0.0, b: 0.0, a: 1.0};
pub const GREEN: Self = Self {r: 0.0, g: 1.0, b: 0.0, a: 1.0};
pub const BLUE: Self = Self {r: 0.0, g: 0.0, b: 1.0, a: 1.0};
}