diff --git a/Cargo.lock b/Cargo.lock index 41f7737..e739fcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,15 +83,15 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64ct" -version = "1.5.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bit_field" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" [[package]] name = "bitflags" @@ -116,9 +116,9 @@ checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "bytemuck" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" [[package]] name = "byteorder" @@ -316,9 +316,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" dependencies = [ "cfg-if", "crossbeam-utils", @@ -326,9 +326,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -337,22 +337,22 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.13" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "memoffset 0.7.1", + "memoffset 0.8.0", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if", ] @@ -449,6 +449,27 @@ dependencies = [ "syn", ] +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "exr" version = "1.5.3" @@ -467,9 +488,9 @@ dependencies = [ [[package]] name = "fast_image_resize" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af227d67d842ef7a621199d7269bf81e190df04fcd82bc65c938b096168f4e7" +checksum = "a203b03e3b112cbea2080fef65b7fdbce9aa77e6379d167ca028f6379c852ab3" dependencies = [ "num-traits", "thiserror", @@ -493,7 +514,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -819,6 +840,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "io-lifetimes" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" +dependencies = [ + "libc", + "windows-sys 0.45.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -914,6 +945,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + [[package]] name = "lock_api" version = "0.4.9" @@ -950,9 +987,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af2c65375e552a67fe3829ca63e8a7c27a378a62824594f43b2851d682b5ec2" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" dependencies = [ "libc", ] @@ -968,9 +1005,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" dependencies = [ "autocfg", ] @@ -1411,15 +1448,6 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "resvg" version = "0.28.0" @@ -1441,16 +1469,16 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.35" +version = "0.8.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7495acf66551cdb696b7711408144bcd3194fc78e32f3a09e809bfe7dd4a7ce3" +checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" dependencies = [ "bytemuck", ] [[package]] name = "rmg" -version = "0.5.7" +version = "0.5.8" dependencies = [ "anyhow", "asefile", @@ -1495,6 +1523,20 @@ dependencies = [ "xmlparser", ] +[[package]] +name = "rustix" +version = "0.36.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + [[package]] name = "rustybuzz" version = "0.6.0" @@ -1654,9 +1696,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] @@ -1712,9 +1754,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.107" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -1723,9 +1765,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.27.7" +version = "0.27.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975fe381e0ecba475d4acff52466906d95b153a40324956552e027b2a9eaa89e" +checksum = "a902e9050fca0a5d6877550b769abd2bd1ce8c04634b941dbe2809735e1a1e33" dependencies = [ "cfg-if", "core-foundation-sys", @@ -1748,16 +1790,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" dependencies = [ "cfg-if", "fastrand", - "libc", "redox_syscall", - "remove_dir_all", - "winapi", + "rustix", + "windows-sys 0.42.0", ] [[package]] @@ -2230,6 +2271,21 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + [[package]] name = "windows-sys" version = "0.45.0" diff --git a/Cargo.toml b/Cargo.toml index d0b8eba..9112212 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rmg" edition = "2021" -version= "0.5.7" +version="0.5.9" authors = ["RSUU "] description = "Rust: Tiny And Fast Manga/Image Viewer" homepage = "https://crates.io/crates/rmg" @@ -55,7 +55,7 @@ gif-dispose = "4.0.0" image = "0.24.5" # window -minifb={version = "0.23.0",features = ["x11", "wayland"]} +minifb={version = "0.23.0",features = ["x11"],default-features = false} # config syn={version = "1.0.107",features = ["parsing", "extra-traits", "full"],default-features = false} @@ -81,6 +81,7 @@ ex_tar = ["dep:zip"] ex_zip = ["dep:tar"] sse4_1 = [] avx2 = [] +wayland=["minifb/wayland", "minifb/dlopen"] [[bench]] name = "bench_main" diff --git a/src/lib.rs b/src/lib.rs index 5ad3353..676afa5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,9 +3,14 @@ pub const FPS: u32 = 1000 / 25; pub const EXT_LIST: &[&str] = &[ "jpg", "jpeg", "png", "heic", "heif", "avif", "ase", "aseprite", "gif", "svg", ]; +pub const SLEEP_MS: u32 = 1000 / 120; // ========================================== pub mod archive; pub mod config; pub mod img; pub mod render; + +pub fn sleep() { + std::thread::sleep_ms(SLEEP_MS); +} diff --git a/src/render.rs b/src/render.rs index bd0fe3b..2c086a9 100644 --- a/src/render.rs +++ b/src/render.rs @@ -1,5 +1,3 @@ -// FIXME: can not free up memory - pub mod display; pub mod keymap; pub mod window; @@ -34,7 +32,7 @@ pub fn new_thread(arc_task: &AsyncTask, data: &Data) { let f = move || loop { if let Some(index) = arc_task.try_start(&data, &mut page) { - //tracing::info!("Thread: {:?} --- task: {index}", thread::current().id(),); + tracing::info!("Thread: {:?}, task: {index}", thread::current().id(),); } else { sleep_ms(100); } @@ -55,12 +53,25 @@ pub enum State { NeedFree, } -// TODO: #[derive(Debug, Clone)] pub enum Img { Init, - Bit(BitData), - Anim(AnimData), + Bit { + img: Frame, + size: Size, + resize: Size, + }, + Anim { + img: Frames, + size: Size, + resize: Size, + + frames_count: usize, // + frame_index: usize, // index of frame + pts: Vec, // + timer: u32, // + miss: u32, // + }, } #[derive(Debug, Clone, Copy, PartialEq)] @@ -158,7 +169,7 @@ pub struct PageList { #[derive(Debug)] pub struct Buffer { pub nums: usize, - pub data: Vec, + pub data: Frame, //scale:Scale, } @@ -176,7 +187,7 @@ pub trait ForAsyncTask { fn try_set_as_todo(&self, index: usize) -> bool; fn try_start(&self, data: &Data, tmp: &mut Page) -> Option; fn try_flush(&self, list: &mut PageList) -> bool; - fn try_free(&self, index: usize) -> bool; + fn try_free(&self, index: usize, list: &mut PageList) -> bool; } // ============================================== @@ -228,8 +239,6 @@ impl PageList { page.number = index; } - //tracing::debug!("list: {:?}", &list); - Self { list: list.to_owned(), cur_dir: std::env::current_dir().expect(""), @@ -271,7 +280,6 @@ impl Buffer { pub fn free(&mut self) { self.data.clear(); - self.data.truncate(0); } pub fn extend(&mut self, slice: &[u32]) { @@ -301,27 +309,21 @@ impl Page { } #[inline(always)] - pub fn flush(&self, buffer: &mut Vec) -> bool { - let slice = match self.img { - Img::Bit(ref bit) => bit.ref_data(), - Img::Anim(ref anim) => anim.ref_data(), - _ => return false, - }; + pub fn flush(&self, buffer: &mut Frame) -> bool { + let slice = self.img.ref_data(); if slice.is_empty() { - false - } else { - buffer.extend_from_slice(slice); - - true + return false; } + + buffer.extend_from_slice(slice); + + true } // =========================================== /// pub fn load_file(&mut self, data: &Data) -> anyhow::Result<()> { - // FIXME: free up memory - use crate::{ archive::{self, ForExtract}, img::*, @@ -393,17 +395,13 @@ impl Page { meta.resize(); self.img = match ImgType::from(&fmt) { - ImgType::Bit => Img::Bit(BitData::new( - Vec::with_capacity(buffer.len()), - meta.image, - meta.fix, - )), - ImgType::Anim => Img::Anim(AnimData::new( + ImgType::Bit => Img::new_bit(Vec::with_capacity(buffer.len()), meta.image, meta.fix), + ImgType::Anim => Img::new_anim( Vec::with_capacity(buffer.len() * buffer[0].len()), pts, meta.image, meta.fix, - )), + ), }; self.img.resize(&mut buffer, &data); @@ -419,14 +417,12 @@ impl ForAsyncTask for AsyncTask { } fn try_set_as_todo(&self, index: usize) -> bool { - if let Ok(mut inner) = self.try_write() { - if inner.get_ref(index).state == State::Empty { - inner.list[index].state = State::Todo; + let Ok(ref mut inner) = self.try_write() else {return false;}; - true - } else { - false - } + if inner.get_ref(index).state == State::Empty { + inner.list[index].state = State::Todo; + + true } else { false } @@ -450,93 +446,202 @@ impl ForAsyncTask for AsyncTask { }; let Some(index)=idx else {return None;}; - let mut count = 0; tmp.load_file(data).expect("ERROR: load_file()"); - while count < 5 { - if let Ok(ref mut inner) = self.try_write() { - //inner.ram_usage += tmp.img.len(); + if let Ok(ref mut inner) = self.try_write() { + //inner.ram_usage += tmp.img.len(); - let task = &mut inner.list[index]; + let task = &mut inner.list[index]; - mem::swap(&mut task.page, tmp); - task.state = State::Done; - *tmp = Page::default(); + mem::swap(&mut task.page, tmp); + task.state = State::Done; + *tmp = Page::default(); - return Some(task.page.number); - } else { - count += 1; - sleep_ms(10); - } + return Some(task.page.number); } None } fn try_flush(&self, list: &mut PageList) -> bool { - if let Ok(mut inner) = self.try_write() { - for (index, page) in list.list.iter_mut().enumerate() { - if inner.get_ref(index).state == State::Done { - inner.get_mut(index).state = State::Locked; + let Ok(ref mut inner) = self.try_write() else {return false;}; + + for (index, page) in list.list.iter_mut().enumerate() { + match inner.get_ref(index).state { + State::Done => { + inner.list[index].state = State::Locked; + // NOTE: free up the memory page.img = mem::take(&mut inner.list[index].page.img); } + + State::NeedFree => { + // NOTE: free up the memory + inner.list[index].page.img.free(); + inner.list[index].state = State::Empty + } + _ => {} } + } + + return true; + } + + fn try_free(&self, index: usize, list: &mut PageList) -> bool { + let Ok(ref mut inner) = self.try_write() else {return false;}; + + if inner.get_ref(index).state == State::Locked { + inner.list[index].state = State::NeedFree; + mem::swap(&mut inner.list[index].page.img, &mut list.list[index].img); true } else { false } } +} - fn try_free(&self, index: usize) -> bool { - if let Ok(mut inner) = self.try_write() { - if inner.get_ref(index).state == State::Locked { - inner.get_mut(index).state = State::Empty; - inner.get_mut(index).page.img.free(); +// ============================================== +impl From<&str> for ImgFormat { + fn from(value: &str) -> Self { + match value { + "jpg" => Self::Jpg, + "png" => Self::Png, + "heic" | "heif" => Self::Heic, + "avif" => Self::Avif, + "ase" | "aseprite" => Self::Aseprite, + "gif" => Self::Gif, + "svg" | "xml" => Self::Svg, + _ => Self::Unknown, + } + } +} - true - //tracing::debug!("free: {}", index); - } else { - false - } - } else { - false +impl From<&ImgFormat> for ImgType { + fn from(value: &ImgFormat) -> Self { + match value { + ImgFormat::Jpg => Self::Bit, + ImgFormat::Png => Self::Bit, + ImgFormat::Heic => Self::Bit, + ImgFormat::Avif => Self::Bit, + ImgFormat::Svg => Self::Bit, + + ImgFormat::Aseprite => Self::Anim, + ImgFormat::Gif => Self::Anim, + + ImgFormat::Unknown => panic!(), } } } +impl Default for Img { + fn default() -> Self { + Self::Init + } +} + impl Img { + pub fn new_bit(img: Frame, size: Size, resize: Size) -> Self { + Self::Bit { img, size, resize } + } + + pub fn new_anim(img: Frames, pts: Vec, size: Size, resize: Size) -> Self { + Self::Anim { + frames_count: img.len(), + frame_index: 0, + timer: 0, + miss: 0, + resize, + img, + size, + pts, + } + } + pub fn len(&self) -> usize { match *self { - Img::Bit(ref img) => img.ref_resize().len(), - Img::Anim(ref img) => img.ref_resize().len(), + Img::Bit { ref resize, .. } => resize.len(), + Img::Anim { ref resize, .. } => resize.len(), _ => 0, } } pub fn resize(&mut self, bytes: &mut Vec>, data: &Data) { - //tracing::debug!("{}", &bytes[0].len()); - //tracing::debug!("{:?}", self.ref_size()); - //tracing::debug!("{:?}", self.ref_resize()); + tracing::debug!("{}", &bytes[0].len()); + tracing::debug!("{:?}", self.ref_size()); + tracing::debug!("{:?}", self.ref_resize()); match *self { - Img::Bit(ref mut img) => img.resize(&mut bytes[0], &data.filter), - Img::Anim(ref mut img) => img.resize(bytes, &data), + Img::Bit { + ref mut img, + ref resize, + ref size, + .. + } => { + resize_rgba8(&mut bytes[0], size, resize, &data.filter).expect(""); + argb_u32(img, &mut bytes[0]); + } + Img::Anim { + ref mut img, + ref mut resize, + ref mut frames_count, + ref size, + .. + } => { + // anim + *img = vec![vec![]; bytes.len()]; + *frames_count = bytes.len(); + + if size.width > data.meta.window.width { + *resize = Size::new(data.meta.window.width, size.height); + + // WARN: unsafe + for (frame_index, frame) in bytes.iter_mut().enumerate() { + resize_rgba8(frame, &size, &resize, &data.filter).expect(""); + + argb_u32(&mut img[frame_index], &mem::take(frame)); + } + } else if size.width <= data.meta.window.width { + let offset = ((data.meta.window.width - size.width) / 2) as usize; + + //tracing::debug!( + // " + //window: {} + //anim: {} + //offset: {} + //", + // data.meta.window.width, + // size.width, + // offset + // ); + + let bg_size = &data.meta.window; + let fg_size = size; + + let mut fg_buffer: Frame = Vec::with_capacity(fg_size.len()); + + for (frame_index, frame) in bytes.iter_mut().enumerate() { + argb_u32(&mut fg_buffer, frame.as_slice()); + center_img(&mut img[frame_index], &fg_buffer, bg_size, fg_size, offset); + } + + *resize = *bg_size; + } + } _ => {} } } pub fn free(&mut self) { match *self { - Img::Bit(ref mut img) => { - img.data.clear(); - img.data.truncate(0); + Img::Bit { ref mut img, .. } => { + img.clear(); + img.shrink_to(0); } - Img::Anim(ref mut img) => { - img.data.clear(); - img.data.truncate(0); + Img::Anim { ref mut img, .. } => { + img.clear(); + img.shrink_to(0); } _ => {} } @@ -544,194 +649,69 @@ impl Img { pub fn ref_size(&self) -> &Size { match *self { - Img::Bit(ref img) => img.ref_size(), - Img::Anim(ref img) => img.ref_size(), - _ => unreachable!(), + Img::Bit { ref size, .. } => size, + Img::Anim { ref size, .. } => size, + _ => &Size { + width: 0, + height: 0, + }, } } pub fn ref_resize(&self) -> &Size { match *self { - Img::Bit(ref img) => img.ref_resize(), - Img::Anim(ref img) => img.ref_resize(), - _ => unreachable!(), + Img::Bit { ref resize, .. } => resize, + Img::Anim { ref resize, .. } => resize, + _ => &Size { + width: 0, + height: 0, + }, } } pub fn to_next_frame(&mut self) { match *self { - Img::Anim(ref mut img) => img.to_next_frame(), + Img::Anim { + ref img, + ref pts, + ref mut timer, + ref mut frame_index, + .. + } => { + let pts = pts[*frame_index]; + + if *timer >= pts { + *timer = timer.checked_sub(pts).unwrap_or(0); + + if *frame_index + 1 < img.len() { + *frame_index += 1; + } else { + // reset + *frame_index = 0; + } + } else { + *timer += FPS; + } + } _ => {} } } -} - -impl BitData { - pub fn new(data: Frame, size: Size, resize: Size) -> Self { - Self { size, data, resize } - } - - pub fn ref_data(&self) -> &[u32] { - self.data.as_slice() - } - - pub fn ref_size(&self) -> &Size { - &self.size - } - - pub fn ref_resize(&self) -> &Size { - &self.resize - } - - pub fn resize(&mut self, bytes: &mut Vec, filter: &fir::FilterType) { - resize_rgba8(bytes, &self.size, &self.resize, filter).expect(""); - argb_u32(&mut self.data, bytes); - } - - pub fn update(&mut self, data: Frame, size: Size, resize: Size) { - self.data = data; - self.size = size; - self.resize = resize; - } -} - -impl AnimData { - pub fn new(data: Frames, pts: Vec, size: Size, resize: Size) -> Self { - Self { - frames_count: data.len(), - frame_index: 0, - timer: 0, - miss: 0, - resize, - data, - size, - pts, - } - } pub fn ref_data(&self) -> &[u32] { - if self.data.is_empty() { - &[] - } else { - self.data[self.frame_index].as_slice() - } - } - - pub fn update(&mut self, data: Frames, size: Size, resize: Size) { - self.data = data; - self.size = size; - self.resize = resize; - } - - pub fn ref_size(&self) -> &Size { - &self.size - } - - pub fn ref_resize(&self) -> &Size { - &self.resize - } - - pub fn to_next_frame(&mut self) { - let pts = self.pts[self.frame_index]; - - if self.timer >= pts { - self.timer = self.timer.checked_sub(pts).unwrap_or(0); - - if self.frame_index + 1 < self.data.len() { - self.frame_index += 1; - } else { - // reset - self.frame_index = 0; - } - } else { - self.timer += FPS; - } - } - - pub fn resize(&mut self, bytes: &mut Vec>, data: &Data) { - // anim - self.data = vec![vec![]; bytes.len()]; - self.frames_count = bytes.len(); - - if self.size.width > data.meta.window.width { - self.resize = Size::new(data.meta.window.width, self.size.height); - - // WARN: unsafe - for (frame_index, frame) in bytes.iter_mut().enumerate() { - resize_rgba8(frame, &self.size, &self.resize, &data.filter).expect(""); - - argb_u32(&mut self.data[frame_index], &mem::take(frame)); - } - } else if self.size.width <= data.meta.window.width { - let offset = ((data.meta.window.width - self.size.width) / 2) as usize; - - //tracing::debug!( - // " - //window: {} - //anim: {} - //offset: {} - //", - // data.meta.window.width, - // self.size.width, - // offset - // ); - - let bg_size = &data.meta.window; - let fg_size = self.size; - - let mut fg_buffer: Vec = Vec::with_capacity(fg_size.len()); - - for (frame_index, frame) in bytes.iter_mut().enumerate() { - argb_u32(&mut fg_buffer, frame.as_slice()); - center_img( - &mut self.data[frame_index], - &mem::take(&mut fg_buffer), - bg_size, - &fg_size, - offset, - ); + match *self { + Img::Bit { ref img, .. } => img, + Img::Anim { + ref img, + ref frame_index, + .. + } => { + if img.is_empty() { + &[] + } else { + img[*frame_index].as_slice() + } } - - self.resize = *bg_size; - } - } -} - -// ============================================== -impl From<&str> for ImgFormat { - fn from(value: &str) -> Self { - match value { - "jpg" => Self::Jpg, - "png" => Self::Png, - "heic" | "heif" => Self::Heic, - "avif" => Self::Avif, - "ase" | "aseprite" => Self::Aseprite, - "gif" => Self::Gif, - "svg" | "xml" => Self::Svg, - _ => Self::Unknown, + Img::Init => &[], } } } - -impl From<&ImgFormat> for ImgType { - fn from(value: &ImgFormat) -> Self { - match value { - ImgFormat::Jpg => Self::Bit, - ImgFormat::Png => Self::Bit, - ImgFormat::Heic => Self::Bit, - ImgFormat::Avif => Self::Bit, - ImgFormat::Svg => Self::Bit, - - ImgFormat::Aseprite => Self::Anim, - ImgFormat::Gif => Self::Anim, - - ImgFormat::Unknown => panic!(), - } - } -} - -impl Default for Img { - fn default() -> Self { - Self::Init - } -} diff --git a/src/render/once.rs b/src/render/once.rs index 9b456d1..48dc8fb 100644 --- a/src/render/once.rs +++ b/src/render/once.rs @@ -2,55 +2,49 @@ use crate::{ render::{ keymap::{self, KeyMap, Map}, scroll::Scroll, - {Data, Page}, window::Canvas, + {Data, Page}, }, - FPS, + sleep, }; -use std::thread::sleep_ms; #[derive(Debug)] pub struct Once { - buffer_max: usize, - y_step: usize, + buffer: Vec, + buffer_size: usize, page: Page, page_loading: Vec, + + y_step: usize, + rng: usize, + bit_len: usize, } impl Once { pub fn from_scroll(scroll: Scroll) -> Self { Self { - buffer_max: scroll.buffer_max, + buffer_size: scroll.buffer_size, y_step: scroll.y_step, page: scroll.page_list.list[0].clone(), page_loading: scroll.page_loading, + rng: 0, + bit_len: 0, + buffer: vec![], } } pub fn start(&mut self, canvas: &mut Canvas, keymaps: &[KeyMap], data: &Data) { self.page.load_file(data).expect("ERROR: load_file()"); - - let mut buffer: Vec = vec![]; - let mut rng = 0; + self.bit_len = self.page.img.len(); 'l1: while canvas.window.is_open() { match keymap::match_event(canvas.window.get_keys().iter().as_slice(), keymaps) { Map::Down => { - // scrolling - if rng + self.y_step <= buffer.len() - self.buffer_max { - rng += self.y_step; - } else { - rng = buffer.len() - self.buffer_max; - }; + self.move_down(); } Map::Up => { - if rng >= self.y_step { - rng -= self.y_step; - } else { - // if (rng >= 0) - rng -= rng; - }; + self.move_up(); } Map::Exit => { @@ -62,21 +56,43 @@ impl Once { _ => {} } - buffer.clear(); - if self.page.flush(&mut buffer) { + self.buffer.clear(); + + if self.page.flush(&mut self.buffer) { self.page.img.to_next_frame(); - } else { - panic!(""); } - while buffer.len() < rng + self.buffer_max { - buffer.extend_from_slice(&self.page_loading); + while self.buffer.len() < self.end() { + self.buffer.extend_from_slice(&self.page_loading); } + self.buffer.clear(); + //self.buffer.shrink_to(0); - buffer.truncate(rng + self.buffer_max); - canvas.flush(&buffer[rng..rng + self.buffer_max]); + canvas.flush(&self.buffer[self.rng..self.end()]); - sleep_ms(6); + sleep() } } + + /// move down + fn move_down(&mut self) { + if self.bit_len >= self.end() + self.y_step { + self.rng += self.y_step; + } else if self.bit_len >= self.buffer_size { + self.rng = self.bit_len - self.buffer_size; + } + } + + /// move up + fn move_up(&mut self) { + if self.rng >= self.y_step { + self.rng -= self.y_step; + } else { + self.rng = 0; + } + } + + fn end(&self) -> usize { + self.rng + self.buffer_size + } } diff --git a/src/render/scroll.rs b/src/render/scroll.rs index 3e12486..5d9de7f 100644 --- a/src/render/scroll.rs +++ b/src/render/scroll.rs @@ -6,17 +6,16 @@ use crate::{ window::Canvas, {AsyncTask, Buffer, Data, ForAsyncTask, Img, Page, PageList}, }, - FPS, + sleep, }; -use std::thread::sleep_ms; #[derive(Debug)] pub struct Scroll { - pub buffer: Buffer, // - pub buffer_max: usize, // - pub bit_len: usize, // - pub mem_limit: usize, // - pub map: Map, // user input + pub buffer: Buffer, // + pub buffer_size: usize, // + pub buffer_limit: usize, // + pub bit_len: usize, // + pub map: Map, // user input pub cur: usize, // =0 pub rng: usize, // =0 @@ -37,7 +36,7 @@ impl Scroll { pub fn new( data: &Data, page_list: PageList, - buffer_max: usize, + buffer_size: usize, config: &Config, null_line_size: usize, ) -> Self { @@ -49,21 +48,10 @@ impl Scroll { sys.total_memory() as usize }; - let mut mem_limit = buffer_max * config.base.limit as usize; - - if mem_limit >= mem { - println!( - "WARN: mem_limit is {}, but total_memory is {}", - mem_limit, mem - ); - - mem_limit = mem / 2; - } - Self { buffer: Buffer::new(), - buffer_max, - mem_limit, + buffer_size, + buffer_limit: buffer_size * config.base.limit as usize, cur: 0, @@ -75,12 +63,12 @@ impl Scroll { map: Map::Down, page_list, - y_step: buffer_max / config.base.step as usize, // drop 1/step part of image once + y_step: buffer_size / config.base.step as usize, // drop 1/step part of image once x_step: data.meta.window.width as usize / config.base.step as usize, window_position: (0, 0), null_line_size, - page_loading: vec![TransRgba::rgba_as_argb_u32(&238, &238, &238, &128); buffer_max], + page_loading: vec![TransRgba::rgba_as_argb_u32(&238, &238, &238, &128); buffer_size], } } @@ -138,7 +126,7 @@ impl Scroll { self.flush(canvas, data, arc_task); self.map = Map::Stop; - sleep_ms(1000 / 120); + sleep(); } } @@ -149,20 +137,14 @@ impl Scroll { if let Some((_, y)) = canvas.window.get_scroll_wheel() { //tracing::trace!("mouse_y == {}", y); - if config.base.invert_mouse { - if y > 0.0 { - self.move_up(); - } else if y < 0.0 { - self.move_down(); - } else { - } - } else { - if y > 0.0 { - self.move_down(); - } else if y < 0.0 { - self.move_up(); - } else { - } + match config.base.invert_mouse { + true if y > 0.0 => self.move_up(), + true if y < 0.0 => self.move_down(), + + false if y > 0.0 => self.move_down(), + false if y < 0.0 => self.move_up(), + + _ => {} } } @@ -186,38 +168,38 @@ impl Scroll { #[inline(always)] fn flush(&mut self, canvas: &mut Canvas, data: &Data, arc_task: &AsyncTask) { if arc_task.try_flush(&mut self.page_list) { - //tracing::trace!("try_flush()"); + } else { + return; + } - self.buffer.free(); + if self.map == Map::Down { + self.load_next(arc_task); + self.free_head(arc_task); + } else if self.map == Map::Up { + self.load_prev(arc_task); + self.free_tail(arc_task); + } - for index in self.head..=self.tail { - if self.page_list.get_ref(index).flush(&mut self.buffer.data) { - self.page_list.get_mut(index).img.to_next_frame(); - } else if arc_task.try_set_as_todo(index) { - let mut n = self.page_list.get_ref(index).img.len() as isize; - - while n > 0 { - self.buffer - .extend(&self.page_loading[0..self.null_line_size]); - n -= self.null_line_size as isize - } - } - } + self.buffer.free(); - if self.map == Map::Down { - self.free_head(arc_task); - } else if self.map == Map::Up { - self.free_tail(arc_task); + for index in self.head..=self.tail { + let len = self.page_list.get_ref(index).img.len(); + + if self.page_list.get_ref(index).flush(&mut self.buffer.data) { + self.page_list.get_mut(index).img.to_next_frame(); + } else if arc_task.try_set_as_todo(index) { + for _ in 0..(len / self.null_line_size) { + self.buffer + .extend(&self.page_loading[0..self.null_line_size]); + } + } else { } - - self.try_load_page(arc_task); } while self.buffer.len() < self.end() { self.buffer .extend(&self.page_loading[0..self.null_line_size]); } - self.buffer.data.truncate(self.end()); canvas.flush(&self.buffer.data[self.rng..self.end()]); @@ -237,11 +219,10 @@ impl Scroll { fn move_down(&mut self) { self.map = Map::Down; - if self.end() + self.y_step <= self.bit_len { + if self.bit_len >= self.end() + self.y_step { self.rng += self.y_step; - } else if self.end() <= self.bit_len { - self.rng = self.bit_len - self.buffer_max; - } else { + } else if self.bit_len >= self.buffer_size { + self.rng = self.bit_len - self.buffer_size; } } @@ -259,10 +240,9 @@ impl Scroll { /// move left fn move_left(&mut self, data: &Data) { - // TODO: self.map = Map::Left; - // ??? How it works + // FIXME: if self.bit_len > self.end() + self.x_step && self.x_step <= data.meta.window.width as usize { self.rng += self.x_step; @@ -277,100 +257,70 @@ impl Scroll { fn move_right(&mut self, data: &Data) { self.map = Map::Right; + // FIXME: if self.rng >= self.x_step && self.x_step <= data.meta.window.width as usize { self.rng -= self.x_step; } else { } } + #[inline(always)] fn end(&self) -> usize { - self.rng + self.buffer_max + self.rng + self.buffer_size } fn free_head(&mut self, arc_task: &AsyncTask) { let page_len = self.page_list.get_ref(self.head).img.len(); - if self.bit_len >= self.mem_limit / 2 + page_len + if self.bit_len >= self.buffer_limit + page_len && self.tail > self.head && self.rng > page_len - && self.bit_len > page_len - && arc_task.try_free(self.head) + && arc_task.try_free(self.head, &mut self.page_list) { - self.rng -= page_len; - self.page_list.free(self.head); + tracing::info!("free head"); + + //self.page_list.free(self.head); self.head += 1; self.bit_len -= page_len; - - //tracing::info!("free head"); + self.rng -= page_len; } } fn free_tail(&mut self, arc_task: &AsyncTask) { let page_len = self.page_list.get_ref(self.tail).img.len(); - if self.bit_len >= self.mem_limit / 4 + if self.bit_len >= self.buffer_limit + page_len && self.tail > self.head && self.bit_len > page_len - && arc_task.try_free(self.tail) + && arc_task.try_free(self.tail, &mut self.page_list) { - self.page_list.free(self.tail); + tracing::info!("free tail"); + tracing::debug!(self.rng, self.bit_len, page_len); + + //self.page_list.free(self.tail); self.tail -= 1; self.bit_len -= page_len; - - //tracing::info!("free tail"); } } - fn try_load_page(&mut self, arc_task: &AsyncTask) { - //tracing::debug!( - // " - //{:?} - //bit_len: {} - //mem_limit: {} - //rng: {} - //", - // (self.head, self.tail), - // self.bit_len, - // self.mem_limit, - // self.rng, - // ); - - // head - // min: 0 - // max: tail - 1 - // tail - // min: head + 1 - // max: len - 1 - match self.map { - Map::Down => { - //tracing::trace!("down"); - - let page_len = self.page_list.get_ref(self.head).img.len(); - - if self.bit_len < self.mem_limit + page_len && self.tail + 1 < self.page_list.len() - { - self.tail += 1; - } - } - - Map::Up => { - //tracing::trace!("up"); + fn load_next(&mut self, arc_task: &AsyncTask) { + let page_len = self.page_list.get_ref(self.head).img.len(); - let page_len = self.page_list.get_ref(self.tail).img.len(); + if self.bit_len < self.buffer_limit + page_len && self.tail + 1 < self.page_list.len() { + self.tail += 1; + } + } - if self.bit_len < self.mem_limit + page_len && self.head > 0 { - self.head -= 1; - } - } + fn load_prev(&mut self, arc_task: &AsyncTask) { + let page_len = self.page_list.get_ref(self.tail).img.len(); - _ => {} + if self.bit_len < self.buffer_limit + page_len && self.head > 0 { + self.head -= 1; } } - pub fn load_from_mark(&mut self) { + pub fn load_from_mark(&mut self, cur: usize) { // TODO: - self.tail = self.cur; - self.head = self.tail - 1; } } diff --git a/src/render/turn.rs b/src/render/turn.rs index 0c233e1..2dc400b 100644 --- a/src/render/turn.rs +++ b/src/render/turn.rs @@ -3,8 +3,8 @@ use crate::{ render::{ keymap::{match_event, KeyMap, Map}, scroll::Scroll, - *, window::Canvas, + *, }, FPS, }; @@ -16,7 +16,7 @@ use std::{ #[derive(Debug)] pub struct Turn { pub buffer: Buffer, - pub buffer_max: usize, + pub buffer_size: usize, pub page_list: PageList, @@ -39,7 +39,7 @@ impl Turn { pub fn from_scroll(scroll: Scroll) -> Self { Self { buffer: Buffer::new(), - buffer_max: scroll.buffer_max, + buffer_size: scroll.buffer_size, page_list: scroll.page_list, cur: 1, map: Map::Stop, @@ -150,11 +150,11 @@ impl Turn { // } // } // - // while self.buffer.len() < self.rng + self.buffer_max { + // while self.buffer.len() < self.rng + self.buffer_size { // self.buffer.extend(&self.page_loading); // } // - // canvas.flush(&self.buffer.data[self.rng..self.rng + self.buffer_max]); + // canvas.flush(&self.buffer.data[self.rng..self.rng + self.buffer_size]); } /// move down @@ -162,8 +162,8 @@ impl Turn { fn move_down(&mut self) { self.map = Map::Down; - // buffer = &[rng..rng+buffer_max] - if self.rng + self.y_step <= self.buffer_max { + // buffer = &[rng..rng+buffer_size] + if self.rng + self.y_step <= self.buffer_size { self.rng += self.y_step; } else { } diff --git a/tests/other/config.rs b/tests/other/config.rs index 44b26fc..7b5d1df 100644 --- a/tests/other/config.rs +++ b/tests/other/config.rs @@ -1,12 +1,12 @@ fn main() { Base { size: (900, 900), - font: None, rename_pad: 6, invert_mouse: false, filter: "Hamming", - step: 5, - limit: 10, + step: 6, + limit: 5, + font: None, }; Keymap {