use super::*;
use i_slint_core::graphics::IntSize;
pub use i_slint_core::graphics::TexturePixelFormat;
#[derive(Clone)]
#[non_exhaustive]
pub struct TextureData<'a> {
pub data: &'a [u8],
pub pixel_format: TexturePixelFormat,
pub byte_stride: usize,
pub width: u32,
pub height: u32,
}
impl<'a> TextureData<'a> {
pub fn new(
data: &'a [u8],
pixel_format: TexturePixelFormat,
byte_stride: usize,
size: IntSize,
) -> Self {
let (width, height) = (size.width, size.height);
Self { data, pixel_format, byte_stride, width, height }
}
}
pub(super) enum TextureDataContainer {
Static(TextureData<'static>),
Shared { buffer: super::scene::SharedBufferData, source_rect: PhysicalRect },
}
#[derive(Debug, Clone)]
pub struct TilingInfo {
pub offset_x: i32,
pub offset_y: i32,
pub scale_x: f32,
pub scale_y: f32,
pub gap_x: u32,
pub gap_y: u32,
}
#[non_exhaustive]
pub struct DrawTextureArgs {
pub(super) data: TextureDataContainer,
pub colorize: Option<Color>,
pub alpha: u8,
pub dst_x: isize,
pub dst_y: isize,
pub dst_width: usize,
pub dst_height: usize,
pub rotation: RenderingRotation,
pub tiling: Option<TilingInfo>,
}
impl DrawTextureArgs {
pub fn source(&self) -> TextureData<'_> {
match &self.data {
TextureDataContainer::Static(data) => data.clone(),
TextureDataContainer::Shared { buffer, source_rect } => {
let stride = buffer.width();
let core::ops::Range { start, end } = compute_range_in_buffer(&source_rect, stride);
let size = source_rect.size.to_untyped().cast();
match &buffer {
SharedBufferData::SharedImage(SharedImageBuffer::RGB8(b)) => TextureData::new(
&b.as_bytes()[start * 3..end * 3],
TexturePixelFormat::Rgb,
stride * 3,
size,
),
SharedBufferData::SharedImage(SharedImageBuffer::RGBA8(b)) => TextureData::new(
&b.as_bytes()[start * 4..end * 4],
TexturePixelFormat::Rgba,
stride * 4,
size,
),
SharedBufferData::SharedImage(SharedImageBuffer::RGBA8Premultiplied(b)) => {
TextureData::new(
&b.as_bytes()[start * 4..end * 4],
TexturePixelFormat::RgbaPremultiplied,
stride * 4,
size,
)
}
SharedBufferData::AlphaMap { data, .. } => TextureData::new(
&data[start..end],
TexturePixelFormat::AlphaMap,
stride,
size,
),
}
}
}
}
pub(super) fn source_size(&self) -> PhysicalSize {
match &self.data {
TextureDataContainer::Static(data) => {
PhysicalSize::new(data.width as _, data.height as _)
}
TextureDataContainer::Shared { source_rect, .. } => source_rect.size,
}
}
}
#[non_exhaustive]
#[derive(Default, Debug)]
pub struct DrawRectangleArgs {
pub x: f32,
pub y: f32,
pub width: f32,
pub height: f32,
pub top_left_radius: f32,
pub top_right_radius: f32,
pub bottom_right_radius: f32,
pub bottom_left_radius: f32,
pub border_width: f32,
pub background: Brush,
pub border: Brush,
pub alpha: u8,
pub rotation: RenderingRotation,
}
impl DrawRectangleArgs {
pub(super) fn from_rect(geometry: euclid::Rect<f32, PhysicalPx>, background: Brush) -> Self {
Self {
x: geometry.origin.x,
y: geometry.origin.y,
width: geometry.size.width,
height: geometry.size.height,
background,
alpha: 255,
..Default::default()
}
}
pub(super) fn geometry(&self) -> euclid::Rect<f32, PhysicalPx> {
euclid::rect(self.x, self.y, self.width, self.height)
}
}
pub trait TargetPixelBuffer {
type TargetPixel: TargetPixel;
fn line_slice(&mut self, line_number: usize) -> &mut [Self::TargetPixel];
fn num_lines(&self) -> usize;
fn fill_background(&mut self, _brush: &Brush, _region: &PhysicalRegion) -> bool {
false
}
fn draw_rectangle(&mut self, _: &DrawRectangleArgs, _clip: &PhysicalRegion) -> bool {
false
}
fn draw_texture(&mut self, _: &DrawTextureArgs, _clip: &PhysicalRegion) -> bool {
false
}
}