Custom Colors (#70)

* First implementation of custom colors

* Remove use-statement

Co-authored-by: June <61218022+itsjunetime@users.noreply.github.com>

* Cleaned up help-text

Co-authored-by: June <61218022+itsjunetime@users.noreply.github.com>

* Removed superfluous features from csscolorparser

* Fix for clippy

* Clarify how to pass in custom colors

* Explicitly install clippy and rustfmt in CI

* Better error handling when colors can not be parsed

Co-authored-by: June <61218022+itsjunetime@users.noreply.github.com>

* More elegant type conversion

Co-authored-by: June <61218022+itsjunetime@users.noreply.github.com>

* Made clippy happy

---------

Co-authored-by: June <61218022+itsjunetime@users.noreply.github.com>
Co-authored-by: itsjunetime <junewelker@gmail.com>
This commit is contained in:
JanNeuendorf
2025-05-28 19:16:07 +02:00
committed by GitHub
parent 2f4e2a54bc
commit e16163efb8
8 changed files with 76 additions and 20 deletions
+29 -1
View File
@@ -51,11 +51,26 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// The number of pages to prerender surrounding the currently-shown page; 0 means no
/// limit. By default, there is no limit.
optional -p,--prerender prerender: usize
/// Custom white color, specified in css format (e.g. "FFFFFF" or "rgb(255, 255, 255)")
optional -w,--white-color white: String
/// Custom black color, specified in css format (e.g "000000" or "rgb(0, 0, 0)")
optional -b,--black-color black: String
/// PDF file to read
required file: PathBuf
};
let path = flags.file.canonicalize()?;
let black = parse_color_to_i32(&flags.black_color.unwrap_or("000000".into())).map_err(|e| {
BadTermSizeStdin(format!(
"Couldn't parse black color: {e} - is it formatted like a CSS color?"
))
})?;
let white = parse_color_to_i32(&flags.white_color.unwrap_or("FFFFFF".into())).map_err(|e| {
BadTermSizeStdin(format!(
"Couldn't parse while color: {e} - is it formatted like a CSS color?"
))
})?;
let (watch_to_render_tx, render_rx) = flume::unbounded();
let tui_tx = watch_to_render_tx.clone();
@@ -141,7 +156,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.and_then(NonZeroUsize::new)
.map_or(PrerenderLimit::All, PrerenderLimit::Limited);
std::thread::spawn(move || {
renderer::start_rendering(&file_path, render_tx, render_rx, window_size, prerender)
renderer::start_rendering(
&file_path,
render_tx,
render_rx,
window_size,
prerender,
black,
white
)
});
let mut ev_stream = crossterm::event::EventStream::new();
@@ -286,3 +309,8 @@ fn on_notify_ev(
}
}
}
fn parse_color_to_i32(cs: &str) -> Result<i32, csscolorparser::ParseColorError> {
let color = csscolorparser::parse(cs)?;
let [r, g, b, _] = color.to_rgba8();
Ok(i32::from_be_bytes([0, r, g, b]))
}
+10 -2
View File
@@ -76,7 +76,9 @@ pub fn start_rendering(
sender: Sender<Result<RenderInfo, RenderError>>,
receiver: Receiver<RenderNotif>,
size: WindowSize,
prerender: PrerenderLimit
prerender: PrerenderLimit,
black: i32,
white: i32
) -> Result<(), SendError<Result<RenderInfo, RenderError>>> {
// We want this outside of 'reload so that if the doc reloads, the search term that somebody
// set will still get highlighted in the reloaded doc
@@ -282,6 +284,8 @@ pub fn start_rendering(
search_term.as_deref(),
rendered,
invert,
black,
white,
(area_w, area_h)
) {
// If that fn returned Some, that means it needed to be re-rendered for some
@@ -421,6 +425,8 @@ fn render_single_page_to_ctx(
search_term: Option<&str>,
prev_render: &PrevRender,
invert: bool,
black: i32,
white: i32,
(area_w, area_h): (f32, f32)
) -> Result<RenderedContext, mupdf::error::Error> {
let result_rects = match prev_render.num_search_found {
@@ -461,7 +467,9 @@ fn render_single_page_to_ctx(
let mut pixmap = page.to_pixmap(&matrix, &colorspace, false, false)?;
if invert {
pixmap.invert()?;
pixmap.tint(white, black)?;
} else {
pixmap.tint(black, white)?;
}
let (x_res, y_res) = pixmap.resolution();