1
0
Fork 0
forked from wry/wry

autocommit 2022-01-28 19:46:23 CET

This commit is contained in:
Julian Orth 2022-01-28 19:46:23 +01:00
parent a5573b8a3a
commit b11a36729c
45 changed files with 1646 additions and 2171 deletions

View file

@ -2,13 +2,8 @@ mod consts;
include!(concat!(env!("OUT_DIR"), "/pixman_tys.rs"));
use crate::rect::Rect;
use crate::render::Border;
use crate::ClientMemError;
pub use consts::*;
use std::cell::Cell;
use std::ptr;
use thiserror::Error;
use uapi::c;
#[link(name = "pixman-1")]
@ -26,37 +21,6 @@ extern "C" {
fn pixman_region32_copy(dst: *mut Region, src: *const Region);
fn pixman_region32_union(dst: *mut Region, a: *const Region, b: *const Region);
fn pixman_region32_subtract(dst: *mut Region, a: *const Region, b: *const Region);
fn pixman_image_set_clip_region32(image: *mut PixmanImage, region: *const Region);
fn pixman_image_create_bits_no_clear(
format: PixmanFormat,
width: c::c_int,
height: c::c_int,
bits: *mut u32,
stride: c::c_int,
) -> *mut PixmanImage;
fn pixman_image_unref(image: *mut PixmanImage) -> c::c_int;
// fn pixman_image_ref(image: *mut PixmanImage) -> *mut PixmanImage;
fn pixman_image_fill_boxes(
op: PixmanOp,
dest: *mut PixmanImage,
color: *const Color,
nboxes: c::c_int,
boxes: *const Box32,
) -> c::c_int;
fn pixman_image_composite32(
op: PixmanOp,
src: *mut PixmanImage,
mask: *mut PixmanImage,
dest: *mut PixmanImage,
src_x: i32,
src_y: i32,
mask_x: i32,
mask_y: i32,
dest_x: i32,
dest_y: i32,
width: i32,
height: i32,
);
}
#[repr(C)]
@ -144,244 +108,3 @@ impl Drop for Region {
}
}
}
pub unsafe trait PixmanMemory: Clone {
type E;
fn access<T, F>(&self, f: F) -> Result<T, Self::E>
where
F: FnOnce(&[Cell<u8>]) -> T;
}
#[derive(Debug, Error)]
pub enum PixmanError {
#[error("The image size values cannot be represented in c_int")]
SizeOverflow,
#[error("The pixman memory does not contain enough memory to hold the image")]
InsufficientMemory,
#[error("The stride does not contain enough bytes to contain a row")]
RowOverflow,
#[error("Pixman images must be aligned at a 4 byte boundary")]
UnalignedMemory,
#[error("Internal pixman error")]
Internal,
#[error(transparent)]
ClientMemError(Box<ClientMemError>),
}
efrom!(PixmanError, ClientMemError, ClientMemError);
impl From<!> for PixmanError {
fn from(_: !) -> Self {
unreachable!()
}
}
struct PixmanImage;
pub struct Image<T> {
data: *mut PixmanImage,
width: u32,
height: u32,
memory: T,
clip: Cell<Option<Region>>,
}
impl<T: PixmanMemory> Image<T>
where
PixmanError: From<<T as PixmanMemory>::E>,
{
pub fn new(
memory: T,
format: Format,
width: u32,
height: u32,
stride: u32,
) -> Result<Self, PixmanError> {
let data = memory.access(|m| {
if format_bpp(format.raw()) as u64 * width as u64 > stride as u64 * 8 {
return Err(PixmanError::RowOverflow);
}
if (m.len() as u64) < height as u64 * stride as u64 {
return Err(PixmanError::InsufficientMemory);
}
let (width, height, stride) =
match (width.try_into(), height.try_into(), stride.try_into()) {
(Ok(w), Ok(h), Ok(s)) => (w, h, s),
_ => return Err(PixmanError::SizeOverflow),
};
if m.as_ptr() as usize % 4 != 0 {
return Err(PixmanError::UnalignedMemory);
}
let data = unsafe {
pixman_image_create_bits_no_clear(
format.raw() as _,
width,
height,
m.as_ptr() as _,
stride,
)
};
if data.is_null() {
return Err(PixmanError::Internal);
}
Ok(data)
})??;
Ok(Self {
data,
width,
height,
memory,
clip: Cell::new(None),
})
}
pub fn with_clip<F: FnOnce()>(&self, clip: Rect, f: F) {
let region = Region::rect(clip.x1(), clip.y1(), clip.width(), clip.height());
unsafe {
pixman_image_set_clip_region32(self.data, &region);
}
let region = self.clip.replace(Some(region));
f();
unsafe {
let region = region
.as_ref()
.map(|p| p as *const _)
.unwrap_or(ptr::null());
pixman_image_set_clip_region32(self.data, region);
}
self.clip.set(region);
}
pub fn fill(&self, r: u8, g: u8, b: u8, a: u8) -> Result<(), PixmanError> {
self.fill_rect(r, g, b, a, 0, 0, self.width as _, self.height as _)
}
#[allow(clippy::too_many_arguments)]
pub fn fill_rect(
&self,
r: u8,
g: u8,
b: u8,
a: u8,
x1: i32,
y1: i32,
x2: i32,
y2: i32,
) -> Result<(), PixmanError> {
self.memory.access(|_| {
let bx = Box32 {
x1: x1.max(0),
y1: y1.max(0),
x2: x2.min(self.width as i32),
y2: y2.min(self.height as i32),
};
let color = Color {
red: (r as u16) << 8,
green: (g as u16) << 8,
blue: (b as u16) << 8,
alpha: (a as u16) << 8,
};
unsafe {
pixman_image_fill_boxes(OP_SRC.raw() as PixmanOp, self.data, &color, 1, &bx);
}
})?;
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub fn fill_inner_border(
&self,
r: u8,
g: u8,
b: u8,
a: u8,
x1: i32,
y1: i32,
x2: i32,
y2: i32,
width: i32,
borders: Border,
) -> Result<(), PixmanError> {
self.memory.access(|_| {
let mut bx = [
Box32 { x1, y1, x2, y2: y1 },
Box32 { x1: x2, y1, x2, y2 },
Box32 { x1, y1, x2: x1, y2 },
Box32 { x1, y1: y2, x2, y2 },
];
if borders.contains(Border::TOP) {
bx[0].y2 += width;
}
if borders.contains(Border::RIGHT) {
bx[1].x1 -= width;
}
if borders.contains(Border::LEFT) {
bx[2].x2 += width;
}
if borders.contains(Border::BOTTOM) {
bx[3].y1 -= width;
}
for bx in &mut bx {
bx.x1 = bx.x1.max(0).min(self.width as i32);
bx.x2 = bx.x2.max(0).min(self.width as i32);
bx.y1 = bx.y1.max(0).min(self.height as i32);
bx.y2 = bx.y2.max(0).min(self.height as i32);
}
let color = Color {
red: (r as u16) << 8,
green: (g as u16) << 8,
blue: (b as u16) << 8,
alpha: (a as u16) << 8,
};
unsafe {
pixman_image_fill_boxes(
OP_SRC.raw() as PixmanOp,
self.data,
&color,
bx.len() as _,
bx.as_ptr(),
);
}
})?;
Ok(())
}
pub fn add_image<U>(&self, over: &Image<U>, x: i32, y: i32) -> Result<(), PixmanError>
where
U: PixmanMemory,
PixmanError: From<<U as PixmanMemory>::E>,
{
self.memory.access(|_| {
over.memory.access(|_| unsafe {
pixman_image_composite32(
OP_OVER.raw(),
over.data,
ptr::null_mut(),
self.data,
0,
0,
0,
0,
x,
y,
over.width as _,
over.height as _,
);
})
})??;
Ok(())
}
#[allow(dead_code)]
pub fn memory(&self) -> &T {
&self.memory
}
}
impl<T> Drop for Image<T> {
fn drop(&mut self) {
unsafe {
pixman_image_unref(self.data);
}
}
}