#![warn(
deprecated_in_future,
missing_debug_implementations,
trivial_casts,
unused_extern_crates,
missing_docs,
clippy::clone_on_ref_ptr,
clippy::cargo_common_metadata,
clippy::cast_lossless,
clippy::checked_conversions,
clippy::default_trait_access
)]
#[macro_use]
extern crate log;
use std::{any, fmt, marker::PhantomData, rc::Rc};
use static_assertions::assert_not_impl_any;
#[cfg(all(feature = "serde", not(feature = "serde1")))]
compile_error!("Tried using the feature `serde` directly, consider enabling `serde1` instead");
#[cfg(feature = "serde1")]
use serde::{Deserialize, Serialize};
macro_rules! bug {
($msg:expr$(,)?) => ({
panic!("{}\n\n This might be a bug, consider filing an issue at https://github.com/lcnr/crow/issues/new", $msg)
});
($fmt:expr, $($arg:tt)+) => ({
panic!("{}\n\n This might be a bug, consider filing an issue at https://github.com/lcnr/crow/issues/new", format_args!($fmt, $($arg)+))
});
}
mod backend;
mod context;
mod error;
mod texture;
pub mod color;
pub mod target;
pub use error::*;
pub use glutin;
pub use image;
use image::RgbaImage;
use backend::{tex::RawTexture, Backend};
trait UnwrapBug<T> {
fn unwrap_bug(self) -> T;
}
impl<T, E: fmt::Debug> UnwrapBug<T> for Result<T, E> {
fn unwrap_bug(self) -> T {
match self {
Ok(v) => v,
Err(e) => bug!("unexpected internal error: {:?}", e),
}
}
}
#[derive(Clone, Copy)]
struct SkipDebug<T>(T);
impl<T> fmt::Debug for SkipDebug<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SkipDebug<{}>", any::type_name::<T>())
}
}
pub trait DrawTarget {
fn receive_draw(
&mut self,
ctx: &mut Context,
texture: &Texture,
position: (i32, i32),
config: &DrawConfig,
);
fn receive_clear_color(&mut self, ctx: &mut Context, color: (f32, f32, f32, f32));
fn receive_clear_depth(&mut self, ctx: &mut Context);
fn receive_line(
&mut self,
ctx: &mut Context,
from: (i32, i32),
to: (i32, i32),
color: (f32, f32, f32, f32),
);
fn receive_rectangle(
&mut self,
ctx: &mut Context,
lower_left: (i32, i32),
upper_right: (i32, i32),
color: (f32, f32, f32, f32),
);
fn get_image_data(&self, ctx: &mut Context) -> RgbaImage;
}
impl<T: DrawTarget> DrawTarget for &mut T {
fn receive_draw(
&mut self,
ctx: &mut Context,
texture: &Texture,
position: (i32, i32),
config: &DrawConfig,
) {
<T>::receive_draw(self, ctx, texture, position, config)
}
fn receive_clear_color(&mut self, ctx: &mut Context, color: (f32, f32, f32, f32)) {
<T>::receive_clear_color(self, ctx, color)
}
fn receive_clear_depth(&mut self, ctx: &mut Context) {
<T>::receive_clear_depth(self, ctx)
}
fn receive_line(
&mut self,
ctx: &mut Context,
from: (i32, i32),
to: (i32, i32),
color: (f32, f32, f32, f32),
) {
<T>::receive_line(self, ctx, from, to, color)
}
fn receive_rectangle(
&mut self,
ctx: &mut Context,
lower_left: (i32, i32),
upper_right: (i32, i32),
color: (f32, f32, f32, f32),
) {
<T>::receive_rectangle(self, ctx, lower_left, upper_right, color)
}
fn get_image_data(&self, ctx: &mut Context) -> RgbaImage {
<T>::get_image_data(self, ctx)
}
}
#[derive(Debug)]
pub struct Context {
backend: Backend,
surface: Option<WindowSurface>,
}
assert_not_impl_any!(Context: Send, Sync, Clone);
#[derive(Debug)]
pub struct WindowSurface {
_marker: PhantomData<*const ()>,
}
assert_not_impl_any!(WindowSurface: Send, Sync, Clone);
#[derive(Debug, Clone)]
pub struct Texture {
inner: Rc<RawTexture>,
position: (u32, u32),
size: (u32, u32),
}
assert_not_impl_any!(Texture: Send, Sync);
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum BlendMode {
Alpha,
Additive,
}
impl Default for BlendMode {
fn default() -> Self {
BlendMode::Alpha
}
}
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct DrawConfig {
pub scale: (u32, u32),
pub rotation: i32,
pub flip_vertically: bool,
pub flip_horizontally: bool,
pub depth: Option<f32>,
pub color_modulation: [[f32; 4]; 4],
pub invert_color: bool,
pub blend_mode: BlendMode,
#[doc(hidden)]
pub __non_exhaustive: (),
}
impl Default for DrawConfig {
fn default() -> Self {
Self {
scale: (1, 1),
rotation: 0,
depth: None,
color_modulation: color::IDENTITY,
invert_color: false,
flip_vertically: false,
flip_horizontally: false,
blend_mode: BlendMode::default(),
__non_exhaustive: (),
}
}
}