it almost basically works

This commit is contained in:
itsjunetime
2025-06-02 22:33:12 -06:00
parent 4d764cd4f9
commit 4bde532d08
4 changed files with 147 additions and 115 deletions
+4 -1
View File
@@ -87,12 +87,15 @@ pub fn start_rendering_loop(
}; };
to_render_tx.send(RenderNotif::Area(main_area)).unwrap(); to_render_tx.send(RenderNotif::Area(main_area)).unwrap();
let cell_height_px = size.height / size.rows;
let cell_width_px = size.width / size.columns;
std::thread::spawn(move || { std::thread::spawn(move || {
start_rendering( start_rendering(
&str_path, &str_path,
to_main_tx, to_main_tx,
from_main_rx, from_main_rx,
size, cell_height_px,
cell_width_px,
tdf::PrerenderLimit::All, tdf::PrerenderLimit::All,
black, black,
white white
+126 -3
View File
@@ -1,7 +1,18 @@
use std::io::Write; use std::{io::Write, num::NonZeroU32};
use crossterm::event::EventStream; use crossterm::{cursor::MoveTo, event::EventStream, execute};
use kittage::{AsyncInputReader, ImageId, action::Action, error::TransmitError}; use kittage::{
AsyncInputReader, ImageDimensions, ImageId, PixelFormat,
action::Action,
delete::{ClearOrDelete, DeleteConfig, WhichToDelete},
display::DisplayConfig,
error::TransmitError,
image::Image,
medium::Medium
};
use ratatui::prelude::Rect;
use crate::converter::MaybeTransferred;
#[derive(Debug)] #[derive(Debug)]
pub struct DbgWriter<W: Write> { pub struct DbgWriter<W: Write> {
@@ -46,3 +57,115 @@ pub async fn run_action<'image, 'data, 'es>(
.await .await
.map(|(_, i)| i) .map(|(_, i)| i)
} }
pub async fn display_kitty_images(
images: Vec<(usize, &mut MaybeTransferred, Rect)>,
ev_stream: &mut EventStream
) -> Result<(), (Vec<usize>, String)> {
run_action(
Action::Delete(DeleteConfig {
effect: ClearOrDelete::Clear,
which: WhichToDelete::All
}),
ev_stream
)
.await
.map_err(|e| (vec![], format!("Couldn't clear previous images: {e}")))?;
let mut err = None;
for (page_num, img, area) in images {
let config = DisplayConfig::default();
execute!(std::io::stdout(), MoveTo(area.x, area.y)).unwrap();
log::debug!("looking at (area {area:?}) img {img:#?}");
let this_err = match img {
MaybeTransferred::NotYet(image, _map) => {
let mut fake_image = Image {
num_or_id: image.num_or_id,
format: PixelFormat::Rgb24(
ImageDimensions {
width: 0,
height: 0
},
None
),
medium: Medium::Direct {
chunk_size: None,
data: (&[]).into()
}
};
std::mem::swap(image, &mut fake_image);
log::debug!("Actually trying to display an image now: {fake_image:?}...");
let res = run_action(
Action::TransmitAndDisplay {
image: fake_image,
config,
placement_id: None
},
ev_stream
)
.await;
log::debug!("And it should've gone through: {res:?}!...");
match res {
Ok(img_id) => {
// We need the `_map` to be dropped here, but can't explicitly carry it
// over to here. So we're just relying on the overwrite of `img` to
// drop `_map` (and thus unmap the memory) for us
*img = MaybeTransferred::Transferred(img_id);
Ok(())
}
Err(e) => Err(match e {
TransmitError::Writing(action, e) => {
let num = if let Action::TransmitAndDisplay {
image: failed_img, ..
} = *action
{
*image = failed_img;
None
} else {
Some(page_num)
};
(num, e.to_string())
}
_ => (Some(page_num), e.to_string())
})
}
}
MaybeTransferred::Transferred(image_id) => {
let e = run_action(
Action::Display {
image_id: *image_id,
placement_id: NonZeroU32::new(1).unwrap(),
config
},
ev_stream
)
.await
.map(|_| ())
.map_err(|e| (None, e.to_string()));
log::debug!("Just tried to display: {e:?}");
e
}
};
if let Err((id, e)) = this_err {
let e = err.get_or_insert_with(|| (vec![], e));
if let Some(id) = id {
e.0.push(id);
}
}
}
match err {
Some(e) => Err(e),
None => Ok(())
}
}
+14 -106
View File
@@ -19,21 +19,16 @@ use flume::{Sender, r#async::RecvStream};
use flexi_logger::FileSpec; use flexi_logger::FileSpec;
use futures_util::{FutureExt, stream::StreamExt}; use futures_util::{FutureExt, stream::StreamExt};
use kittage::{ use kittage::{
ImageDimensions, PixelFormat,
action::Action, action::Action,
delete::{ClearOrDelete, DeleteConfig, WhichToDelete}, delete::{ClearOrDelete, DeleteConfig, WhichToDelete}
display::{DisplayConfig, DisplayLocation},
error::TransmitError,
image::Image as KImage,
medium::Medium
}; };
use notify::{Event, EventKind, RecursiveMode, Watcher}; use notify::{Event, EventKind, RecursiveMode, Watcher};
use ratatui::{Terminal, backend::CrosstermBackend}; use ratatui::{Terminal, backend::CrosstermBackend};
use ratatui_image::picker::{Picker, ProtocolType}; use ratatui_image::picker::{Picker, ProtocolType};
use tdf::{ use tdf::{
PrerenderLimit, PrerenderLimit,
converter::{ConvertedPage, ConverterMsg, MaybeTransferred, run_conversion_loop}, converter::{ConvertedPage, ConverterMsg, run_conversion_loop},
kitty::run_action, kitty::{display_kitty_images, run_action},
renderer::{self, RenderError, RenderInfo, RenderNotif}, renderer::{self, RenderError, RenderInfo, RenderNotif},
tui::{BottomMessage, InputAction, MessageSetting, Tui} tui::{BottomMessage, InputAction, MessageSetting, Tui}
}; };
@@ -236,12 +231,16 @@ async fn main() -> Result<(), WrappedErr> {
.prerender .prerender
.and_then(NonZeroUsize::new) .and_then(NonZeroUsize::new)
.map_or(PrerenderLimit::All, PrerenderLimit::Limited); .map_or(PrerenderLimit::All, PrerenderLimit::Limited);
let cell_height_px = window_size.height / window_size.rows;
let cell_width_px = window_size.width / window_size.columns;
std::thread::spawn(move || { std::thread::spawn(move || {
renderer::start_rendering( renderer::start_rendering(
&file_path, &file_path,
render_tx, render_tx,
render_rx, render_rx,
window_size, cell_height_px,
cell_width_px,
prerender, prerender,
black, black,
white white
@@ -419,107 +418,16 @@ async fn enter_redraw_loop(
to_display = tui.render(f, &main_area); to_display = tui.render(f, &main_area);
})?; })?;
let mut maybe_err = Ok(()); let maybe_err = display_kitty_images(to_display, &mut ev_stream).await;
let mut to_replace = Vec::new();
for (page_num, img, area) in to_display {
let config = DisplayConfig {
location: DisplayLocation {
x: area.x.into(),
y: area.y.into(),
..DisplayLocation::default()
},
..DisplayConfig::default()
};
log::debug!("looking at img {img:#?}"); if let Err((to_replace, e)) = maybe_err {
maybe_err = match img {
MaybeTransferred::NotYet(image, _map) => {
let mut fake_image = KImage {
num_or_id: image.num_or_id,
format: PixelFormat::Rgb24(
ImageDimensions {
width: 0,
height: 0
},
None
),
medium: Medium::Direct {
chunk_size: None,
data: (&[]).into()
}
};
std::mem::swap(image, &mut fake_image);
log::debug!("Actually trying to display an image now: {fake_image:?}...");
let res = run_action(
Action::TransmitAndDisplay {
image: fake_image,
config,
placement_id: None
},
&mut ev_stream
)
.await;
log::debug!("And it should've gone through: {res:?}!...");
match res {
Ok(img_id) => {
// We need the `_map` to be dropped here, but can't explicitly carry it
// over to here. So we're just relying on the overwrite of `img` to
// drop `_map` (and thus unmap the memory) for us
*img = MaybeTransferred::Transferred(img_id);
Ok(())
}
Err(e) => Err(match e {
TransmitError::Writing(action, e) => {
if let Action::TransmitAndDisplay {
image: failed_img, ..
} = *action
{
*image = failed_img;
} else {
to_replace.push(page_num);
}
e.to_string()
}
_ => {
to_replace.push(page_num);
e.to_string()
}
})
}
}
MaybeTransferred::Transferred(image_id) => {
let e = run_action(
Action::Display {
image_id: *image_id,
placement_id: NonZeroU32::new(1).unwrap(),
config
},
&mut ev_stream
)
.await
.map(|_| ())
.map_err(|e| e.to_string());
log::debug!("Just tried to display: {e:?}");
e
}
};
}
for page_num in to_replace {
tui.page_failed_display(page_num);
}
if let Err(e) = maybe_err {
tui.set_msg(MessageSetting::Some(BottomMessage::Error(format!( tui.set_msg(MessageSetting::Some(BottomMessage::Error(format!(
"Couldn't transfer image to the terminal: {e}" "Couldn't transfer image to the terminal: {e}"
)))); ))));
for page_num in to_replace {
tui.page_failed_display(page_num);
}
} }
execute!(stdout().lock(), EndSynchronizedUpdate)?; execute!(stdout().lock(), EndSynchronizedUpdate)?;
+3 -5
View File
@@ -1,6 +1,5 @@
use std::{thread::sleep, time::Duration}; use std::{thread::sleep, time::Duration};
use crossterm::terminal::WindowSize;
use flume::{Receiver, SendError, Sender, TryRecvError}; use flume::{Receiver, SendError, Sender, TryRecvError};
use itertools::Itertools; use itertools::Itertools;
use mupdf::{ use mupdf::{
@@ -78,7 +77,8 @@ pub fn start_rendering(
path: &str, path: &str,
sender: Sender<Result<RenderInfo, RenderError>>, sender: Sender<Result<RenderInfo, RenderError>>,
receiver: Receiver<RenderNotif>, receiver: Receiver<RenderNotif>,
size: WindowSize, col_h: u16,
col_w: u16,
prerender: PrerenderLimit, prerender: PrerenderLimit,
black: i32, black: i32,
white: i32 white: i32
@@ -88,9 +88,7 @@ pub fn start_rendering(
let mut search_term = None; let mut search_term = None;
// And although the font size could theoretically change, we aren't accounting for that right // And although the font size could theoretically change, we aren't accounting for that right
// now, so we just keep this out of the loop. // now, so we just use the values passed in.
let col_w = size.width / size.columns;
let col_h = size.height / size.rows;
let mut stored_doc = None; let mut stored_doc = None;
let mut invert = false; let mut invert = false;