From 7a99bc23b0c0208de659a592735b2e05b5e14554 Mon Sep 17 00:00:00 2001 From: RSUU Date: Sun, 18 Dec 2022 11:28:52 +0800 Subject: [PATCH] misc --- Cargo.lock | 2 +- Cargo.toml | 49 +- README.md | 26 +- docs/BUG.md | 3 + examples/heic.rs | 7 +- examples/minifb_rgba.rs | 54 --- src/archive/dir.rs | 43 +- src/archive/tar.rs | 4 +- src/color/format.rs | 5 - src/color/rgba.rs | 21 +- src/config/rsconf.rs | 9 +- src/img/resize.rs | 72 ++- src/img/size.rs | 18 +- src/lib.rs | 3 +- src/main.rs | 45 +- src/reader/display.rs | 324 ++++--------- src/reader/once.rs | 77 +++ src/reader/scroll.rs | 810 ++++++++++++++++++------------- src/reader/turn.rs | 191 +++++++- src/reader/view.rs | 215 ++++++-- src/reader/window.rs | 1 + src/utils/cli.rs | 47 +- src/utils/file.rs | 15 +- tests/{files => anim}/ase/00.ase | Bin tests/{files => anim}/ase/01.ase | Bin tests/{files => anim}/ase/02.ase | Bin tests/{files => bit}/avif/0.avif | Bin tests/{files => bit}/heic/1.heic | Bin tests/{files => bit}/png/1.png | Bin tests/{files => bit}/png/2.jpg | Bin tests/{files => bit}/png/2.png | Bin tests/{files => bit}/svg/0.svg | 0 tests/files/config.rs | 6 +- 33 files changed, 1196 insertions(+), 851 deletions(-) create mode 100644 docs/BUG.md delete mode 100644 examples/minifb_rgba.rs create mode 100644 src/reader/once.rs rename tests/{files => anim}/ase/00.ase (100%) rename tests/{files => anim}/ase/01.ase (100%) rename tests/{files => anim}/ase/02.ase (100%) rename tests/{files => bit}/avif/0.avif (100%) rename tests/{files => bit}/heic/1.heic (100%) rename tests/{files => bit}/png/1.png (100%) rename tests/{files => bit}/png/2.jpg (100%) rename tests/{files => bit}/png/2.png (100%) rename tests/{files => bit}/svg/0.svg (100%) diff --git a/Cargo.lock b/Cargo.lock index c284687..9ff1032 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1405,7 +1405,7 @@ dependencies = [ [[package]] name = "rmg" -version = "0.3.0" +version = "0.4.0" dependencies = [ "asefile", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 85bde24..bc10503 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rmg" -version = "0.3.0" +version = "0.4.0" edition = "2021" authors = ["RSUU "] description = "Rust: Tiny And Fast Manga/Image Viewer" @@ -91,62 +91,21 @@ de_svg= ["dep:usvg","dep:tiny-skia","dep:resvg"] [profile.release] -strip = true -codegen-units = 1 -debug = false -debug-assertions = false -incremental = false -lto = true +lto = "thin" opt-level = 3 -overflow-checks = false -panic = "abort" - - -[profile.dev.package.asefile] -strip = true codegen-units = 1 -debug = false -debug-assertions = false -incremental = false -opt-level = 3 -overflow-checks = false - - -[profile.dev.package.fast_image_resize] strip = true -codegen-units = 1 debug = false debug-assertions = false incremental = false -opt-level = 3 overflow-checks = false +panic = "abort" -[profile.dev.package.image] -strip = true -codegen-units = 1 -debug = false -debug-assertions = false -incremental = false +[profile.release.package."*"] opt-level = 3 -overflow-checks = false - - -[profile.dev.package.gif] -strip = true codegen-units = 1 -debug = false -debug-assertions = false -incremental = false -opt-level = 3 -overflow-checks = false - - -[profile.dev.package.gif-dispose] strip = true -codegen-units = 1 debug = false debug-assertions = false incremental = false -opt-level = 3 -overflow-checks = false diff --git a/README.md b/README.md index b350c32..c165fae 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,13 @@ cargo build --release ## Usage ```bash -rmg ./tests/files/img.tar +rmg file.tar -# OR -rmg --size 600,600 ./tests/files/img.tar +rmg --size 600,600 file.tar -# OR -rmg --size 600,600 --config ./tests/files/config.rs ./tests/files/img.tar +rmg --size 600,600 --config ./tests/files/config.rs file.tar + +rmg file.gif ``` ### KeyMap @@ -67,14 +67,14 @@ q | quit ## Supported formats -| Format | Supported | Default |Dependency -|:-|:-|:-|:-| -.jpg |โœ… | โœ…| -.png|โœ…| โœ…| -.heic / .avif|๐Ÿ”ฌ|โŒ|libheif -.gif|๐Ÿ”ฌ|โœ…| -.aseprite|๐Ÿ”ฌ|โŒ| -.svg|๐Ÿ”ฌ|โŒ| +| Format | Supported | Default |Dependency | Mode +|:-|:-|:-|:-|:-| +.jpg |โœ… | โœ…||Scroll/Once +.png|โœ…| โœ…||Scroll/Once +.heic / .avif|๐Ÿ”ฌ|โŒ|libheif|Scroll/Once +.gif|๐Ÿ”ฌ|โœ…||Once +.aseprite|๐Ÿ”ฌ|โŒ||Once +.svg|๐Ÿ”ฌ|โŒ||Scroll/Once --- | Format | Supported | Default |Dependency diff --git a/docs/BUG.md b/docs/BUG.md new file mode 100644 index 0000000..273d087 --- /dev/null +++ b/docs/BUG.md @@ -0,0 +1,3 @@ +infer svg + +gif OOM diff --git a/examples/heic.rs b/examples/heic.rs index 2cff3a3..d24066b 100644 --- a/examples/heic.rs +++ b/examples/heic.rs @@ -1,9 +1,8 @@ use cfg_if::cfg_if; fn main() { - cfg_if! { - // decode heic - if #[cfg(feature="de_heic")] { + cfg_if! { // decode heic + if #[cfg(feature="de_heic")] { // cg ex heic -F de_heic use libheif_rs; @@ -61,7 +60,7 @@ where let rgb = yuv_to_rgb(img[y].into(), img[u].into(), img[v].into()); - res[idx + 0] = rgb[0]; + res[idx] = rgb[0]; res[idx + 1] = rgb[1]; res[idx + 2] = rgb[2]; } diff --git a/examples/minifb_rgba.rs b/examples/minifb_rgba.rs deleted file mode 100644 index 6b6e044..0000000 --- a/examples/minifb_rgba.rs +++ /dev/null @@ -1,54 +0,0 @@ - -use image::io::Reader as ImageReader; - -use minifb::{Scale, ScaleMode, Window}; - -fn main() { - // Read source image from file - let img = ImageReader::open("./tests/2.png") - .unwrap() - .decode() - .unwrap(); - let _rgb = img.to_rgb8().into_vec(); - let rgba = img.to_rgba8().into_vec(); - //println!("rgb: {:?}", &rgb[..]); - //println!("rgba: {:?}", &rgba[..]); - - let windowoptions = minifb::WindowOptions { - borderless: false, - transparency: false, - title: true, - resize: false, - topmost: false, - none: true, - scale_mode: ScaleMode::Center, - scale: Scale::X1, - }; - - let mut window = Window::new("rmg", 428, 400, windowoptions).unwrap(); - - window.limit_update_rate(Some(std::time::Duration::from_micros(16600))); // Limit to max ~60 fps update rate - - // NOTE: ARGB - let mut buffer = Vec::new(); - for f in (0..rgba.len()).step_by(4) { - buffer.push(argb_to_u32(&rgba[f..f + 4].try_into().unwrap())); - } - - loop { - window - .update_with_buffer(buffer.as_slice(), 428, 400) - .unwrap(); - - std::thread::sleep(std::time::Duration::from_millis(40)); - } -} - -pub fn argb_to_u32(rgba: &[u8; 4]) -> u32 { - let a = (rgba[3] as u32) << 8 * 3; - let r = (rgba[0] as u32) << 8 * 2; - let g = (rgba[1] as u32) << 8 * 1; - let b = (rgba[2] as u32) << 8 * 0; - - r + g + b + a -} diff --git a/src/archive/dir.rs b/src/archive/dir.rs index 8c6a8d9..781094d 100644 --- a/src/archive/dir.rs +++ b/src/archive/dir.rs @@ -16,21 +16,27 @@ pub fn load_file(path: impl AsRef) -> Res> { } pub fn load_dir(path: impl AsRef, pos: usize) -> Res> { - for (idx, tmp) in walkdir::WalkDir::new(path.as_ref()).into_iter().enumerate() { - if pos == idx { - let mut buffer = Vec::new(); - let mut file = OpenOptions::new() - .read(true) - .write(false) - .create(false) - .open(tmp?.path())?; - - file.read_to_end(&mut buffer)?; - - // done - return Ok(buffer); + let mut idx = 0; + + for tmp in walkdir::WalkDir::new(path.as_ref()).into_iter() { + if tmp.as_ref().unwrap().file_type().is_file() { + if pos == idx { + let mut buffer = Vec::new(); + let mut file = OpenOptions::new() + .read(true) + .write(false) + .create(false) + .open(tmp?.path())?; + + file.read_to_end(&mut buffer)?; + + log::debug!("{},{}", idx, pos); + // done + return Ok(buffer); + } else { + idx += 1; + } } else { - // to next } } @@ -39,9 +45,14 @@ pub fn load_dir(path: impl AsRef, pos: usize) -> Res> { pub fn get_file_list(path: impl AsRef) -> Res> { let mut list = Vec::new(); + let mut idx = 0; - for (idx, file) in walkdir::WalkDir::new(path.as_ref()).into_iter().enumerate() { - list.push((file?.path().to_str().unwrap().to_string(), idx)); + for file in walkdir::WalkDir::new(path.as_ref()).into_iter() { + if file.as_ref().unwrap().file_type().is_file() { + list.push((file?.path().to_str().unwrap().to_string(), idx)); + idx += 1; + } else { + } } Ok(list) diff --git a/src/archive/tar.rs b/src/archive/tar.rs index 94441bc..de5ef87 100644 --- a/src/archive/tar.rs +++ b/src/archive/tar.rs @@ -6,7 +6,7 @@ use std::{ pub fn load_file(path: &Path, idx: usize) -> Res> { cfg_if::cfg_if! { if #[cfg(feature = "ex_tar")] { - feat::load_file(path.as_ref(), idx) + feat::load_file(path, idx) } else { Err(MyErr::FeatTar) } @@ -33,7 +33,7 @@ pub fn load_file(path: &Path, idx: usize) -> Res> { pub fn get_file_list(path: &Path) -> Res> { cfg_if::cfg_if! { if #[cfg(feature = "ex_tar")] { - feat::get_file_list(path.as_ref()) + feat::get_file_list(path) } else { Err( MyErr::FeatTar) } diff --git a/src/color/format.rs b/src/color/format.rs index 259416c..e69de29 100644 --- a/src/color/format.rs +++ b/src/color/format.rs @@ -1,5 +0,0 @@ -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum PixelFormat { - Rgb8, - Rgba8, -} diff --git a/src/color/rgba.rs b/src/color/rgba.rs index a8190b8..1762abb 100644 --- a/src/color/rgba.rs +++ b/src/color/rgba.rs @@ -26,40 +26,25 @@ impl TransRgba { // (rgba & 0x0ff) as u8, // ]; - // SAFETY + // SAFETY: unsafe { std::mem::transmute::(rgba.to_be()) } } } -// trait ExtRgba { -// fn as_u32(&self) -> u32; -// } -// -// impl ExtRgba for rgb::RGBA8 { -// #[inline(always)] -// fn as_u32(&self) -> u32 { -// let r = (self.r as u32) << 24; -// let g = (self.g as u32) << 16; -// let b = (self.b as u32) << 8; -// let a = self.a as u32; -// -// r + g + b + a -// } -// } - mod test { - use super::TransRgba; #[test] fn _rgba_as_argb_u32() {} #[test] fn _rgba_as_u32() { + use crate::color::rgba::TransRgba; assert_eq!(16909060, TransRgba::rgba_as_u32(&1, &2, &3, &4)); } #[test] fn _rgba_from_u32() { + use crate::color::rgba::TransRgba; assert_eq!([1_u8, 2, 3, 4], TransRgba::rgba_from_u32(&16909060)); } } diff --git a/src/config/rsconf.rs b/src/config/rsconf.rs index d521540..a335420 100644 --- a/src/config/rsconf.rs +++ b/src/config/rsconf.rs @@ -52,7 +52,13 @@ pub struct Keymap { pub left: Char_, // move to left pub right: Char_, // move to right pub exit: Char_, // exit - // pub fullscreen: Char_, + pub fullscreen: Char_, +} + +#[derive(Debug)] +pub struct Image { + pub resize_anim: bool, + pub resize_bit: bool, } #[derive(Debug)] @@ -100,6 +106,7 @@ impl Default for Keymap { left: 'h', right: 'l', exit: 'q', + fullscreen: 'f', } } } diff --git a/src/img/resize.rs b/src/img/resize.rs index 1b00fb3..bc1a2f7 100644 --- a/src/img/resize.rs +++ b/src/img/resize.rs @@ -5,10 +5,8 @@ use crate::{ }; use cfg_if::cfg_if; use fir; - use std::num::NonZeroU32; -#[inline(always)] pub fn resize_rgba8( bytes: Vec, meta: &MetaSize, @@ -44,11 +42,66 @@ pub fn resize_rgba8( alpha_mul_div.divide_alpha_inplace(&mut dst_view)?; // - Ok(dst_image.buffer().to_vec()) } -#[inline(always)] +pub fn center_img(bg: &mut Vec, fg: &[u32], bw: usize, fw: usize, fh: usize, offset: usize) { + *bg = vec![0; bw * fh]; + + let mut idx_fg = 0; + let mut idx_bg = 0; + + for y in 0..fh { + idx_fg = (fw * y); + idx_bg = (bw * y) + offset; + + for x in 0..fw { + bg[idx_bg + x] = fg[idx_fg + x]; + } + } +} + +pub fn crop_img2(img: &[u32], offset: usize, iw: usize, ih: usize, ow: usize) -> Vec { + let mut buffer = vec![0; ow * ih]; + + let mut i = 0; + let mut o = 0; + + for y in 0..ih { + i = (iw * y) + offset; + o = (ow * y); + + for x in 0..ow { + buffer[o + x] = img[i + x]; + } + } + + buffer +} + +pub fn crop_img( + buffer: &mut Vec, + img: &[u32], + offset: usize, + iw: usize, + ih: usize, + ow: usize, +) { + *buffer = vec![0; ow * ih]; + + let mut i = 0; + let mut o = 0; + + for y in 0..ih { + i = (iw * y) + offset; + o = (ow * y); + + for x in 0..ow { + buffer[o + x] = img[i + x]; + } + } +} + pub fn argb_u32(buffer: &mut Vec, bytes: &[u8]) { *buffer = vec![0; bytes.len() / 4]; @@ -57,3 +110,14 @@ pub fn argb_u32(buffer: &mut Vec, bytes: &[u8]) { TransRgba::rgba_as_argb_u32(&bytes[f], &bytes[f + 1], &bytes[f + 2], &bytes[f + 3]); } } + +pub fn rgba_u32(buffer: &mut Vec, bytes: &[u8]) { + *buffer = vec![0; bytes.len() / 4]; + + for (idx, f) in (0..bytes.len()).step_by(4).enumerate() { + buffer[idx] = + TransRgba::rgba_as_u32(&bytes[f], &bytes[f + 1], &bytes[f + 2], &bytes[f + 3]); + } +} + +pub fn yuv420_u32() {} diff --git a/src/img/size.rs b/src/img/size.rs index 02382a0..8710b57 100644 --- a/src/img/size.rs +++ b/src/img/size.rs @@ -28,13 +28,11 @@ impl TMetaSize for MetaSize { fn resize(&mut self) { // WARN: DO NOT use odd numbers. (โ•ฏยฐะ”ยฐ)โ•ฏ๏ธต โ”ปโ”โ”ป - // if - // width = 3, height = 4 - // do - // width = (width/2) * 2 = (3/2) * 2 = 1 * 2 = 2 - // height = (height/2) * 2 = (4/2) * 2 = 2 * 2 = 4 - let w = self.window.width as f32; + // e.g. width = 3, height = 4 + // width = (width /2)*2 = 2 + // height = (height/2)*2 = 4 let q = self.image.width as f32 / self.image.height as f32; + let w = self.window.width as f32; let h = w / q; self.fix.width = (w as Self::T / 2) * 2; @@ -52,4 +50,12 @@ impl Size { pub fn new(width: T, height: T) -> Self { Size { width, height } } + + pub fn len(&self) -> usize + where + T: TryInto + Copy, + T::Error: std::fmt::Debug, + { + self.width.try_into().unwrap() * self.height.try_into().unwrap() + } } diff --git a/src/lib.rs b/src/lib.rs index f15681b..e36e2c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -use std::path::Path; + pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const FPS: u64 = 40; // 1000/25 @@ -84,6 +84,7 @@ pub mod reader { pub mod view; pub mod window; + pub mod once; pub mod scroll; pub mod turn; } diff --git a/src/main.rs b/src/main.rs index 54d20d8..839a868 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -use log; use rmg::{ archive::{self, ArchiveType}, config::rsconf::Config, @@ -6,7 +5,7 @@ use rmg::{ reader::{display, view::Page}, utils::{cli, err::MyErr, file}, }; -use simple_logger; + use std::path::Path; fn main() { @@ -15,7 +14,7 @@ fn main() { let mut args = cli::Args::new(); let mut config: Config = args.init_config(); - args.parse(&mut config).unwrap_or_else(|_| panic!()); + args.parse(&mut config).unwrap_or_else(|_| todo!()); log::debug!("Args: {:#?}", args); log::debug!("Config: {:#?}", config); @@ -31,20 +30,24 @@ fn main() { log::debug!("meta_size: {:#?}", &meta_size); - let Some(path) = &config.cli.file_path else { -todo!() - }; + let Some(path) = &config.cli.file_path else { rmg::utils::cli::print_help() }; println!("Open: {}", path.as_str()); - let file_list = get_file_list(path.as_str()).unwrap(); let archive_type = get_archive_type(path.as_str()); - let page_list = get_page_list(&file_list, config.base.rename_pad as usize); + let file_list = get_file_list(path.as_str()).unwrap(); + let mut page_list = get_page_list(&file_list, config.base.rename_pad as usize); log::debug!("file_list: {:#?}", file_list); log::debug!("page_list: {:#?}", page_list); - match display::cat_img(&config, page_list, meta_size, path.as_str(), archive_type) { + match display::cat_img( + &config, + &mut page_list, + meta_size, + path.as_str(), + archive_type, + ) { Ok(_) => { std::process::exit(0); } @@ -85,35 +88,29 @@ where pub fn get_page_list(file_list: &[(String, usize)], rename_pad: usize) -> Vec { let mut page_list = Vec::new(); - let mut number = 0; for (path, pos) in file_list.iter() { if rmg::utils::file::has_supported(AsRef::::as_ref(path.as_str())) { let page = if rename_pad == 0 { - Page::new(path.clone(), number, *pos) + Page::new(path.clone(), *pos) } else { // rename - Page::new(file::pad_name(rename_pad, path.as_str()), number, *pos) + Page::new(file::pad_name(rename_pad, path.as_str()), *pos) }; page_list.push(page); - number += 1; } else { // skip } } - page_list.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap()); - - log::debug!("sort: page_list: {:#?}", page_list.as_slice()); - page_list } pub fn get_file_list(path: impl AsRef) -> Result, ()> { if path.as_ref().is_dir() { let file_list = archive::dir::get_file_list(path.as_ref()).unwrap(); - return Ok(file_list); + Ok(file_list) } else { match file::get_filetype(path.as_ref()).as_str() { "tar" => { @@ -121,14 +118,14 @@ pub fn get_file_list(path: impl AsRef) -> Result, ()> return Err(()); }; - return Ok(file_list); + Ok(file_list) } "zip" => { if let Ok(file_list) = archive::zip::get_file_list(path.as_ref()) { - return Ok(file_list); + Ok(file_list) } else { - return Err(()); + Err(()) } } @@ -142,12 +139,12 @@ pub fn get_file_list(path: impl AsRef) -> Result, ()> == rmg::reader::view::ImgFormat::Unknown { // unsupport - return Err(()); + Err(()) } else { // Only one file. return Ok(vec![(path.as_ref().display().to_string(), 0)]); } } - }; - }; + } + } } diff --git a/src/reader/display.rs b/src/reader/display.rs index e3cd4f5..ed83623 100644 --- a/src/reader/display.rs +++ b/src/reader/display.rs @@ -3,29 +3,26 @@ use crate::{ config::rsconf::Config, img::size::MetaSize, reader::{ - keymap::{self, Map}, - scroll::{Render, State}, - view::{Buffer, Page, ViewMode}, + keymap::KeyMap, + once::Once, + scroll::{self, Scroll, State}, + turn::Turn, + view::{ArcTmpBuffer, Check, Data, ImgType, Page, PageList, ViewMode}, window::Canvas, }, utils::err::Res, - FPS, }; use log::{debug, info}; use std::{ - ops::Sub, path::PathBuf, sync::{Arc, RwLock}, }; -use super::scroll::{self, ExtData}; - /// display images pub fn cat_img( config: &Config, - page_list: Vec, + page_list: &mut Vec, meta_size: MetaSize, - //_metadata: &Option, path: &str, archive_type: ArchiveType, ) -> Res<()> { @@ -34,38 +31,60 @@ pub fn cat_img( let buffer_max = window_size.width as usize * window_size.height as usize; let step = config.base.step as usize; - let filter = config.base.filter; - let keymaps = keymap::KeyMap::new(); - let mut buf = Render::new( - page_list, + let keymaps = KeyMap::new(); + + let mut canvas = Canvas::new(window_size.width as usize, window_size.height as usize); + + let data = Data::new( archive_type, - path, - buffer_max, - step, + PathBuf::from(path), screen_size, window_size, - config.base.view_mode, - filter, - ); - let mut canvas = Canvas::new(window_size.width as usize, window_size.height as usize); + config.base.filter, + ); // use for resize image + + let arc_state = Arc::new(RwLock::new(State::Nothing)); + let arc_buffer = ArcTmpBuffer::new_arc(); + + page_list.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap()); + + let mut page_list = PageList::new(page_list.to_owned()); + + for (idx, page) in page_list.list.iter_mut().enumerate() { + page.number = idx; + } + + let mut scroll = Scroll::new(&data, page_list, buffer_max, step, config.base.view_mode); - buf.init(); // init + init(&mut scroll, &data); // init - match buf.view_mode { + match scroll.view_mode { // Bit ViewMode::Scroll => { - for_minifb_scroll(config, &mut buf, &mut canvas, &keymaps); + Scroll::start( + config, + &mut scroll, + &mut canvas, + &keymaps, + &data, + &arc_state, + &arc_buffer, + ); } // Bit OR Anim - ViewMode::Image => { - for_minifb_image(config, &mut buf, &mut canvas, &keymaps); + ViewMode::Once => { + // TODO: scale gif? + Once::start(&mut scroll, &mut canvas, &keymaps); } // Bit OR Anim - ViewMode::Page => { - for_minifb_page(config, &mut buf, &mut canvas, &keymaps); + ViewMode::Turn => { + todo!(); + + //let mut turn = Turn::from_scroll(scroll); + //turn.start(&mut canvas, &keymaps); } } @@ -74,224 +93,71 @@ pub fn cat_img( Ok(()) } -pub fn for_minifb_page( - _config: &Config, - _buf: &mut Render, - _canvas: &mut Canvas, - _keymaps: &[keymap::KeyMap], -) { - todo!() -} - -pub fn for_minifb_image( - _config: &Config, - buf: &mut Render, - canvas: &mut Canvas, - keymaps: &[keymap::KeyMap], -) { - let mut time_start = std::time::Instant::now(); - let mut sleep = FPS; - - let end = buf.page_list[0].size(); - - buf.buffer.data = vec![0; buf.buffer_max]; - - 'l1: while canvas.window.is_open() { - match keymap::match_event(canvas.window.get_keys().iter().as_slice(), keymaps) { - Map::Down => { - // scrolling - if buf.rng + buf.y_step <= end { - buf.rng += buf.y_step; - } else if buf.rng <= end { - buf.rng = end - buf.rng; - } else { - unreachable!() - } - } +/// +pub fn init(scroll: &mut Scroll, data: &Data) { + let mut tmp = (0, 0); - Map::Up => { - if buf.rng >= buf.y_step { - buf.rng -= buf.y_step; - } else if buf.rng >= 0 { - buf.rng -= buf.rng; - } else { - unreachable!() - }; - } + let mut len = 0; + let mut anim_count = 0; - Map::Exit => { - println!("EXIT"); + scroll.head = 1; + scroll.tail = 0; - // BUG: Miss Key::Escape - break 'l1; - } + debug!("{:#?}", &scroll.page_list.list); - _ => {} + // [Head, 1, 2, Tail] + match scroll.page_list.len() { + 0..=2 => { + panic!() } - buf.buffer.data = vec![0; buf.buffer_max]; - buf.buffer.data.copy_from_slice(buf.page_list[0].data()); - buf.page_list[0].to_next_frame(); - - canvas.flush(&buf.buffer.data[buf.rng..buf.rng + buf.buffer_max]); - - let now = std::time::Instant::now(); - let count = (now - time_start).as_millis() as u64; - - time_start = now; - sleep = FPS.checked_sub(count / 6).unwrap_or(10); - - std::thread::sleep(std::time::Duration::from_millis(sleep)); - } -} - -pub fn for_minifb_scroll( - config: &Config, - buf: &mut Render, - canvas: &mut Canvas, - keymaps: &[keymap::KeyMap], -) { - let arc_state = Arc::new(RwLock::new(State::Nothing)); - let arc_extdata = Arc::new(RwLock::new(ExtData::new( - buf.archive_type.clone(), - buf.archive_path.clone(), - buf.screen_size.clone(), - buf.window_size.clone(), - buf.filter.clone(), - ))); // use for resize image - - let arc_state_main = arc_state.clone(); - let arc_extdata_main = arc_extdata.clone(); - - let arc_state_thread = arc_state.clone(); - let arc_extdata_thread = arc_extdata.clone(); - - // new thread for resize image - let _thread_for_resize_image = new_thread(arc_state_thread, arc_extdata_thread); - - let mut time_start = std::time::Instant::now(); - let mut sleep = FPS; - - 'l1: while canvas.window.is_open() { - match keymap::match_event(canvas.window.get_keys().iter().as_slice(), keymaps) { - Map::Down => { - buf.move_down(&arc_state_main, &arc_extdata_main); - } - - Map::Up => { - buf.move_up(&arc_state_main, &arc_extdata_main); - } - - Map::Reset => { - todo!() - } - - Map::FullScreen => { - todo!() - } + 3 => { + scroll.view_mode = ViewMode::Once; + tmp = load_next(scroll, data); + return; + } - Map::Left => { - buf.move_left(); + _ => { + while len <= scroll.mem_limit && scroll.not_tail() { + scroll.tail += 1; + tmp = load_next(scroll, data); + len += tmp.0; + anim_count += tmp.1; } - Map::Right => { - buf.move_right(); - } + debug!("{}", scroll.tail); + } + } - Map::Exit => { - println!("EXIT"); + if anim_count >= 1 { + // TODO: + scroll.view_mode = ViewMode::Turn; + return; + } - // TODO: Key::Escape - break 'l1; - } + if len < scroll.buffer_max { + todo!() + } - _ => { - // input from mouse - if config.base.invert_mouse { - if let Some((_x, y)) = canvas.window.get_scroll_wheel() { - if y > 0.0 { - buf.move_up(&arc_state_main, &arc_extdata_main); - } else if y < 0.0 { - buf.move_down(&arc_state_main, &arc_extdata_main); - } else { - } - - debug!("mouse_y == {}", y); - } - } else if let Some((_x, y)) = canvas.window.get_scroll_wheel() { - if y > 0.0 { - buf.move_down(&arc_state_main, &arc_extdata_main); - } else if y < 0.0 { - buf.move_up(&arc_state_main, &arc_extdata_main); - } else { - } - - debug!("mouse_y == {}", y); - } - } - } + debug!(" len = {}", len); +} - buf.flush(canvas, &arc_state); +pub fn load_next(scroll: &mut Scroll, data: &Data) -> (usize, usize) { + let tail = scroll.page_list.get_mut(scroll.tail); + let pos = tail.pos; - let now = std::time::Instant::now(); - let count = (now - time_start).as_millis() as u64; + let (ty, mut buffer, format) = + scroll::load_file(&data.archive_type, data.path.as_path(), pos).unwrap(); + let (meta, pts) = + scroll::load_img(&format, &mut buffer, &data.screen_size, &data.window_size).unwrap(); - time_start = now; - sleep = FPS.checked_sub(count / 6).unwrap_or(10); + tail.ty = ty; + tail.resize = meta.fix; + tail.pts = pts; - std::thread::sleep(std::time::Duration::from_millis(sleep)); - } -} + scroll::resize_page(tail, &mut buffer, &meta, &data.filter, &data.window_size); -pub fn new_thread(arc_state: Arc>, arc_extdata: Arc>) { - std::thread::spawn(move || { - loop { - if let Ok(mut arc_state) = arc_state.try_write() { - match *arc_state { - State::LoadNext | State::LoadPrev => { - if let Ok(mut arc_extdata) = arc_extdata.try_write() { - let (ty, mut buffer, format) = scroll::load_file( - arc_extdata.archive_type.clone(), - arc_extdata.path.clone().as_path(), - arc_extdata.pos, - ) - .unwrap(); - - let (meta, pts) = scroll::load_img( - format, - &mut buffer, - arc_extdata.screen_size, - arc_extdata.window_size, - ) - .unwrap(); - - arc_extdata.page.ty = ty; - arc_extdata.page.resize = meta.fix; - arc_extdata.page.pts = pts; - - let f = arc_extdata.filter.clone(); - - scroll::resize_page(&mut arc_extdata.page, &mut buffer, &meta, &f); - - *arc_state = match *arc_state { - State::LoadPrev => State::DonePrev, - State::LoadNext => State::DoneNext, - _ => { - unreachable!() - } - } - } else { - // wait - } - } - _ => {} - } - } else { - // wait - } + tail.is_ready = true; - // limit CPU usage - std::thread::sleep(std::time::Duration::from_millis(10)); - } - }); + (tail.len(), (tail.ty == ImgType::Anim) as usize) } diff --git a/src/reader/once.rs b/src/reader/once.rs new file mode 100644 index 0000000..a8c4a6d --- /dev/null +++ b/src/reader/once.rs @@ -0,0 +1,77 @@ +use crate::{ + reader::{ + keymap::{self, KeyMap, Map}, + scroll::Scroll, + window::Canvas, + }, + FPS, +}; + +#[derive(Debug)] +pub struct Once {} + +impl Once { + pub fn start(tmp: &mut Scroll, canvas: &mut Canvas, keymaps: &[KeyMap]) { + let mut time_start = std::time::Instant::now(); + let mut sleep = FPS; + + let buffer_max = tmp.buffer_max; + let y_step = tmp.y_step; + let _end = tmp.end(); + let mut rng = 0; + let page = tmp.page_list.get_mut(0); + let size = page.size(); + + let mut buffer = if size > buffer_max { + vec![0; size] + } else { + vec![0; buffer_max] + }; + + 'l1: while canvas.window.is_open() { + match keymap::match_event(canvas.window.get_keys().iter().as_slice(), keymaps) { + Map::Down => { + // scrolling + if rng + y_step <= buffer.len() - buffer_max { + rng += y_step; + } else { + rng = buffer.len() - buffer_max; + }; + } + + Map::Up => { + if rng >= y_step { + rng -= y_step; + } else { + // if (rng >= 0) + rng -= rng; + }; + } + + Map::Exit => { + println!("EXIT"); + + // BUG: Miss Key::Escape + break 'l1; + } + + _ => {} + } + + for (idx, data) in page.data().iter().enumerate() { + buffer[idx] = *data; + } + + canvas.flush(&buffer[rng..rng + buffer_max]); + page.to_next_frame(); + + let now = std::time::Instant::now(); + let count = (now - time_start).as_millis() as u64; + + time_start = now; + sleep = FPS.checked_sub(count / 6).unwrap_or(10); + + std::thread::sleep(std::time::Duration::from_millis(sleep)); + } + } +} diff --git a/src/reader/scroll.rs b/src/reader/scroll.rs index 3304c17..95b5bec 100644 --- a/src/reader/scroll.rs +++ b/src/reader/scroll.rs @@ -1,12 +1,14 @@ use crate::{ archive::{self, ArchiveType}, + config::rsconf::Config, img::{ ase, gif, heic, resize, size::{MetaSize, Size, TMetaSize}, + svg, }, reader::{ - keymap::Map, - view::{Buffer, ImgFormat, ImgType, Page, ViewMode}, + keymap::{self, KeyMap, Map}, + view::{ArcTmpBuffer, Buffer, Check, Data, ImgFormat, ImgType, Page, PageList, ViewMode}, window::Canvas, }, utils::{ @@ -14,58 +16,20 @@ use crate::{ file, traits::AutoLog, }, + FPS, }; use fir::FilterType; use log::{debug, info}; use std::{ mem, - path::{Path, PathBuf}, + path::Path, sync::{Arc, RwLock}, - thread::spawn, }; -#[derive(Debug, Clone)] -pub struct ExtData { - pub page: Page, - - pub archive_type: ArchiveType, - pub path: PathBuf, - pub screen_size: Size, - pub window_size: Size, - pub filter: FilterType, - pub pos: usize, -} - -impl ExtData { - pub fn new( - archive_type: ArchiveType, - path: PathBuf, - screen_size: Size, - window_size: Size, - filter: FilterType, - ) -> Self { - Self { - page: Page::null(), - archive_type, - path, - screen_size, - window_size, - filter, - pos: 0, - } - } -} - #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] pub enum State { Nothing, - NextReady, - NextDone, - - PrevReady, - PrevDone, - LoadNext, LoadPrev, @@ -74,432 +38,484 @@ pub enum State { } #[derive(Debug)] -pub struct Render { +pub struct Scroll { pub buffer: Buffer, pub buffer_max: usize, + pub bit_len: usize, // free up Bit pub mem_limit: usize, pub head: usize, // =0 pub tail: usize, // =0 pub rng: usize, // - pub load_next: bool, - pub load_prev: bool, - - pub page_list: Vec, - pub page_end: usize, - pub archive_path: PathBuf, - pub archive_type: ArchiveType, + pub page_list: PageList, pub x_step: usize, // move_down AND move_up pub y_step: usize, // move_left AND move_right - pub mode: Map, // [UP, DOWN, QUIT, ...] + pub map: Map, // [UP, DOWN, QUIT, ...] - pub window_size: Size, // - pub screen_size: Size, // not need pub window_position: (i32, i32), // - pub filter: FilterType, // resize image - - pub len: usize, // free up Bit - pub all_len: usize, // free up Anim + pub view_mode: ViewMode, pub page_load_list: Vec, + pub page_number: usize, + pub page_loading: Vec, +} - pub view_mode: ViewMode, +/////////////////////////////////////// +impl State { + pub fn as_i8(&self) -> i8 { + match *self { + Self::Nothing => 0, + Self::DonePrev => 1, + Self::DoneNext => 2, + Self::LoadPrev => -1, + Self::LoadNext => -2, + _ => { + unreachable!() + } + } + } - pub page_number: u32, - pub page_loading: Vec, + pub fn from_i8(v: &i8) -> Self { + match *v { + 0 => Self::Nothing, + 1 => Self::DonePrev, + 2 => Self::DoneNext, + -1 => Self::LoadPrev, + -2 => Self::LoadNext, + _ => { + unreachable!() + } + } + } } -impl Render { +impl Scroll { pub fn new( - page_list: Vec, - archive_type: ArchiveType, - path: impl AsRef, + data: &Data, + page_list: PageList, buffer_max: usize, step: usize, - screen_size: Size, - window_size: Size, view_mode: ViewMode, - filter: FilterType, ) -> Self { Self { buffer: Buffer::new(), buffer_max, - mem_limit: buffer_max * 5, + mem_limit: buffer_max * 6, head: 0, tail: 0, rng: 0, - load_next: false, - load_prev: false, - len: 0, - all_len: 0, + bit_len: 0, - archive_path: path.as_ref().to_path_buf(), - archive_type, - - mode: Map::Stop, - page_end: page_list.len(), + map: Map::Stop, page_list, y_step: buffer_max / step, // drop 1/step part of image once - x_step: window_size.width as usize / step, + x_step: data.window_size.width as usize / step, window_position: (0, 0), - screen_size, - window_size, - page_load_list: Vec::new(), - filter, view_mode, page_number: 0, - page_loading: vec![0; buffer_max * 4], + page_loading: vec![0x112233; buffer_max], } } - /// init - pub fn init(&mut self) { - let mut tmp = (0, 0); + pub fn load_page_number(&mut self, page_number: usize) {} - let mut len = 0; - let mut has_anim_file = 0; + pub fn flush(&mut self, canvas: &mut Canvas, _arc_state: &Arc>) { + let mut tmp = (0, 0, true); - match self.page_list.len() { - 0 => { - panic!() - } - 1 => { - self.view_mode = ViewMode::Image; - tmp = self.load_next(); - } - _ => { - tmp = self.load_next(); - len += tmp.0; - has_anim_file += tmp.1; + let anim_len = self.pages_data_len().1; + anim_len._dbg(); + + self.buffer.clear(); - 'l1: while len <= self.mem_limit && self.tail + 1 < self.page_end { - self.tail += 1; + for idx in self.page_load_list.iter() { + // flush buffer + self.buffer.flush(self.page_list.get(*idx).data()); - tmp = self.load_next(); - len += tmp.0; - has_anim_file += tmp.1; - } + // page number + if tmp.0 >= self.rng && tmp.2 { + tmp.1 = self.page_list.get(*idx).number; + tmp.2 = false; + } else { + tmp.0 += self.page_list.get(*idx).data().len(); } - } - // image.len() < buffer.len() - if has_anim_file >= 1 { - self.view_mode = ViewMode::Page; - } else { + // anim + self.page_list.get_mut(*idx).to_next_frame(); } - "*** INIT ***"._info(); + self.page_number = match tmp.1 { + 0 => self.page_list.list.len() - 1, + _ => tmp.1, + }; - debug!(" len = {}", len); + canvas.flush(&self.buffer.data[self.rng..self.rng + self.buffer_max]); + + self.page_number._info(); } - // use for init - pub fn load_next(&mut self) -> (usize, usize) { - let tail = &mut self.page_list[self.tail]; - let pos = tail.pos; + pub fn start( + config: &Config, + buf: &mut Scroll, + canvas: &mut Canvas, + keymaps: &[KeyMap], + data: &Data, + arc_state: &Arc>, + arc_buffer: &Arc>, + ) { + // WARN: new thread + thread_resize_image(&data, &arc_state, &arc_buffer); - let (ty, mut buffer, format) = - load_file(self.archive_type, self.archive_path.as_path(), pos).unwrap(); - let (meta, pts) = - load_img(format, &mut buffer, self.screen_size, self.window_size).unwrap(); + let mut time_start = std::time::Instant::now(); + let mut sleep = FPS; - tail.ty = ty; - tail.resize = meta.fix; - tail.pts = pts; + 'l1: while canvas.window.is_open() { + buf.pages_data_len(); - resize_page(tail, &mut buffer, &meta, &self.filter); + match keymap::match_event(canvas.window.get_keys().iter().as_slice(), keymaps) { + Map::Down => { + buf.move_down(); + } - tail.is_ready = true; + Map::Up => { + buf.move_up(); + } - (tail.len(), (tail.ty == ImgType::Anim) as usize) - } + Map::Reset => { + todo!() + } - #[inline(always)] - pub fn flush(&mut self, canvas: &mut Canvas, _arc_state: &Arc>) { - self.buffer.clear(); - self.len = self.page_list_len().0; - self.all_len = self.page_list_len().1; + Map::FullScreen => { + todo!() + } - for idx in self.page_load_list.iter() { - if self.page_list[*idx].is_ready { - self.buffer.flush(self.page_list[*idx].data()); - self.page_list[*idx].to_next_frame(); - } else { - // self.buffer - // .data - // .extend_from_slice(&self.page_loading[0..self.buffer_max]); + Map::Left => { + buf.move_left(data); + } + + Map::Right => { + buf.move_right(data); + } + + Map::Exit => { + println!("EXIT"); + + // TODO: Key::Escape + break 'l1; + } + + _ => { + // input from mouse + if config.base.invert_mouse { + if let Some((_x, y)) = canvas.window.get_scroll_wheel() { + if y > 0.0 { + buf.move_up(); + } else if y < 0.0 { + buf.move_down(); + } else { + } + + debug!("mouse_y == {}", y); + } + } else if let Some((_x, y)) = canvas.window.get_scroll_wheel() { + if y > 0.0 { + buf.move_down(); + } else if y < 0.0 { + buf.move_up(); + } else { + } + + debug!("mouse_y == {}", y); + } + } } - } - canvas.flush(&self.buffer.data[self.rng..self.rng + self.buffer_max]); + buf.flush(canvas, &arc_state); + buf.try_load_page(data, arc_state, arc_buffer); + + let now = std::time::Instant::now(); + let count = (now - time_start).as_millis() as u64; - // debug!("self.page_number = {}", self.page_number); + time_start = now; + sleep = FPS.checked_sub(count / 6).unwrap_or(10); + + std::thread::sleep(std::time::Duration::from_millis(sleep)); + } } - #[inline] - pub fn page_list_len(&mut self) -> (usize, usize) { + pub fn pages_data_len(&mut self) -> (usize, usize) { let (mut len, mut all_lan) = (0, 0); self.page_load_list.clear(); - for (idx, page) in self.page_list.iter().enumerate() { - if page.len() > 0 { + for (idx, page) in self.page_list.list.iter().enumerate() { + if page.is_ready && page.len() > 0 { len += page.len(); - all_lan += page.all_len(); + all_lan += page.anim_len(); self.page_load_list.push(idx); } else { } } + self.bit_len = len; + (len, all_lan) } /// move down - #[inline(always)] - pub fn move_down( - &mut self, - arc_state: &Arc>, - arc_extdata: &Arc>, - ) { - "move_down()"._info(); - debug!( - "{}, -{}", - self.rng, self.len - ); - - self.mode = Map::Down; - - // scrolling - if self.rng + self.y_step <= self.len - self.buffer_max { - self.load_next = false; + pub fn move_down(&mut self) { + "MOVE DOWN"._info(); + + self.map = Map::Down; + + // buffer = &[rng..rng+buffer_max] + if self.rng + self.buffer_max + self.y_step <= self.bit_len { self.rng += self.y_step; - } else if self.rng <= self.len - self.buffer_max { - self.load_next = true; - self.rng = self.len - self.buffer_max; + } else if self.rng + self.buffer_max <= self.bit_len { + self.rng = self.bit_len - self.buffer_max; } else { - }; + } - let head_len = self.page_list[self.head].len(); + debug!("{}, {}", self.rng, self.bit_len); + } - if let Ok(mut arc_state) = arc_state.try_write() { - match *arc_state { - State::Nothing | State::PrevDone => { - // try to load next page - if self.tail + 1 < self.page_end && self.len <= self.mem_limit + head_len { - if let Ok(mut arc_extdata) = arc_extdata.try_write() { - info!("load next"); - info!("{:?}", *arc_state); + /// move up + pub fn move_up(&mut self) { + "MOVE UP"._info(); - self.tail += 1; + self.map = Map::Up; - let idx = self.tail; - self.page_list[idx].is_ready = false; - arc_extdata.pos = self.page_list[idx].pos; + if self.rng >= self.y_step { + self.rng -= self.y_step; + } else { + self.rng = 0; + }; + } - mem::swap(&mut self.page_list[idx], &mut arc_extdata.page); + /// move left + pub fn move_left(&mut self, data: &Data) { + // TODO: + self.map = Map::Left; - *arc_state = State::LoadNext; - } else { - // wait - } - } else { - // nothing - } - } - _ => {} - } + // ??? How it works + if self.bit_len > self.end() + self.x_step && self.x_step <= data.window_size.width as usize + { + self.rng += self.x_step; } else { - // wait } - if let Ok(mut arc_state) = arc_state.try_write() { - match *arc_state { - State::DoneNext => { - debug!("state == {:?}", *arc_state); + debug!("start: {}", self.rng); + debug!("end: {}", self.end()); + } - if let Ok(mut arc_extdata) = arc_extdata.try_write() { - // swap page and arc_temp_page again - mem::swap(&mut self.page_list[self.tail], &mut arc_extdata.page); - self.page_list[self.tail].is_ready = true; + /// move right + pub fn move_right(&mut self, data: &Data) { + self.map = Map::Right; - *arc_state = State::Nothing; + if self.rng >= self.x_step && self.x_step <= data.window_size.width as usize { + self.rng -= self.x_step; + } else { + } + } - "*** NEXT ***"._info(); - } else { - // wait - } - } + pub fn end(&self) -> usize { + self.rng + self.buffer_max + } + + pub fn page_list_tail(&self) -> usize { + self.page_list.len() + } - State::Nothing => { - debug!("state == {:?}", *arc_state); + pub fn not_tail(&self) -> bool { + self.page_list.get(self.tail + 1).check != Check::Tail + } - if self.head + 1 < self.tail - && self.len >= self.mem_limit / 2 + head_len - && self.rng >= self.buffer_max * 2 + head_len - { - self.rng -= self.page_list[self.head].len(); - self.page_list[self.head].free(); - self.head += 1; + pub fn not_head(&self) -> bool { + self.page_list.get(self.head - 1).check != Check::Head + } - "*** FREE ***"._info(); - } else { - // nothing - } - } - _ => {} + pub fn try_load_page( + &mut self, + data: &Data, + arc_state: &Arc>, + arc_buffer: &Arc>, + ) { + debug!("{},{}", self.head, self.tail); + + match self.map { + Map::Down => { + self.try_load_page_next(data, arc_state, arc_buffer); } - } else { - // wait + + Map::Up => { + self.try_load_page_prev(data, arc_state, arc_buffer); + } + + _ => {} } } - /// move up - #[inline(always)] - pub fn move_up(&mut self, arc_state: &Arc>, arc_extdata: &Arc>) { - info!("move_up()"); + fn need_load_next(&self) -> bool { + self.not_tail() + && (self.bit_len <= self.mem_limit || self.rng + self.buffer_max == self.bit_len) + } - self.mode = Map::Up; + fn need_load_prev(&self) -> bool { + self.not_head() && (self.bit_len <= self.mem_limit || self.rng == 0) + } - if self.rng >= self.y_step { - self.load_prev = false; - self.rng -= self.y_step; - } else if self.rng >= 0 { - self.load_prev = true; - self.rng -= self.rng; - } else { - unreachable!() - }; + fn need_free_head(&self) -> bool { + let len = self.page_list.get(self.head).len(); - let tail_len = self.page_list[self.tail].len(); + self.tail > self.head + && self.rng >= len + && self.bit_len >= self.mem_limit / 2 + len + && self.bit_len >= self.rng + } - // load image - if let Ok(mut arc_state) = arc_state.try_write() { - match *arc_state { - State::Nothing | State::DoneNext => { - // try to load prev page - if self.head >= 1 && self.len <= self.mem_limit + tail_len { - if let Ok(mut arc_extdata) = arc_extdata.try_write() { - info!("load prev"); + fn need_free_tail(&self) -> bool { + let len = self.page_list.get(self.tail).len(); - self.head -= 1; + self.tail > self.head + && self.bit_len >= self.mem_limit / 2 + len + && self.bit_len >= self.rng + self.buffer_max + len + } - let idx = self.head; - self.page_list[idx].is_ready = false; + pub fn try_load_page_next( + &mut self, + data: &Data, + arc_state: &Arc>, + arc_buffer: &Arc>, + ) { + let head_len = self.page_list.get(self.head).len() * 2; - arc_extdata.pos = self.page_list[idx].pos; - mem::swap(&mut self.page_list[idx], &mut arc_extdata.page); + let Ok(mut arc_state) = arc_state.try_write() else { return; }; - *arc_state = State::LoadPrev; - } else { - // wait - } - } else { - // nothing - } - } - _ => {} - } - } else { - // wait - } + match *arc_state { + // resize image + State::Nothing | State::DonePrev if self.need_load_next() => { + let Ok(mut arc_buffer) = arc_buffer.try_write() else {return;}; - // display image - if let Ok(mut arc_state) = arc_state.try_write() { - debug!("state == {:?}", *arc_state); + info!("load next"); - match *arc_state { - State::DonePrev => { - debug!("state == {:?}", *arc_state); + self.tail += 1; + let idx = self.tail; - if let Ok(mut arc_extdata) = arc_extdata.try_write() { - // swap page and arc_temp_page again - mem::swap(&mut self.page_list[self.head], &mut arc_extdata.page); + self.page_list.get_mut(idx).is_ready = false; - self.page_list[self.head].is_ready = true; + arc_buffer.pos = self.page_list.get(idx).pos; + mem::swap(self.page_list.get_mut(idx), &mut arc_buffer.page); - // a bit different with move_down() - self.rng += self.page_list[self.head].len(); + *arc_state = State::LoadNext; + } - *arc_state = State::Nothing; + // load next + State::DoneNext => { + let Ok(mut arc_buffer) = arc_buffer.try_write() else {return;}; - "*** PREV ***"._info(); - } else { - // wait - } - } + // swap page and buffer again + mem::swap(self.page_list.get_mut(self.tail), &mut arc_buffer.page); + self.page_list.get_mut(self.tail).is_ready = true; - State::Nothing => { - // free up memory - if self.tail > self.head + 1 - && self.len >= self.mem_limit / 2 + tail_len - && self.len >= self.rng + self.buffer_max * 2 + tail_len - { - self.page_list[self.tail].is_ready = false; - self.page_list[self.tail].free(); - self.tail -= 1; - - "*** FREE ***"._info(); - } else { - } - } - _ => {} + *arc_state = State::Nothing; + + "*** NEXT ***"._info(); } - } else { - // wait + + State::Nothing if self.need_free_head() => { + self.rng -= self.page_list.get(self.head).len(); + self.page_list.get_mut(self.head).free(); + self.head += 1; + + "*** FREE HEAD ***"._info(); + } + + _ => {} } } - /// move left - pub fn move_left(&mut self) { - // ??? How it works - if self.len > self.end() + self.x_step && self.x_step <= self.window_size.width as usize { - self.rng += self.x_step; + pub fn try_load_page_prev( + &mut self, + data: &Data, + arc_state: &Arc>, + arc_buffer: &Arc>, + ) { + let tail_len = self.page_list.get(self.tail).len() * 2; - debug!("start: {}", self.rng); - debug!("end: {}", self.end()); - } else { - } + let Ok(mut arc_state) = arc_state.try_write() else {return;}; - self.mode = Map::Left; - } + match *arc_state { + State::Nothing | State::DoneNext if self.need_load_prev() => { + let Ok(mut arc_buffer) = arc_buffer.try_write() else { + return; + }; - /// move right - pub fn move_right(&mut self) { - if self.rng >= self.x_step && self.x_step <= self.window_size.width as usize { - self.rng -= self.x_step; - } else { - } + info!("load prev"); - self.mode = Map::Right; - } + self.head -= 1; + let idx = self.head; + self.page_list.get_mut(idx).is_ready = false; - #[inline] - pub fn end(&self) -> usize { - self.rng + self.buffer_max + arc_buffer.pos = self.page_list.get(idx).pos; + mem::swap(self.page_list.get_mut(idx), &mut arc_buffer.page); + + *arc_state = State::LoadPrev; + } + + State::DonePrev => { + debug!("state == {:?}", *arc_state); + + let Ok(mut arc_buffer) = arc_buffer.try_write() else { + return; + }; + + // swap page and buffer again + mem::swap(self.page_list.get_mut(self.head), &mut arc_buffer.page); + + self.page_list.get_mut(self.head).is_ready = true; + self.rng += self.page_list.get(self.head).len(); + + *arc_state = State::Nothing; + + "*** LOAD PREV ***"._info(); + } + + State::Nothing if self.need_free_tail() => { + // free tail + //self.rng -= self.page_list.get(self.tail).len(); + self.page_list.get_mut(self.tail).free(); + self.tail -= 1; + + "*** FREE TAIL ***"._info(); + } + + _ => {} + } + + debug!("prev(): {}, {}", self.bit_len, self.rng); } } +/////////////////////////////////////// + /// -#[inline(always)] pub fn load_file( - archive_type: ArchiveType, + archive_type: &ArchiveType, archive_path: &Path, page_pos: usize, ) -> Res<(ImgType, Vec>, ImgFormat)> { debug!("archive_type == {:?}", archive_type); - let bytes = match archive_type { + let bytes = match *archive_type { ArchiveType::Tar => { "load tar"._dbg(); @@ -536,6 +552,8 @@ pub fn load_file( } else if file::is_aseprite(&bytes[0]) { format = ImgFormat::Aseprite; } else { + // FIXME:rmg -t svg xxx.svg + // format = ImgFormat::Svg; } match format { @@ -549,12 +567,11 @@ pub fn load_file( } } -#[inline(always)] pub fn load_img( - format: ImgFormat, + format: &ImgFormat, bytes: &mut Vec>, - screen_size: Size, - window_size: Size, + screen_size: &Size, + window_size: &Size, ) -> Res<(MetaSize, Vec)> { let mut meta = MetaSize::::new( screen_size.width, @@ -565,16 +582,15 @@ pub fn load_img( 0, ); - let mut pts = vec![]; + let pts = vec![]; - match format { + match *format { ImgFormat::Jpg | ImgFormat::Png => { let img = image::load_from_memory(&bytes[0])?; meta.image.width = img.width(); meta.image.height = img.height(); meta.resize(); - // BUG: mem::swap(bytes, &mut vec![img.to_rgba8().to_vec()]); Ok((meta, pts)) @@ -583,7 +599,6 @@ pub fn load_img( ImgFormat::Heic | ImgFormat::Avif => { let mut img = heic::load_heic(&bytes[0])?; // heic - meta.image.width = img.0; meta.image.height = img.1; meta.resize(); @@ -597,7 +612,7 @@ pub fn load_img( let mut anim = ase::load_ase(&bytes[0])?; meta.image = anim.0; - meta.resize(); + meta.fix = anim.0; mem::swap(bytes, &mut anim.1); @@ -605,10 +620,11 @@ pub fn load_img( } ImgFormat::Gif => { + // TODO: let mut anim = gif::load_gif(bytes[0].as_slice())?; meta.image = anim.0; - meta.resize(); + meta.fix = anim.0; mem::swap(bytes, &mut anim.1); @@ -616,7 +632,7 @@ pub fn load_img( } ImgFormat::Svg => { - let mut img = crate::img::svg::load_svg(bytes[0].as_slice())?; + let mut img = svg::load_svg(bytes[0].as_slice())?; meta.image = img.0; meta.resize(); @@ -630,13 +646,20 @@ pub fn load_img( } } -#[inline(always)] pub fn resize_page( page: &mut Page, img: &mut Vec>, meta: &MetaSize, filter: &FilterType, + window_size: &Size, ) { + // frames + page.data = vec![vec![]; img.len()]; + + let size = page.get_resize(); + + let mut tmp = Vec::with_capacity(size.len()); + match img.len() { 1 => { let mut tmp = resize::resize_rgba8(mem::take(&mut img[0]), meta, filter).unwrap(); @@ -646,20 +669,111 @@ pub fn resize_page( } _ => { - let mut tmp: Vec = Vec::new(); + if size.width > window_size.width { + // FIXME: How to do? + // resize() + + todo!(); + + for (frame_idx, frame) in img.iter_mut().enumerate() { + resize::argb_u32(&mut tmp, frame.as_slice()); + + // resize::crop_img( + // &mut page.data[frame_idx], + // &tmp, + // offset++, + // size.width as usize, + // size.height as usize, + // window_size.width as usize, + // ); + + page.data[frame_idx] = mem::take(&mut tmp); + } + } else { + let offset = ((window_size.width as usize - size.width as usize) / 2); - page.data = vec![vec![]; img.len()]; // anim + debug!("{}, {}, {}", window_size.width, size.width, offset); - for idx in 0..img.len() { - tmp = resize::resize_rgba8(mem::take(&mut img[idx]), meta, filter).unwrap(); + for (frame_idx, frame) in img.iter_mut().enumerate() { + resize::argb_u32(&mut tmp, frame.as_slice()); - resize::argb_u32(&mut page.data[idx], &mem::take(&mut tmp)); + resize::center_img( + &mut page.data[frame_idx], + &mem::take(&mut tmp), + window_size.width as usize, + size.width as usize, + size.height as usize, + offset, + ); + } } } } } -// #[inline(always)] +// use for resize image only +pub fn thread_resize_image( + data: &Data, + arc_state: &Arc>, + arc_buffer: &Arc>, +) { + let data = data.clone(); + let arc_state = arc_state.clone(); + let arc_buffer = arc_buffer.clone(); + + std::thread::spawn(move || { + loop { + if let Some(_) = load_page(&data, &arc_state, &arc_buffer) { + } else { + } + + // limit CPU usage + //std::thread::sleep(std::time::Duration::from_millis(1000)); + std::thread::yield_now(); + } + }); +} + +pub fn load_page( + data: &Data, + arc_state: &Arc>, + arc_buffer: &Arc>, +) -> Option<(usize, ImgType)> { + if let Ok(mut arc_state) = arc_state.try_write() { + if (*arc_state == State::LoadNext) || (*arc_state == State::LoadPrev) { + if let Ok(mut arc_buffer) = arc_buffer.try_write() { + let (ty, mut buffer, format) = + load_file(&data.archive_type, &data.path, arc_buffer.pos).unwrap(); + + let (meta, pts) = + load_img(&format, &mut buffer, &data.screen_size, &data.window_size).unwrap(); + + arc_buffer.page.ty = ty; + arc_buffer.page.resize = meta.fix; + arc_buffer.page.pts = pts; + + resize_page( + &mut arc_buffer.page, + &mut buffer, + &meta, + &data.filter, + &data.window_size, + ); + + *arc_state = State::from_i8(&arc_state.as_i8().abs()); + + Some((arc_buffer.page.len(), arc_buffer.page.ty)) + } else { + None + } + } else { + None + } + } else { + None + } +} +// // pub fn push_front(vec: &mut Vec, slice: &[T]) { // let amt = slice.len(); // [1, 2, 3] // let len = vec.len(); // [4, 5, 6] @@ -674,7 +788,7 @@ pub fn resize_page( // } // } // -// #[inline(always)] +// // pub fn free_head(buffer: &mut Vec, range: usize) // where // T: Sized + Clone, @@ -682,7 +796,7 @@ pub fn resize_page( // buffer.drain(..range); // } // -// #[inline(always)] +// // pub fn free_tail(buffer: &mut Vec, range: usize) // where // T: Sized, diff --git a/src/reader/turn.rs b/src/reader/turn.rs index f983bb0..13c64e0 100644 --- a/src/reader/turn.rs +++ b/src/reader/turn.rs @@ -1,4 +1,191 @@ +use crate::{ + archive::ArchiveType, + reader::{ + scroll::Scroll, + view::{Buffer, Check, Data, Page, PageList}, + }, + utils::traits::AutoLog, + FPS, +}; +use log::debug; +use std::{mem::swap, path::PathBuf}; + +use super::{keymap, keymap::Map, window::Canvas}; +use crate::reader::keymap::KeyMap; + #[derive(Debug)] -pub struct PageBuffer { - is_single_page: bool, +pub struct Turn { + pub buffer: Buffer, + pub buffer_max: usize, + + pub page_list: PageList, + + pub cur: usize, // + pub map: Map, + + pub rng: usize, + pub y_step: usize, + + pub is_double_page: bool, + pub is_manga: bool, + + pub page_max: usize, +} + +impl Turn { + pub fn from_scroll(scroll: Scroll) -> Self { + Self { + buffer: Buffer::new(), + buffer_max: scroll.buffer_max, + page_list: scroll.page_list, + cur: 1, + map: Map::Right, + rng: 0, + y_step: scroll.y_step, // drop 1/step part of image once + is_double_page: false, + is_manga: false, + page_max: 3, + } + } + + pub fn start(&mut self, canvas: &mut Canvas, keymaps: &[KeyMap]) { + let mut time_start = std::time::Instant::now(); + let mut sleep = FPS; + + 'l1: while canvas.window.is_open() { + match keymap::match_event(canvas.window.get_keys().iter().as_slice(), keymaps) { + Map::Down => self.move_down(), + + Map::Up => self.move_up(), + + Map::Left => self.goto_prev_page(), + + Map::Right => self.goto_next_page(), + + Map::Exit => break 'l1, + + _ => {} + } + } + + self.flush(canvas); + self.to_next_frame(); + + let now = std::time::Instant::now(); + let count = (now - time_start).as_millis() as u64; + + time_start = now; + sleep = FPS.checked_sub(count / 6).unwrap_or(10); + + std::thread::sleep(std::time::Duration::from_millis(sleep)); + } + + pub fn flush(&mut self, canvas: &mut Canvas) { + self.buffer.flush(self.page_list.get(self.cur).data()); + + if self.cur_len() > self.buffer_max { + self.buffer + .data + .extend_from_slice(&vec![0; self.cur_len() - self.buffer_max]); + } else { + }; + + canvas.flush(&self.buffer.data[self.rng..self.rng + self.buffer_max]); + } + + pub fn sort_page(&mut self) { + if self.is_manga { + let count = self.page_list.len() / 2; + let (mut l, mut r) = (0, 1); + + for _ in 0..count { + self.page_list.swap(l, r); + + l += 2; + r += 2; + } + } else { + } + } + + pub fn not_tail(&self) -> bool { + self.page_list.get(self.cur + 1).check != Check::Tail + } + + pub fn not_head(&self) -> bool { + self.page_list.get(self.cur - 1).check != Check::Head + } + + pub fn get_cur_mut(&mut self) -> &mut Page { + self.page_list.get_mut(self.cur) + } + + pub fn get_cur(&self) -> &Page { + self.page_list.get(self.cur) + } + + pub fn cur_len(&self) -> usize { + self.page_list.get(self.cur).len() + } + + pub fn goto_next_page(&mut self) { + if self.not_tail() { + //self.try_free_page_prev( self.cur - 1 ); + //self.try_load_page_next( self.cur + 1 ); + + self.rng = 0; + self.cur += 1; + } + } + + pub fn goto_prev_page(&mut self) { + if self.not_head() { + self.rng = 0; + self.cur -= 1; + } + } + + pub fn try_load_page_next(&mut self) { + for f in 0..self.page_max {} + } + + pub fn try_load_page_prev(&mut self) { + for f in 0..self.page_max {} + } + + pub fn free_page(&mut self) {} + + /// move up + pub fn move_up(&mut self) { + "MOVE UP"._info(); + + self.map = Map::Up; + + if self.rng >= self.y_step { + self.rng -= self.y_step; + } else { + // if (self.rng >= 0) + self.rng = 0; + }; + } + + /// move down + pub fn move_down(&mut self) { + "MOVE DOWN"._info(); + debug!("{} -- {}", self.rng, self.buffer.len()); + + self.map = Map::Down; + + // scrolling + if self.rng + self.y_step <= self.buffer.len() - self.buffer_max { + self.rng += self.y_step; + } else { + // if (self.rng <= self.buffer_len - self.buffer_max) + self.rng = self.buffer.len() - self.buffer_max; + }; + } + + pub fn to_next_frame(&mut self) { + self.get_cur_mut().to_next_frame() + } } diff --git a/src/reader/view.rs b/src/reader/view.rs index 1db7ef6..1b48af8 100644 --- a/src/reader/view.rs +++ b/src/reader/view.rs @@ -1,6 +1,113 @@ -use crate::img::size::Size; -use crate::FPS; +use crate::{archive::ArchiveType, img::resize, img::size::Size, FPS}; +use fir::FilterType; use log::debug; +use std::{ + mem::swap, + path::PathBuf, + sync::{Arc, RwLock}, +}; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum Check { + Head, + Body, + Tail, +} + +// use in the thread +#[derive(Debug, Clone)] +pub struct ArcTmpBuffer { + pub page: Page, + pub pos: usize, +} + +impl ArcTmpBuffer { + pub fn new() -> Self { + Self { + page: Page::null(), + pos: 0, + } + } + + pub fn new_arc() -> Arc> { + Arc::new(RwLock::new(Self::new())) + } +} + +#[derive(Debug, Clone)] +pub struct Data { + pub page: Page, + pub pos: usize, + pub archive_type: ArchiveType, + pub path: PathBuf, + pub screen_size: Size, + pub window_size: Size, + pub filter: FilterType, +} + +impl Data { + pub fn new( + archive_type: ArchiveType, + path: PathBuf, + screen_size: Size, + window_size: Size, + filter: FilterType, + ) -> Self { + Self { + page: Page::null(), + pos: 0, + archive_type, + path, + screen_size, + window_size, + filter, + } + } +} + +#[derive(Debug)] +pub struct PageList { + pub list: Vec, + pub head: usize, + pub tail: usize, + pub cur: usize, +} + +impl PageList { + pub fn new(tmp_list: Vec) -> Self { + let mut list = Vec::with_capacity(tmp_list.len() + 2); + + list.push(Page::null()); + list.extend(tmp_list.into_iter()); + list.push(Page::null()); + + list.first_mut().unwrap().check = Check::Head; + list.last_mut().unwrap().check = Check::Tail; + + Self { + list, + cur: 0, + head: 0, + tail: 0, + } + } + + pub fn get(&self, idx: usize) -> &Page { + &self.list[idx] + } + + pub fn get_mut(&mut self, idx: usize) -> &mut Page { + self.list.get_mut(idx).unwrap() + } + + pub fn len(&self) -> usize { + self.list.len() + } + + pub fn swap(&mut self, l: usize, r: usize) { + self.list.swap(l, r); + } +} #[derive(Debug)] pub struct Buffer { @@ -23,43 +130,35 @@ pub struct Page { pub pos: usize, // index of image in the archive file pub resize: Size, // (fix_width, fix_height) + pub offset_x: usize, + // for gif only pub idx: usize, // index of frame pub timer: usize, pub miss: usize, pub pts: Vec, // pts = delay + fps + pub check: Check, } -// ๆ”พๅคง้•œ -// ้ผ ๆ ‡ ๆˆชๅ–ๅŒบๅ— -// ๅฎšไฝ -// copy from buffer with Block -// -// ่ฟ›ๅ…ฅ crop ๆจกๅผ -// ๆš‚ๅœ -// ้€‰ๆ‹ฉๅŒบๅ— -// ๆ”พๅคง -// ้€€ๅ‡บ #[derive(Debug, Clone)] struct CropBlock { - // (sx, sy) - // +--------------+ - // | | - // | | - // | | - // | | - // +--------------+ - // (rx, ry) - sx: u32, - sy: u32, // - rx: u32, - ry: u32, // + // (x , y) + // +--------------+ + // | | + // | | + // | | + // | | + // +--------------+ + x: u32, + y: u32, + w: u32, + h: u32, } #[derive(Debug, Clone, Copy, PartialEq)] pub enum ImgType { - Bit = 0, // jpg / heic ... - Anim = 1, // gif / aseprite + Bit, // jpg / heic ... + Anim, // gif / aseprite } #[derive(Debug, Clone, Copy, PartialEq)] @@ -93,9 +192,9 @@ pub enum ViewMode { #[default] Scroll, - Image, // image OR gif + Once, // image OR gif - Page, // + Turn, // // Manga: Left to Right // Comic: Right to Left } @@ -121,6 +220,7 @@ impl Buffer { self.data.extend_from_slice(bytes); } } + impl From<&str> for ImgFormat { fn from(value: &str) -> Self { match value { @@ -137,13 +237,15 @@ impl From<&str> for ImgFormat { } impl Page { - pub fn new(name: String, number: usize, pos: usize) -> Self { + pub fn new(name: String, pos: usize) -> Self { Self { name, - number, + number: 0, pos, resize: Size::new(0, 0), is_ready: false, + check: Check::Body, + offset_x: 0, data: vec![], pts: vec![], @@ -165,6 +267,8 @@ impl Page { pos: 0, resize: Size::new(0, 0), is_ready: false, + check: Check::Body, + offset_x: 0, data: vec![], pts: vec![], @@ -192,11 +296,26 @@ impl Page { self.resize = Size::new(width, height); } + pub fn get_resize(&mut self) -> Size { + self.resize + } + #[inline(always)] pub fn data(&self) -> &[u32] { self.data[self.idx].as_slice() } + pub fn data_crop(&self, ww: usize) { + // TODO: + let res = resize::crop_img2( + self.data[self.idx].as_slice(), + self.offset_x, + self.resize.width as usize, + self.resize.height as usize, + ww, // window_size.width + ); + } + pub fn free(&mut self) { self.data.clear(); self.data.shrink_to(0); @@ -204,7 +323,7 @@ impl Page { } #[inline] - pub fn all_len(&self) -> usize { + pub fn anim_len(&self) -> usize { if self.is_ready { self.data[0].len() * self.data.len() } else { @@ -225,8 +344,8 @@ impl Page { #[inline(always)] pub fn to_next_frame(&mut self) { if self.ty == ImgType::Anim { - if self.timer >= (self.pts() as isize - self.miss as isize).abs() as usize { - self.miss = self.timer.checked_sub(self.pts()).unwrap_or(0); + if self.timer >= (self.pts() as isize - self.miss as isize).unsigned_abs() { + self.miss = self.timer.saturating_sub(self.pts()); if self.idx + 1 < self.data.len() { self.idx += 1; @@ -239,30 +358,22 @@ impl Page { self.timer += FPS as usize; } - // debug!("self.timer = {}", self.timer); - // debug!("self.idx = {}", self.idx); - // debug!("self.miss = {}", self.miss); - // debug!("self.pts() = {}", self.pts()); - // debug!( - // "self.data.len() = {} - // - // ", - // self.data.len() - // ); + debug!("self.timer = {}", self.timer); + debug!("self.idx = {}", self.idx); + debug!("self.miss = {}", self.miss); + debug!("self.pts() = {}", self.pts()); + debug!( + "self.data.len() = {} + + ", + self.data.len() + ); } else { } - - // let add = self.ty as usize; - // - // if self.idx + add < self.data.len() { - // self.idx += add; - // } else { - // self.idx = 0; - // } } } -// mem::take() +// use for mem::take() impl Default for Page { fn default() -> Self { Page::null() diff --git a/src/reader/window.rs b/src/reader/window.rs index 6637bb2..b250c2f 100644 --- a/src/reader/window.rs +++ b/src/reader/window.rs @@ -29,6 +29,7 @@ impl Canvas { Self { window, + size: (width, height), } } diff --git a/src/utils/cli.rs b/src/utils/cli.rs index 0cede4e..9118564 100644 --- a/src/utils/cli.rs +++ b/src/utils/cli.rs @@ -1,4 +1,6 @@ -use crate::{config::rsconf::Config, img::size::Size, utils::err::Res}; +use crate::{ + config::rsconf::Config, img::size::Size, reader::view::ViewMode, utils::err::Res, VERSION, +}; use dirs_next; use lexopt::{self, prelude::*}; use std::{path::PathBuf, process::exit}; @@ -28,7 +30,7 @@ impl Args { Long("size") | Short('s') => { let size = parser.value()?.into_string()?; - let size = size.as_str().split(',').collect::>(); + let size = size.as_str().split('x').collect::>(); let (w, h) = ( size[0].parse::().unwrap_or_default(), @@ -39,11 +41,19 @@ impl Args { } Long("mode") | Short('m') => { - todo!() + let mode = parser.value()?.into_string()?; + + config.base.view_mode = match mode.as_str() { + "s" | "scroll" => ViewMode::Scroll, + "o" | "once" => ViewMode::Once, + "t" | "turn" => ViewMode::Turn, + _ => ViewMode::Scroll, + }; } Long("pad") => { let pad = parser.value()?.into_string()?; + config.base.rename_pad = pad.parse::()?; } @@ -93,28 +103,31 @@ impl Args { } } -fn print_help() -> ! { - use crate::VERSION; - +pub fn print_help() -> ! { // TODO: println!( - r#"rmg: {version} -Manga Reader + r#"rmg: {VERSION} +Manga Viewer USAGE: rmg [OPTIONS] file OPTIONS: - -h, --help Prints help information - -V, --version Prints version information - - -s, --size Max width and height of the buffer - e.g. rmg --size 900,900 - -c, --config Reset the config path - - --pad ... + -h, --help + Prints help information + -V, --version + Prints version information + -s, --size + Reset the width and the height of the buffer + Example: rmg --size 900x900 + -c, --config + Specify the config file path + -m, --mode + (TODO) + --pad + (TODO) "#, - version = VERSION ); + exit(127); } diff --git a/src/utils/file.rs b/src/utils/file.rs index 1d1dd31..84f12b7 100644 --- a/src/utils/file.rs +++ b/src/utils/file.rs @@ -4,15 +4,18 @@ use std::path::Path; use super::err::Res; use crate::EXT_LIST; +// TODO: rewrite pub fn has_supported(path: impl AsRef) -> bool { if path.as_ref().is_dir() { return false; } else { for ext in EXT_LIST { + // HINT: non-UTF-8 path is allow if path .as_ref() - .to_str() - .unwrap() + .display() + .to_string() + .as_str() .ends_with(format!(".{}", ext).as_str()) { return true; @@ -26,6 +29,7 @@ pub fn has_supported(path: impl AsRef) -> bool { false } +// TODO: rewrite pub fn get_filetype(path: impl AsRef) -> String { let Ok(opt_file) = infer::get_from_path(path.as_ref()) else { todo!() @@ -35,9 +39,8 @@ pub fn get_filetype(path: impl AsRef) -> String { return ty.extension().to_string(); } else { match path.as_ref().extension().unwrap().to_str().unwrap() { - "ase" | "aseprite" => { - return "aseprite".to_string(); - } + "ase" | "aseprite" => "aseprite".to_string(), + "svg" => "svg".to_string(), _ => { println!("{:?}", path.as_ref()); @@ -63,7 +66,7 @@ where for f in list.iter() { let full = Path::new(f.as_ref()); - let mut path = full.parent().unwrap().to_str().unwrap().to_string(); + let mut path = full.parent().unwrap().display().to_string(); let suffix = full.extension().unwrap().to_str().unwrap(); let filename = full.file_stem().unwrap().to_str().unwrap(); diff --git a/tests/files/ase/00.ase b/tests/anim/ase/00.ase similarity index 100% rename from tests/files/ase/00.ase rename to tests/anim/ase/00.ase diff --git a/tests/files/ase/01.ase b/tests/anim/ase/01.ase similarity index 100% rename from tests/files/ase/01.ase rename to tests/anim/ase/01.ase diff --git a/tests/files/ase/02.ase b/tests/anim/ase/02.ase similarity index 100% rename from tests/files/ase/02.ase rename to tests/anim/ase/02.ase diff --git a/tests/files/avif/0.avif b/tests/bit/avif/0.avif similarity index 100% rename from tests/files/avif/0.avif rename to tests/bit/avif/0.avif diff --git a/tests/files/heic/1.heic b/tests/bit/heic/1.heic similarity index 100% rename from tests/files/heic/1.heic rename to tests/bit/heic/1.heic diff --git a/tests/files/png/1.png b/tests/bit/png/1.png similarity index 100% rename from tests/files/png/1.png rename to tests/bit/png/1.png diff --git a/tests/files/png/2.jpg b/tests/bit/png/2.jpg similarity index 100% rename from tests/files/png/2.jpg rename to tests/bit/png/2.jpg diff --git a/tests/files/png/2.png b/tests/bit/png/2.png similarity index 100% rename from tests/files/png/2.png rename to tests/bit/png/2.png diff --git a/tests/files/svg/0.svg b/tests/bit/svg/0.svg similarity index 100% rename from tests/files/svg/0.svg rename to tests/bit/svg/0.svg diff --git a/tests/files/config.rs b/tests/files/config.rs index 72afec7..2431a58 100644 --- a/tests/files/config.rs +++ b/tests/files/config.rs @@ -2,10 +2,10 @@ fn main() { Base { size: (900, 900), // width AND height font: None, // - rename_pad: 0, // + rename_pad: 6, // invert_mouse: false, // - filter: "Hamming", // ["Box", "Hamming", "Lanczos3"] - step: 10, // + filter: "Lanczos3", // [Box, Hamming, Lanczos3, CatmullRom, Mitchell] + step: 4, // }; Keymap {