#![deny(missing_docs)]
use euclid::{size2, Box2D, num::Zero};
use peek_poke::PeekPoke;
use std::ops::{Add, Sub};
use std::sync::Arc;
use crate::{IdNamespace, TileSize};
use crate::font::{FontInstanceKey, FontInstanceData, FontKey, FontTemplate};
use crate::units::*;
pub const DEFAULT_TILE_SIZE: TileSize = 512;
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
pub struct ImageKey(pub IdNamespace, pub u32);
impl Default for ImageKey {
fn default() -> Self {
ImageKey::DUMMY
}
}
impl ImageKey {
pub const DUMMY: Self = ImageKey(IdNamespace(0), 0);
pub fn new(namespace: IdNamespace, key: u32) -> Self {
ImageKey(namespace, key)
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct BlobImageKey(pub ImageKey);
impl BlobImageKey {
pub fn as_image(self) -> ImageKey {
self.0
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
pub struct SnapshotImageKey(pub ImageKey);
impl SnapshotImageKey {
pub fn as_image(self) -> ImageKey {
self.0
}
}
impl Default for SnapshotImageKey {
fn default() -> Self {
SnapshotImageKey(ImageKey::DUMMY)
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct ExternalImageId(pub u64);
pub enum ExternalImageSource<'a> {
RawData(&'a [u8]),
NativeTexture(u32),
Invalid,
}
pub struct ExternalImage<'a> {
pub uv: TexelRect,
pub source: ExternalImageSource<'a>,
}
pub trait ExternalImageHandler {
fn lock(&mut self, key: ExternalImageId, channel_index: u8, is_composited: bool) -> ExternalImage;
fn unlock(&mut self, key: ExternalImageId, channel_index: u8);
}
#[repr(u8)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub enum ImageBufferKind {
Texture2D = 0,
TextureRect = 1,
TextureExternal = 2,
TextureExternalBT709 = 3,
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum ExternalImageType {
TextureHandle(ImageBufferKind),
Buffer,
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct ExternalImageData {
pub id: ExternalImageId,
pub channel_index: u8,
pub image_type: ExternalImageType,
pub normalized_uvs: bool,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum ImageFormat {
R8 = 1,
R16 = 2,
BGRA8 = 3,
RGBAF32 = 4,
RG8 = 5,
RG16 = 6,
RGBAI32 = 7,
RGBA8 = 8,
}
impl ImageFormat {
pub fn bytes_per_pixel(self) -> i32 {
match self {
ImageFormat::R8 => 1,
ImageFormat::R16 => 2,
ImageFormat::BGRA8 => 4,
ImageFormat::RGBAF32 => 16,
ImageFormat::RG8 => 2,
ImageFormat::RG16 => 4,
ImageFormat::RGBAI32 => 16,
ImageFormat::RGBA8 => 4,
}
}
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
pub enum ColorDepth {
#[default]
Color8,
Color10,
Color12,
Color16,
}
impl ColorDepth {
pub fn bit_depth(self) -> u32 {
match self {
ColorDepth::Color8 => 8,
ColorDepth::Color10 => 10,
ColorDepth::Color12 => 12,
ColorDepth::Color16 => 16,
}
}
pub fn rescaling_factor(self) -> f32 {
match self {
ColorDepth::Color8 => 1.0,
ColorDepth::Color10 => 64.0,
ColorDepth::Color12 => 16.0,
ColorDepth::Color16 => 1.0,
}
}
}
bitflags! {
#[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub struct ImageDescriptorFlags: u32 {
const IS_OPAQUE = 1;
const ALLOW_MIPMAPS = 2;
}
}
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct ImageDescriptor {
pub format: ImageFormat,
pub size: DeviceIntSize,
pub stride: Option<i32>,
pub offset: i32,
pub flags: ImageDescriptorFlags,
}
impl ImageDescriptor {
pub fn new(
width: i32,
height: i32,
format: ImageFormat,
flags: ImageDescriptorFlags,
) -> Self {
ImageDescriptor {
size: size2(width, height),
format,
stride: None,
offset: 0,
flags,
}
}
pub fn compute_stride(&self) -> i32 {
self.stride.unwrap_or(self.size.width * self.format.bytes_per_pixel())
}
pub fn compute_total_size(&self) -> i32 {
self.compute_stride() * self.size.height
}
pub fn full_rect(&self) -> DeviceIntRect {
DeviceIntRect::from_origin_and_size(
DeviceIntPoint::zero(),
self.size,
)
}
pub fn is_opaque(&self) -> bool {
self.flags.contains(ImageDescriptorFlags::IS_OPAQUE)
}
pub fn allow_mipmaps(&self) -> bool {
self.flags.contains(ImageDescriptorFlags::ALLOW_MIPMAPS)
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ImageData {
Raw(#[serde(with = "serde_image_data_raw")] Arc<Vec<u8>>),
External(ExternalImageData),
}
mod serde_image_data_raw {
extern crate serde_bytes;
use std::sync::Arc;
use serde::{Deserializer, Serializer};
pub fn serialize<S: Serializer>(bytes: &Arc<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error> {
serde_bytes::serialize(bytes.as_slice(), serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Arc<Vec<u8>>, D::Error> {
serde_bytes::deserialize(deserializer).map(Arc::new)
}
}
impl ImageData {
pub fn new(bytes: Vec<u8>) -> Self {
ImageData::Raw(Arc::new(bytes))
}
pub fn new_shared(bytes: Arc<Vec<u8>>) -> Self {
ImageData::Raw(bytes)
}
}
pub trait BlobImageResources {
fn get_font_data(&self, key: FontKey) -> Option<FontTemplate>;
fn get_font_instance_data(&self, key: FontInstanceKey) -> Option<FontInstanceData>;
}
pub trait BlobImageHandler: Send {
fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobImageRasterizer>;
fn create_similar(&self) -> Box<dyn BlobImageHandler>;
fn prepare_resources(
&mut self,
services: &dyn BlobImageResources,
requests: &[BlobImageParams],
);
fn add(&mut self, key: BlobImageKey, data: Arc<BlobImageData>, visible_rect: &DeviceIntRect,
tile_size: TileSize);
fn update(&mut self, key: BlobImageKey, data: Arc<BlobImageData>, visible_rect: &DeviceIntRect,
dirty_rect: &BlobDirtyRect);
fn delete(&mut self, key: BlobImageKey);
fn delete_font(&mut self, key: FontKey);
fn delete_font_instance(&mut self, key: FontInstanceKey);
fn clear_namespace(&mut self, namespace: IdNamespace);
fn enable_multithreading(&mut self, enable: bool);
}
pub trait AsyncBlobImageRasterizer : Send {
fn rasterize(
&mut self,
requests: &[BlobImageParams],
low_priority: bool,
tile_pool: &mut crate::BlobTilePool,
) -> Vec<(BlobImageRequest, BlobImageResult)>;
}
#[derive(Copy, Clone, Debug)]
pub struct BlobImageParams {
pub request: BlobImageRequest,
pub descriptor: BlobImageDescriptor,
pub dirty_rect: BlobDirtyRect,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum DirtyRect<T: Copy, U> {
All,
Partial(Box2D<T, U>)
}
impl<T, U> DirtyRect<T, U>
where
T: Copy + Clone
+ PartialOrd + PartialEq
+ Add<T, Output = T>
+ Sub<T, Output = T>
+ Zero
{
pub fn empty() -> Self {
DirtyRect::Partial(Box2D::zero())
}
pub fn is_empty(&self) -> bool {
match self {
DirtyRect::All => false,
DirtyRect::Partial(rect) => rect.is_empty(),
}
}
pub fn replace_with_empty(&mut self) -> Self {
::std::mem::replace(self, DirtyRect::empty())
}
pub fn map<F>(self, func: F) -> Self
where F: FnOnce(Box2D<T, U>) -> Box2D<T, U>,
{
use crate::DirtyRect::*;
match self {
All => All,
Partial(rect) => Partial(func(rect)),
}
}
pub fn union(&self, other: &Self) -> Self {
use crate::DirtyRect::*;
match (*self, *other) {
(All, _) | (_, All) => All,
(Partial(rect1), Partial(rect2)) => Partial(rect1.union(&rect2)),
}
}
pub fn intersection(&self, other: &Self) -> Self {
use crate::DirtyRect::*;
match (*self, *other) {
(All, rect) | (rect, All) => rect,
(Partial(rect1), Partial(rect2)) => {
Partial(rect1.intersection(&rect2).unwrap_or_else(Box2D::zero))
}
}
}
pub fn to_subrect_of(&self, rect: &Box2D<T, U>) -> Box2D<T, U> {
use crate::DirtyRect::*;
match *self {
All => *rect,
Partial(dirty_rect) => {
dirty_rect.intersection(rect).unwrap_or_else(Box2D::zero)
}
}
}
}
impl<T: Copy, U> Copy for DirtyRect<T, U> {}
impl<T: Copy, U> Clone for DirtyRect<T, U> {
fn clone(&self) -> Self { *self }
}
impl<T: Copy, U> From<Box2D<T, U>> for DirtyRect<T, U> {
fn from(rect: Box2D<T, U>) -> Self {
DirtyRect::Partial(rect)
}
}
pub type BlobImageData = Vec<u8>;
pub type BlobImageResult = Result<RasterizedBlobImage, BlobImageError>;
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct BlobImageDescriptor {
pub rect: LayoutIntRect,
pub format: ImageFormat,
}
pub struct RasterizedBlobImage {
pub rasterized_rect: DeviceIntRect,
pub data: Arc<Vec<u8>>,
}
#[derive(Clone, Debug)]
pub enum BlobImageError {
Oom,
Other(String),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct BlobImageRequest {
pub key: BlobImageKey,
pub tile: TileOffset,
}