use std::sync::LazyLock;
use crate::ffi::{Handle, HandleStore};
pub static TRANSITIONS: LazyLock<HandleStore<Transition>> = LazyLock::new(HandleStore::new);
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TransitionType {
#[default]
None = 0,
Split = 1,
Blinds = 2,
Box = 3,
Wipe = 4,
Dissolve = 5,
Glitter = 6,
Fly = 7,
Push = 8,
Cover = 9,
Uncover = 10,
Fade = 11,
}
impl TransitionType {
pub fn from_i32(value: i32) -> Self {
match value {
0 => TransitionType::None,
1 => TransitionType::Split,
2 => TransitionType::Blinds,
3 => TransitionType::Box,
4 => TransitionType::Wipe,
5 => TransitionType::Dissolve,
6 => TransitionType::Glitter,
7 => TransitionType::Fly,
8 => TransitionType::Push,
9 => TransitionType::Cover,
10 => TransitionType::Uncover,
11 => TransitionType::Fade,
_ => TransitionType::None,
}
}
pub fn name(&self) -> &'static str {
match self {
TransitionType::None => "None",
TransitionType::Split => "Split",
TransitionType::Blinds => "Blinds",
TransitionType::Box => "Box",
TransitionType::Wipe => "Wipe",
TransitionType::Dissolve => "Dissolve",
TransitionType::Glitter => "Glitter",
TransitionType::Fly => "Fly",
TransitionType::Push => "Push",
TransitionType::Cover => "Cover",
TransitionType::Uncover => "Uncover",
TransitionType::Fade => "Fade",
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Default)]
pub struct Transition {
pub transition_type: TransitionType,
pub duration: f32,
pub vertical: i32,
pub outwards: i32,
pub direction: i32,
pub state0: i32,
pub state1: i32,
}
impl Transition {
pub fn new(transition_type: TransitionType, duration: f32) -> Self {
Self {
transition_type,
duration,
vertical: 0,
outwards: 0,
direction: 0,
state0: 0,
state1: 0,
}
}
pub fn split(duration: f32, vertical: bool, outwards: bool) -> Self {
Self {
transition_type: TransitionType::Split,
duration,
vertical: if vertical { 1 } else { 0 },
outwards: if outwards { 1 } else { 0 },
direction: 0,
state0: 0,
state1: 0,
}
}
pub fn blinds(duration: f32, vertical: bool) -> Self {
Self {
transition_type: TransitionType::Blinds,
duration,
vertical: if vertical { 1 } else { 0 },
outwards: 0,
direction: 0,
state0: 0,
state1: 0,
}
}
pub fn box_transition(duration: f32, outwards: bool) -> Self {
Self {
transition_type: TransitionType::Box,
duration,
vertical: 0,
outwards: if outwards { 1 } else { 0 },
direction: 0,
state0: 0,
state1: 0,
}
}
pub fn wipe(duration: f32, direction: i32) -> Self {
Self {
transition_type: TransitionType::Wipe,
duration,
vertical: 0,
outwards: 0,
direction,
state0: 0,
state1: 0,
}
}
pub fn dissolve(duration: f32) -> Self {
Self {
transition_type: TransitionType::Dissolve,
duration,
vertical: 0,
outwards: 0,
direction: 0,
state0: 0,
state1: 0,
}
}
pub fn glitter(duration: f32, direction: i32) -> Self {
Self {
transition_type: TransitionType::Glitter,
duration,
vertical: 0,
outwards: 0,
direction,
state0: 0,
state1: 0,
}
}
pub fn fly(duration: f32, direction: i32, outwards: bool) -> Self {
Self {
transition_type: TransitionType::Fly,
duration,
vertical: 0,
outwards: if outwards { 1 } else { 0 },
direction,
state0: 0,
state1: 0,
}
}
pub fn push(duration: f32, direction: i32) -> Self {
Self {
transition_type: TransitionType::Push,
duration,
vertical: 0,
outwards: 0,
direction,
state0: 0,
state1: 0,
}
}
pub fn cover(duration: f32, direction: i32) -> Self {
Self {
transition_type: TransitionType::Cover,
duration,
vertical: 0,
outwards: 0,
direction,
state0: 0,
state1: 0,
}
}
pub fn uncover(duration: f32, direction: i32) -> Self {
Self {
transition_type: TransitionType::Uncover,
duration,
vertical: 0,
outwards: 0,
direction,
state0: 0,
state1: 0,
}
}
pub fn fade(duration: f32) -> Self {
Self {
transition_type: TransitionType::Fade,
duration,
vertical: 0,
outwards: 0,
direction: 0,
state0: 0,
state1: 0,
}
}
}
pub fn generate_transition_frame(
tpix: &mut [u8],
opix: &[u8],
npix: &[u8],
width: i32,
height: i32,
n: i32,
time: i32,
trans: &Transition,
) -> bool {
if tpix.len() != opix.len() || opix.len() != npix.len() {
return false;
}
let t = time.clamp(0, 256) as f32 / 256.0;
let components = n as usize;
match trans.transition_type {
TransitionType::None => {
tpix.copy_from_slice(if time >= 128 { npix } else { opix });
}
TransitionType::Fade => {
for i in 0..tpix.len() {
let old_val = opix[i] as f32;
let new_val = npix[i] as f32;
tpix[i] = (old_val * (1.0 - t) + new_val * t) as u8;
}
}
TransitionType::Dissolve => {
let threshold = (t * 255.0) as u8;
let stride = (width as usize) * components;
for y in 0..height as usize {
for x in 0..width as usize {
let idx = y * stride + x * components;
let hash = ((x * 7919 + y * 6271) % 256) as u8;
let use_new = hash < threshold;
for c in 0..components {
tpix[idx + c] = if use_new {
npix[idx + c]
} else {
opix[idx + c]
};
}
}
}
}
TransitionType::Wipe => {
let direction = trans.direction;
let stride = (width as usize) * components;
for y in 0..height as usize {
for x in 0..width as usize {
let idx = y * stride + x * components;
let pixel_t = match direction {
0 | 360 => x as f32 / width as f32, 90 => (height as usize - 1 - y) as f32 / height as f32, 180 => (width as usize - 1 - x) as f32 / width as f32, 270 => y as f32 / height as f32, _ => x as f32 / width as f32, };
let use_new = pixel_t < t;
for c in 0..components {
tpix[idx + c] = if use_new {
npix[idx + c]
} else {
opix[idx + c]
};
}
}
}
}
TransitionType::Split => {
let stride = (width as usize) * components;
let hw = width as f32 / 2.0;
let hh = height as f32 / 2.0;
for y in 0..height as usize {
for x in 0..width as usize {
let idx = y * stride + x * components;
let pixel_t = if trans.vertical != 0 {
let dist = (y as f32 - hh).abs() / hh;
if trans.outwards != 0 {
dist
} else {
1.0 - dist
}
} else {
let dist = (x as f32 - hw).abs() / hw;
if trans.outwards != 0 {
dist
} else {
1.0 - dist
}
};
let use_new = pixel_t < t;
for c in 0..components {
tpix[idx + c] = if use_new {
npix[idx + c]
} else {
opix[idx + c]
};
}
}
}
}
TransitionType::Blinds => {
let stride = (width as usize) * components;
let num_blinds = 10;
for y in 0..height as usize {
for x in 0..width as usize {
let idx = y * stride + x * components;
let blind_pos = if trans.vertical != 0 {
(x as f32 / width as f32 * num_blinds as f32) % 1.0
} else {
(y as f32 / height as f32 * num_blinds as f32) % 1.0
};
let use_new = blind_pos < t;
for c in 0..components {
tpix[idx + c] = if use_new {
npix[idx + c]
} else {
opix[idx + c]
};
}
}
}
}
TransitionType::Box => {
let stride = (width as usize) * components;
let hw = width as f32 / 2.0;
let hh = height as f32 / 2.0;
for y in 0..height as usize {
for x in 0..width as usize {
let idx = y * stride + x * components;
let dx = (x as f32 - hw).abs() / hw;
let dy = (y as f32 - hh).abs() / hh;
let dist = dx.max(dy);
let pixel_t = if trans.outwards != 0 {
1.0 - dist
} else {
dist
};
let use_new = pixel_t < t;
for c in 0..components {
tpix[idx + c] = if use_new {
npix[idx + c]
} else {
opix[idx + c]
};
}
}
}
}
TransitionType::Glitter => {
let stride = (width as usize) * components;
let direction = trans.direction;
for y in 0..height as usize {
for x in 0..width as usize {
let idx = y * stride + x * components;
let diag = match direction {
0 | 360 => (x + y) as f32 / (width + height) as f32,
90 => (x + (height as usize - y)) as f32 / (width + height) as f32,
180 => {
((width as usize - x) + (height as usize - y)) as f32
/ (width + height) as f32
}
270 => ((width as usize - x) + y) as f32 / (width + height) as f32,
_ => (x + y) as f32 / (width + height) as f32,
};
let hash = ((x * 7919 + y * 6271) % 64) as f32 / 256.0;
let pixel_t = diag + hash * 0.1;
let use_new = pixel_t < t;
for c in 0..components {
tpix[idx + c] = if use_new {
npix[idx + c]
} else {
opix[idx + c]
};
}
}
}
}
TransitionType::Push | TransitionType::Cover | TransitionType::Uncover => {
let stride = (width as usize) * components;
let direction = trans.direction;
let (dx, dy) = match direction {
0 | 360 => ((t * width as f32) as i32, 0), 90 => (0, (t * height as f32) as i32), 180 => (-((t * width as f32) as i32), 0), 270 => (0, -((t * height as f32) as i32)), _ => ((t * width as f32) as i32, 0),
};
for y in 0..height as usize {
for x in 0..width as usize {
let idx = y * stride + x * components;
let (src_new, src_old) = match trans.transition_type {
TransitionType::Push => {
let nx = (x as i32 - dx).clamp(0, width - 1) as usize;
let ny = (y as i32 - dy).clamp(0, height - 1) as usize;
let ox = (x as i32 + (width - dx.abs())).clamp(0, width - 1) as usize;
let oy = (y as i32 + (height - dy.abs())).clamp(0, height - 1) as usize;
((nx, ny), (ox, oy))
}
TransitionType::Cover => {
let nx = (x as i32 - dx).clamp(0, width - 1) as usize;
let ny = (y as i32 - dy).clamp(0, height - 1) as usize;
((nx, ny), (x, y))
}
TransitionType::Uncover => {
let ox = (x as i32 + dx).clamp(0, width - 1) as usize;
let oy = (y as i32 + dy).clamp(0, height - 1) as usize;
((x, y), (ox, oy))
}
_ => ((x, y), (x, y)),
};
let show_new = match direction {
0 | 360 => (x as i32) < dx,
90 => (y as i32) < dy,
180 => (x as i32) >= (width + dx),
270 => (y as i32) >= (height + dy),
_ => (x as i32) < dx,
};
let src_idx = if show_new {
src_new.1 * stride + src_new.0 * components
} else {
src_old.1 * stride + src_old.0 * components
};
for c in 0..components {
tpix[idx + c] = if show_new {
npix.get(src_idx + c).copied().unwrap_or(0)
} else {
opix.get(src_idx + c).copied().unwrap_or(0)
};
}
}
}
}
TransitionType::Fly => {
let stride = (width as usize) * components;
let scale = if trans.outwards != 0 {
1.0 - t * 0.5 } else {
0.5 + t * 0.5 };
let center_x = width as f32 / 2.0;
let center_y = height as f32 / 2.0;
for y in 0..height as usize {
for x in 0..width as usize {
let idx = y * stride + x * components;
let sx = center_x + (x as f32 - center_x) / scale;
let sy = center_y + (y as f32 - center_y) / scale;
let in_bounds =
sx >= 0.0 && sx < width as f32 && sy >= 0.0 && sy < height as f32;
if trans.outwards != 0 {
if in_bounds {
let src_idx = (sy as usize) * stride + (sx as usize) * components;
let blend = (1.0 - t).clamp(0.0, 1.0);
for c in 0..components {
let old_val = opix.get(src_idx + c).copied().unwrap_or(0) as f32;
let new_val = npix[idx + c] as f32;
tpix[idx + c] = (old_val * blend + new_val * (1.0 - blend)) as u8;
}
} else {
for c in 0..components {
tpix[idx + c] = npix[idx + c];
}
}
} else {
if in_bounds && t > 0.1 {
let src_idx = (sy as usize) * stride + (sx as usize) * components;
let blend = t.clamp(0.0, 1.0);
for c in 0..components {
let old_val = opix[idx + c] as f32;
let new_val = npix.get(src_idx + c).copied().unwrap_or(0) as f32;
tpix[idx + c] = (old_val * (1.0 - blend) + new_val * blend) as u8;
}
} else {
for c in 0..components {
tpix[idx + c] = opix[idx + c];
}
}
}
}
}
}
}
true
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_transition(transition_type: i32, duration: f32) -> Handle {
let trans = Transition::new(TransitionType::from_i32(transition_type), duration);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_split_transition(duration: f32, vertical: i32, outwards: i32) -> Handle {
let trans = Transition::split(duration, vertical != 0, outwards != 0);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_blinds_transition(duration: f32, vertical: i32) -> Handle {
let trans = Transition::blinds(duration, vertical != 0);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_box_transition(duration: f32, outwards: i32) -> Handle {
let trans = Transition::box_transition(duration, outwards != 0);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_wipe_transition(duration: f32, direction: i32) -> Handle {
let trans = Transition::wipe(duration, direction);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_dissolve_transition(duration: f32) -> Handle {
let trans = Transition::dissolve(duration);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_glitter_transition(duration: f32, direction: i32) -> Handle {
let trans = Transition::glitter(duration, direction);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_fly_transition(duration: f32, direction: i32, outwards: i32) -> Handle {
let trans = Transition::fly(duration, direction, outwards != 0);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_push_transition(duration: f32, direction: i32) -> Handle {
let trans = Transition::push(duration, direction);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_cover_transition(duration: f32, direction: i32) -> Handle {
let trans = Transition::cover(duration, direction);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_uncover_transition(duration: f32, direction: i32) -> Handle {
let trans = Transition::uncover(duration, direction);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_new_fade_transition(duration: f32) -> Handle {
let trans = Transition::fade(duration);
TRANSITIONS.insert(trans)
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_drop_transition(_ctx: Handle, trans: Handle) {
TRANSITIONS.remove(trans);
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_generate_transition(
_ctx: Handle,
tpix: Handle,
opix: Handle,
npix: Handle,
time: i32,
trans: Handle,
) -> i32 {
let transition = match TRANSITIONS.get(trans) {
Some(t) => t.lock().unwrap().clone(),
None => return 0,
};
let tpix_arc = match crate::ffi::PIXMAPS.get(tpix) {
Some(p) => p,
None => return 0,
};
let opix_arc = match crate::ffi::PIXMAPS.get(opix) {
Some(p) => p,
None => return 0,
};
let npix_arc = match crate::ffi::PIXMAPS.get(npix) {
Some(p) => p,
None => return 0,
};
let mut tpix_guard = tpix_arc.lock().unwrap();
let opix_guard = opix_arc.lock().unwrap();
let npix_guard = npix_arc.lock().unwrap();
if tpix_guard.w() != opix_guard.w()
|| tpix_guard.w() != npix_guard.w()
|| tpix_guard.h() != opix_guard.h()
|| tpix_guard.h() != npix_guard.h()
|| tpix_guard.n() != opix_guard.n()
|| tpix_guard.n() != npix_guard.n()
{
return 0;
}
let width = tpix_guard.w();
let height = tpix_guard.h();
let n = tpix_guard.n();
let tpix_samples = tpix_guard.samples_mut();
let opix_samples = opix_guard.samples();
let npix_samples = npix_guard.samples();
if generate_transition_frame(
tpix_samples,
opix_samples,
npix_samples,
width,
height,
n,
time,
&transition,
) {
1
} else {
0
}
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_transition_type(trans: Handle) -> i32 {
if let Some(t) = TRANSITIONS.get(trans) {
t.lock().unwrap().transition_type as i32
} else {
0
}
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_transition_duration(trans: Handle) -> f32 {
if let Some(t) = TRANSITIONS.get(trans) {
t.lock().unwrap().duration
} else {
0.0
}
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_transition_set_duration(trans: Handle, duration: f32) {
if let Some(t) = TRANSITIONS.get(trans) {
t.lock().unwrap().duration = duration;
}
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_transition_vertical(trans: Handle) -> i32 {
if let Some(t) = TRANSITIONS.get(trans) {
t.lock().unwrap().vertical
} else {
0
}
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_transition_set_vertical(trans: Handle, vertical: i32) {
if let Some(t) = TRANSITIONS.get(trans) {
t.lock().unwrap().vertical = vertical;
}
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_transition_outwards(trans: Handle) -> i32 {
if let Some(t) = TRANSITIONS.get(trans) {
t.lock().unwrap().outwards
} else {
0
}
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_transition_set_outwards(trans: Handle, outwards: i32) {
if let Some(t) = TRANSITIONS.get(trans) {
t.lock().unwrap().outwards = outwards;
}
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_transition_direction(trans: Handle) -> i32 {
if let Some(t) = TRANSITIONS.get(trans) {
t.lock().unwrap().direction
} else {
0
}
}
#[unsafe(no_mangle)]
pub extern "C" fn fz_transition_set_direction(trans: Handle, direction: i32) {
if let Some(t) = TRANSITIONS.get(trans) {
t.lock().unwrap().direction = direction;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_transition_type_from_i32() {
assert_eq!(TransitionType::from_i32(0), TransitionType::None);
assert_eq!(TransitionType::from_i32(1), TransitionType::Split);
assert_eq!(TransitionType::from_i32(5), TransitionType::Dissolve);
assert_eq!(TransitionType::from_i32(11), TransitionType::Fade);
assert_eq!(TransitionType::from_i32(99), TransitionType::None);
}
#[test]
fn test_transition_type_name() {
assert_eq!(TransitionType::None.name(), "None");
assert_eq!(TransitionType::Fade.name(), "Fade");
assert_eq!(TransitionType::Dissolve.name(), "Dissolve");
}
#[test]
fn test_new_transition() {
let trans = fz_new_transition(TransitionType::Fade as i32, 1.5);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Fade as i32);
assert!((fz_transition_duration(trans) - 1.5).abs() < 0.01);
fz_drop_transition(0, trans);
}
#[test]
fn test_split_transition() {
let trans = fz_new_split_transition(2.0, 1, 0);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Split as i32);
assert_eq!(fz_transition_vertical(trans), 1);
assert_eq!(fz_transition_outwards(trans), 0);
fz_drop_transition(0, trans);
}
#[test]
fn test_blinds_transition() {
let trans = fz_new_blinds_transition(1.0, 0);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Blinds as i32);
assert_eq!(fz_transition_vertical(trans), 0);
fz_drop_transition(0, trans);
}
#[test]
fn test_box_transition() {
let trans = fz_new_box_transition(1.5, 1);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Box as i32);
assert_eq!(fz_transition_outwards(trans), 1);
fz_drop_transition(0, trans);
}
#[test]
fn test_wipe_transition() {
let trans = fz_new_wipe_transition(1.0, 90);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Wipe as i32);
assert_eq!(fz_transition_direction(trans), 90);
fz_drop_transition(0, trans);
}
#[test]
fn test_dissolve_transition() {
let trans = fz_new_dissolve_transition(2.0);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Dissolve as i32);
fz_drop_transition(0, trans);
}
#[test]
fn test_glitter_transition() {
let trans = fz_new_glitter_transition(1.5, 45);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Glitter as i32);
fz_drop_transition(0, trans);
}
#[test]
fn test_fly_transition() {
let trans = fz_new_fly_transition(1.0, 0, 1);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Fly as i32);
assert_eq!(fz_transition_outwards(trans), 1);
fz_drop_transition(0, trans);
}
#[test]
fn test_push_transition() {
let trans = fz_new_push_transition(0.5, 180);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Push as i32);
assert_eq!(fz_transition_direction(trans), 180);
fz_drop_transition(0, trans);
}
#[test]
fn test_cover_transition() {
let trans = fz_new_cover_transition(0.75, 270);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Cover as i32);
fz_drop_transition(0, trans);
}
#[test]
fn test_uncover_transition() {
let trans = fz_new_uncover_transition(0.75, 90);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Uncover as i32);
fz_drop_transition(0, trans);
}
#[test]
fn test_fade_transition() {
let trans = fz_new_fade_transition(1.0);
assert!(trans > 0);
assert_eq!(fz_transition_type(trans), TransitionType::Fade as i32);
fz_drop_transition(0, trans);
}
#[test]
fn test_set_duration() {
let trans = fz_new_fade_transition(1.0);
fz_transition_set_duration(trans, 2.5);
assert!((fz_transition_duration(trans) - 2.5).abs() < 0.01);
fz_drop_transition(0, trans);
}
#[test]
fn test_set_direction() {
let trans = fz_new_wipe_transition(1.0, 0);
fz_transition_set_direction(trans, 180);
assert_eq!(fz_transition_direction(trans), 180);
fz_drop_transition(0, trans);
}
#[test]
fn test_all_transition_types() {
let transitions = vec![
fz_new_transition(0, 1.0), fz_new_transition(1, 1.0), fz_new_transition(2, 1.0), fz_new_transition(3, 1.0), fz_new_transition(4, 1.0), fz_new_transition(5, 1.0), fz_new_transition(6, 1.0), fz_new_transition(7, 1.0), fz_new_transition(8, 1.0), fz_new_transition(9, 1.0), fz_new_transition(10, 1.0), fz_new_transition(11, 1.0), ];
for (i, trans) in transitions.iter().enumerate() {
assert!(*trans > 0);
assert_eq!(fz_transition_type(*trans), i as i32);
fz_drop_transition(0, *trans);
}
}
#[test]
fn test_generate_transition_frame_fade() {
let width = 4;
let height = 4;
let n = 4;
let mut tpix = vec![0u8; (width * height * n) as usize];
let opix = vec![255u8; (width * height * n) as usize]; let npix = vec![0u8; (width * height * n) as usize];
let trans = Transition::fade(1.0);
let result =
generate_transition_frame(&mut tpix, &opix, &npix, width, height, n, 128, &trans);
assert!(result);
let expected = 127; assert!((tpix[0] as i32 - expected as i32).abs() < 5);
}
#[test]
fn test_generate_transition_frame_none() {
let width = 2;
let height = 2;
let n = 4;
let mut tpix = vec![0u8; (width * height * n) as usize];
let opix = vec![100u8; (width * height * n) as usize];
let npix = vec![200u8; (width * height * n) as usize];
let trans = Transition::new(TransitionType::None, 0.0);
let result =
generate_transition_frame(&mut tpix, &opix, &npix, width, height, n, 64, &trans);
assert!(result);
assert_eq!(tpix[0], 100);
let result =
generate_transition_frame(&mut tpix, &opix, &npix, width, height, n, 192, &trans);
assert!(result);
assert_eq!(tpix[0], 200);
}
#[test]
fn test_generate_transition_frame_mismatched_sizes() {
let mut tpix = vec![0u8; 16];
let opix = vec![0u8; 8];
let npix = vec![0u8; 16];
let trans = Transition::fade(1.0);
let result = generate_transition_frame(&mut tpix, &opix, &npix, 2, 2, 4, 128, &trans);
assert!(!result);
}
#[test]
fn test_fz_generate_transition_invalid_handles() {
assert_eq!(fz_generate_transition(0, 0, 0, 0, 128, 0), 0);
}
#[test]
fn test_fz_transition_type_invalid() {
assert_eq!(fz_transition_type(0), 0);
}
#[test]
fn test_fz_transition_duration_invalid() {
assert_eq!(fz_transition_duration(0), 0.0);
}
#[test]
fn test_fz_transition_set_duration_invalid() {
fz_transition_set_duration(0, 2.0);
}
#[test]
fn test_fz_transition_vertical_invalid() {
assert_eq!(fz_transition_vertical(0), 0);
}
#[test]
fn test_fz_transition_set_vertical_invalid() {
fz_transition_set_vertical(0, 1);
}
#[test]
fn test_fz_transition_outwards_invalid() {
assert_eq!(fz_transition_outwards(0), 0);
}
#[test]
fn test_fz_transition_set_outwards_invalid() {
fz_transition_set_outwards(0, 1);
}
#[test]
fn test_fz_transition_direction_invalid() {
assert_eq!(fz_transition_direction(0), 0);
}
#[test]
fn test_fz_transition_set_direction_invalid() {
fz_transition_set_direction(0, 90);
}
#[test]
fn test_generate_transition_frame_dissolve() {
let width = 4;
let height = 4;
let n = 4;
let mut tpix = vec![0u8; (width * height * n) as usize];
let opix = vec![255u8; (width * height * n) as usize];
let npix = vec![0u8; (width * height * n) as usize];
let trans = Transition::dissolve(1.0);
let result =
generate_transition_frame(&mut tpix, &opix, &npix, width, height, n, 128, &trans);
assert!(result);
}
#[test]
fn test_generate_transition_frame_wipe() {
let width = 4;
let height = 4;
let n = 4;
let mut tpix = vec![0u8; (width * height * n) as usize];
let opix = vec![255u8; (width * height * n) as usize];
let npix = vec![0u8; (width * height * n) as usize];
let trans = Transition::wipe(1.0, 0);
let result =
generate_transition_frame(&mut tpix, &opix, &npix, width, height, n, 128, &trans);
assert!(result);
}
#[test]
fn test_generate_transition_frame_split() {
let width = 4;
let height = 4;
let n = 4;
let mut tpix = vec![0u8; (width * height * n) as usize];
let opix = vec![255u8; (width * height * n) as usize];
let npix = vec![0u8; (width * height * n) as usize];
let trans = Transition::split(1.0, false, false);
let result =
generate_transition_frame(&mut tpix, &opix, &npix, width, height, n, 128, &trans);
assert!(result);
}
#[test]
fn test_generate_transition_frame_blinds() {
let width = 4;
let height = 4;
let n = 4;
let mut tpix = vec![0u8; (width * height * n) as usize];
let opix = vec![255u8; (width * height * n) as usize];
let npix = vec![0u8; (width * height * n) as usize];
let trans = Transition::blinds(1.0, false);
let result =
generate_transition_frame(&mut tpix, &opix, &npix, width, height, n, 128, &trans);
assert!(result);
}
#[test]
fn test_generate_transition_frame_box() {
let width = 4;
let height = 4;
let n = 4;
let mut tpix = vec![0u8; (width * height * n) as usize];
let opix = vec![255u8; (width * height * n) as usize];
let npix = vec![0u8; (width * height * n) as usize];
let trans = Transition::box_transition(1.0, false);
let result =
generate_transition_frame(&mut tpix, &opix, &npix, width, height, n, 128, &trans);
assert!(result);
}
#[test]
fn test_fz_transition_invalid_handle() {
assert_eq!(fz_transition_type(0), 0);
assert_eq!(fz_transition_duration(0), 0.0);
assert_eq!(fz_transition_vertical(0), 0);
assert_eq!(fz_transition_outwards(0), 0);
assert_eq!(fz_transition_direction(0), 0);
fz_drop_transition(0, 0);
fz_transition_set_direction(0, 1);
}
}