mod viewer;
use std::sync::mpsc;
use stet_graphics::display_list::DisplayList;
pub type DisplayListMsg = (DisplayList, f64, u32, u32, Option<std::sync::Arc<Vec<u8>>>);
pub enum ViewerMsg {
Page(PageReady),
NewJob,
JobDone,
PasswordRequired { filename: String, retry: bool },
}
pub struct PageReady {
pub display_list: DisplayList,
pub width: u32,
pub height: u32,
pub dpi: f64,
pub page_num: u32,
pub cmyk_bytes: Option<std::sync::Arc<Vec<u8>>>,
}
pub enum ScreenInfo {
DpiOverride(f64),
AvailableHeight(f64),
}
pub struct InterpreterEnd {
pub dl_receiver: mpsc::Receiver<DisplayListMsg>,
pub page_sender: mpsc::Sender<ViewerMsg>,
pub screen_info_receiver: mpsc::Receiver<ScreenInfo>,
}
pub struct ViewerEnd {
pub page_receiver: mpsc::Receiver<ViewerMsg>,
pub screen_info_sender: mpsc::SyncSender<ScreenInfo>,
pub advance_sender: mpsc::SyncSender<()>,
pub file_drop_sender: mpsc::Sender<String>,
pub interrupt_flag: std::sync::Arc<std::sync::atomic::AtomicBool>,
pub password_response_sender: mpsc::Sender<Option<String>>,
}
pub fn create_channels() -> (
InterpreterEnd,
ViewerEnd,
mpsc::Sender<DisplayListMsg>,
mpsc::Receiver<()>,
mpsc::Receiver<String>,
std::sync::Arc<std::sync::atomic::AtomicBool>,
mpsc::Receiver<Option<String>>,
) {
let (dl_tx, dl_rx) = mpsc::channel();
let (page_tx, page_rx) = mpsc::channel();
let (info_tx, info_rx) = mpsc::sync_channel(1);
let (advance_tx, advance_rx) = mpsc::sync_channel(0);
let (file_drop_tx, file_drop_rx) = mpsc::channel();
let interrupt_flag = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
let (password_response_tx, password_response_rx) = mpsc::channel();
(
InterpreterEnd {
dl_receiver: dl_rx,
page_sender: page_tx,
screen_info_receiver: info_rx,
},
ViewerEnd {
page_receiver: page_rx,
screen_info_sender: info_tx,
advance_sender: advance_tx,
file_drop_sender: file_drop_tx,
interrupt_flag: interrupt_flag.clone(),
password_response_sender: password_response_tx,
},
dl_tx,
advance_rx,
file_drop_rx,
interrupt_flag,
password_response_rx,
)
}
const DEFAULT_PAGE_W: f64 = 612.0;
const DEFAULT_PAGE_H: f64 = 792.0;
pub fn run_viewer(
viewer_end: ViewerEnd,
dpi_override: Option<f64>,
filename: Option<&str>,
page_size: Option<(f64, f64)>,
system_cmyk_bytes: Option<std::sync::Arc<Vec<u8>>>,
no_aa: bool,
) {
run_viewer_inner(
viewer_end,
dpi_override,
filename,
page_size,
system_cmyk_bytes,
no_aa,
)
}
fn run_viewer_inner(
viewer_end: ViewerEnd,
dpi_override: Option<f64>,
filename: Option<&str>,
page_size: Option<(f64, f64)>,
system_cmyk_bytes: Option<std::sync::Arc<Vec<u8>>>,
no_aa: bool,
) {
let app = viewer::ViewerApp::new(viewer_end, dpi_override, system_cmyk_bytes, no_aa);
let title = match filename {
Some(name) => {
let base = std::path::Path::new(name)
.file_name()
.map(|n| n.to_string_lossy().to_string())
.unwrap_or_else(|| name.to_string());
format!("stet — {}", base)
}
None => "stet".to_string(),
};
let (page_w, page_h) = page_size.unwrap_or((DEFAULT_PAGE_W, DEFAULT_PAGE_H));
let aspect = page_w / page_h;
let status_bar_est = 32.0_f32;
let est_mon_h = 1440.0_f32;
let est_mon_w = 2560.0_f32;
let max_content_h = est_mon_h * 0.85 - status_bar_est;
let max_content_w = est_mon_w * 0.85;
let mut content_h = max_content_h;
let mut content_w = content_h * aspect as f32;
if content_w > max_content_w {
content_w = max_content_w;
content_h = content_w / aspect as f32;
}
let init_w = content_w;
let init_h = content_h + status_bar_est;
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_title(&title)
.with_inner_size([init_w, init_h])
.with_drag_and_drop(true),
centered: true,
persist_window: false,
..Default::default()
};
eframe::run_native("stet", options, Box::new(|_cc| Ok(Box::new(app))))
.expect("Failed to start viewer");
}