R8.1: document content keeps the file's colours in a dark app
Pages, cells, slides and PDF pages paint as the file says in any appearance; only the chrome around them follows dark mode. The kernel keeps Ely's one light scheme, sent once a view, and MuPDF no longer inverts. Reviews now run gpt-6.1-sol at xhigh. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
42 files changed
+204
-209
No files matched your search
@@ -350,7 +350,7 @@ fn brightness(tile: &Tile) -> u32 {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_page_follows_a_dark_theme_and_back() {
|
||||
fn ely_scheme_paints_the_page_white() {
|
||||
let Some(install) = install() else {
|
||||
eprintln!("SKIP: no pinned LOK build");
|
||||
return;
|
||||
@@ -363,23 +363,11 @@ fn the_page_follows_a_dark_theme_and_back() {
|
||||
let doc = worker
|
||||
.load(&crate::file_url(&source))
|
||||
.expect("the document loads");
|
||||
let area = (1440, 1440, 3840, 3840);
|
||||
let seen = poll_until(&mut worker, &doc, &Events::default(), QUIET, |_| false);
|
||||
let light = brightness(&doc.paint_tile(&mut worker, area, (64, 64)).expect("a tile"));
|
||||
let paint = |worker: &mut Worker, scheme: &str, seen: &Events| {
|
||||
worker.run(&doc, "view.theme", &[scheme]).expect("a theme");
|
||||
let repainted = poll_until(worker, &doc, seen, SETTLE, |seen| seen.all);
|
||||
assert!(repainted.all, "{name}: {scheme} repaints the view");
|
||||
let tile = doc.paint_tile(worker, area, (64, 64)).expect("a tile");
|
||||
(brightness(&tile), repainted)
|
||||
};
|
||||
let (dark, seen) = paint(&mut worker, "COLOR_SCHEME_ELY_DARK", &seen);
|
||||
let (back, _) = paint(&mut worker, "COLOR_SCHEME_ELY_LIGHT", &seen);
|
||||
eprintln!("THEME {name} light {light} dark {dark} back {back}");
|
||||
assert!(
|
||||
light > 200 && dark < 100 && back > 200,
|
||||
"{name}: {light} {dark} {back}"
|
||||
);
|
||||
poll_until(&mut worker, &doc, &Events::default(), QUIET, |_| false);
|
||||
worker.run(&doc, "view.theme", &["COLOR_SCHEME_ELY_LIGHT"]).expect("the scheme");
|
||||
let tile = doc.paint_tile(&mut worker, (1440, 1440, 3840, 3840), (64, 64)).expect("a tile");
|
||||
let shade = brightness(&tile);
|
||||
assert!(shade > 200, "{name}: the page is light, {shade}");
|
||||
worker.close_doc(doc).expect("the document closes");
|
||||
}
|
||||
}
|
||||
@@ -182,18 +182,16 @@ pub(super) fn open_book(text: &str) -> (tempfile::TempDir, Worker, Doc) {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_theme_switch_is_no_edit() {
|
||||
fn the_scheme_is_no_edit() {
|
||||
if install().is_none() {
|
||||
eprintln!("SKIP: no pinned LOK build");
|
||||
return;
|
||||
}
|
||||
let (_dir, mut worker, doc) = open_book(FODS);
|
||||
for scheme in ["COLOR_SCHEME_ELY_DARK", "COLOR_SCHEME_ELY_LIGHT"] {
|
||||
worker.run(&doc, "view.theme", &[scheme]).expect("the theme runs");
|
||||
let undo = worker.values(&doc, ".uno:Undo").expect("the undo stack");
|
||||
let undo: serde_json::Value = serde_json::from_str(&undo).expect("undo JSON");
|
||||
assert_eq!(undo["actions"], "", "{scheme} left undo steps");
|
||||
}
|
||||
worker.run(&doc, "view.theme", &["COLOR_SCHEME_ELY_LIGHT"]).expect("the scheme runs");
|
||||
let undo = worker.values(&doc, ".uno:Undo").expect("the undo stack");
|
||||
let undo: serde_json::Value = serde_json::from_str(&undo).expect("undo JSON");
|
||||
assert_eq!(undo["actions"], "", "the scheme left undo steps");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -21,7 +21,7 @@ pub use client::{
|
||||
#[cfg(feature = "view")]
|
||||
pub use view::{
|
||||
CONTEXT, Copy, Cut, Geom, Layout, LokError, LokView, Paste, Reported, ZOOM_STEPS, notch,
|
||||
Zoomed, init, layout, paper, read_off, scheme,
|
||||
SCHEME, Zoomed, init, layout, paper, read_off,
|
||||
};
|
||||
#[cfg(feature = "view")]
|
||||
mod view;
|
||||
|
||||
@@ -32,7 +32,7 @@ mod scroll;
|
||||
mod sheet;
|
||||
pub use input::{CONTEXT, Copy, Cut, Paste, init};
|
||||
pub use off::read_off;
|
||||
pub use render::{paper, scheme};
|
||||
pub use render::{SCHEME, paper};
|
||||
mod turn;
|
||||
pub use turn::notch;
|
||||
|
||||
@@ -123,8 +123,8 @@ pub struct LokView {
|
||||
pointer: gpui::CursorStyle,
|
||||
selection: Vec<Rect>,
|
||||
cell: crate::Cell,
|
||||
/// Whether the kernel was last told to paint dark.
|
||||
dark: Option<bool>,
|
||||
/// Whether the kernel was told Ely's scheme.
|
||||
lit: bool,
|
||||
/// The zoom follows the viewport so a page fits.
|
||||
fit: bool,
|
||||
/// Set when the wheel and Up, Down turn parts.
|
||||
@@ -218,7 +218,7 @@ impl LokView {
|
||||
pointer: gpui::CursorStyle::Arrow,
|
||||
selection: Vec::new(),
|
||||
cell: crate::Cell::default(),
|
||||
dark: None,
|
||||
lit: false,
|
||||
fit: false,
|
||||
turning: None,
|
||||
part: 0,
|
||||
|
||||
@@ -6,9 +6,9 @@ use super::LokView;
|
||||
use crate::Rect;
|
||||
|
||||
impl LokView {
|
||||
/// Whether the kernel paints dark; None before the first frame.
|
||||
pub fn dark(&self) -> Option<bool> {
|
||||
self.dark
|
||||
/// Whether the kernel was told Ely's scheme.
|
||||
pub fn lit(&self) -> bool {
|
||||
self.lit
|
||||
}
|
||||
|
||||
/// The kernel's state for `uno`, as LOK reports it (LOK-05).
|
||||
|
||||
@@ -15,33 +15,21 @@ use gpui::{Pixels, RenderImage, point};
|
||||
use super::{CONTEXT, LokView, TILE_TWIPS, TWIPS_PER_PIXEL, handles, input};
|
||||
use crate::Rect;
|
||||
|
||||
/// Ely's kernel color schemes, from `ely.xcd`.
|
||||
const DARK: &str = "COLOR_SCHEME_ELY_DARK";
|
||||
const LIGHT: &str = "COLOR_SCHEME_ELY_LIGHT";
|
||||
/// Ely's kernel color scheme, from `ely.xcd`.
|
||||
pub const SCHEME: &str = "COLOR_SCHEME_ELY_LIGHT";
|
||||
|
||||
/// The kernel scheme for a light or dark app.
|
||||
pub fn scheme(dark: bool) -> &'static str {
|
||||
if dark { DARK } else { LIGHT }
|
||||
}
|
||||
|
||||
/// A page's colour; the kernel's Ely schemes share it.
|
||||
pub fn paper(cx: &gpui::App) -> gpui::Hsla {
|
||||
let theme = cx.theme();
|
||||
if theme.is_dark() {
|
||||
theme.colors.surface
|
||||
} else {
|
||||
theme.colors.paper
|
||||
}
|
||||
/// A page's colour, the scheme's `DocColor`.
|
||||
pub fn paper() -> gpui::Hsla {
|
||||
gpui::white()
|
||||
}
|
||||
|
||||
impl LokView {
|
||||
/// Paints with the app's light or dark scheme.
|
||||
pub(super) fn follow_theme(&mut self, dark: bool) {
|
||||
if self.dark != Some(dark) {
|
||||
self.dark = Some(dark);
|
||||
let scheme = scheme(dark);
|
||||
log::info!("lok: paints with {scheme}");
|
||||
self.send(input::Input::Theme(scheme));
|
||||
/// Content keeps the file's colours in any app theme.
|
||||
pub(super) fn paint_light(&mut self) {
|
||||
if !self.lit {
|
||||
self.lit = true;
|
||||
log::info!("lok: paints with {SCHEME}");
|
||||
self.send(input::Input::Theme(SCHEME));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,11 +41,11 @@ impl Render for LokView {
|
||||
self.keep_scroll(|view| view.geom.dpi = dpi);
|
||||
self.retire_tiles();
|
||||
}
|
||||
self.follow_theme(cx.theme().is_dark());
|
||||
self.paint_light();
|
||||
let this = cx.entity().clone();
|
||||
let focus = self.focus.clone();
|
||||
let colors = &cx.theme().colors;
|
||||
let paper = super::paper(cx);
|
||||
let paper = super::paper();
|
||||
let (selection_color, caret_color) = (colors.selection, colors.focus);
|
||||
let canvas_color = colors.sunken;
|
||||
let caret_width = cx.theme().caret_width().to_pixels(window.rem_size());
|
||||
|
||||
@@ -24,37 +24,63 @@ fn area() -> Bounds<Pixels> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A user profile whose dark scheme paints the page black.
|
||||
const DARK_PROFILE: &str = r#"<?xml version="1.0" encoding="UTF-8"?>
|
||||
<oor:items xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<item oor:path="/org.openoffice.Office.UI/ColorScheme/ColorSchemes"><node oor:name="TEST_DARK" oor:op="replace"><node oor:name="DocColor"><prop oor:name="Color" oor:op="fuse"><value>0</value></prop></node></node></item>
|
||||
</oor:items>
|
||||
"#;
|
||||
|
||||
/// Shows a view in a window.
|
||||
struct Host(Entity<LokView>);
|
||||
|
||||
impl gpui::Render for Host {
|
||||
fn render(&mut self, _: &mut gpui::Window, _: &mut gpui::Context<Self>) -> impl gpui::IntoElement {
|
||||
self.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_view_paints_the_app_theme_and_back() {
|
||||
fn a_dark_app_paints_the_page_white() {
|
||||
let Some(install) = crate::client::tests::install() else {
|
||||
eprintln!("SKIP: no pinned LOK build");
|
||||
return;
|
||||
};
|
||||
let cx = TestAppContext::single();
|
||||
let (view, worker) = cx.update(|app| live_view(app, &install));
|
||||
let doc = cx.update(|app| view.read(app).doc.clone());
|
||||
let mut shades = Vec::new();
|
||||
for dark in [true, false] {
|
||||
cx.update(|app| view.update(app, |view, _| view.follow_theme(dark)));
|
||||
assert!(
|
||||
settle(&cx, |app| view.read(app).settled()),
|
||||
"the theme goes out"
|
||||
);
|
||||
let mut cx = TestAppContext::single();
|
||||
cx.update(|app| {
|
||||
ely_gpui_component::init_for_tests(app);
|
||||
ely_gpui_component::theme::Theme::set_mode_now(ely_gpui_component::theme::Mode::Dark, app);
|
||||
});
|
||||
// A dark profile, as an old Ely left.
|
||||
let dir = tempfile::tempdir().expect("a temp dir");
|
||||
let profile = dir.path().join("profile");
|
||||
std::fs::create_dir_all(profile.join("user")).expect("a profile");
|
||||
std::fs::write(profile.join("user/registrymodifications.xcu"), DARK_PROFILE).expect("the scheme writes");
|
||||
let source = dir.path().join("note.fodt");
|
||||
std::fs::write(&source, crate::client::tests::FODT).expect("the fixture writes");
|
||||
let mut started = crate::Worker::spawn(&install, &profile).expect("the worker");
|
||||
let doc = started.load(&crate::file_url(&source)).expect("the document loads");
|
||||
let laid = super::super::layout(&mut started, &doc).expect("the layout reads");
|
||||
let worker = Arc::new(Mutex::new(started));
|
||||
let shade = || {
|
||||
let mut worker = worker.lock().expect("the worker");
|
||||
let tile = doc
|
||||
.paint_tile(&mut worker, (1440, 1440, 3840, 3840), (64, 64))
|
||||
.expect("a tile");
|
||||
let sum: u64 = tile
|
||||
.pixels
|
||||
.chunks_exact(4)
|
||||
.map(|px| u64::from(px[0]) + u64::from(px[1]) + u64::from(px[2]))
|
||||
.sum();
|
||||
shades.push(sum / (64 * 64 * 3));
|
||||
}
|
||||
let tile = doc.paint_tile(&mut worker, (1440, 1440, 3840, 3840), (64, 64)).expect("a tile");
|
||||
let sum: u64 = tile.pixels.chunks_exact(4).map(|px| u64::from(px[0]) + u64::from(px[1]) + u64::from(px[2])).sum();
|
||||
sum / (64 * 64 * 3)
|
||||
};
|
||||
worker.lock().expect("the worker").run(&doc, "view.theme", &["TEST_DARK"]).expect("the dark scheme");
|
||||
let dark = shade();
|
||||
assert!(dark < 100, "the kernel starts dark: {dark}");
|
||||
let view = cx.update(|app| LokView::open(Arc::clone(&worker), doc.clone(), laid, app));
|
||||
let shown = view.clone();
|
||||
cx.add_window(move |_, _| Host(shown));
|
||||
assert!(
|
||||
shades[0] < 100 && shades[1] > 200,
|
||||
"dark then light: {shades:?}"
|
||||
settle(&cx, |app| view.read(app).lit() && view.read(app).settled()),
|
||||
"the scheme goes out"
|
||||
);
|
||||
assert_eq!(paper(), gpui::white(), "the page mask is the scheme's white");
|
||||
let light = shade();
|
||||
assert!(light > 240, "the view paints the page white: {light}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -224,7 +224,7 @@ static fz_matrix placed(fz_rect box, float scale, int rotate)
|
||||
|
||||
/* Paints device pixels x, y, w, h as BGRA. */
|
||||
int ely_render(fz_context *ctx, fz_document *doc, int number, float scale, int rotate,
|
||||
const int tile[4], int dark, unsigned char *bgra)
|
||||
const int tile[4], unsigned char *bgra)
|
||||
{
|
||||
fz_page *page = NULL;
|
||||
fz_pixmap *pix = NULL;
|
||||
@@ -242,8 +242,6 @@ int ely_render(fz_context *ctx, fz_document *doc, int number, float scale, int r
|
||||
dev = fz_new_draw_device(ctx, fz_identity, pix);
|
||||
fz_run_page(ctx, page, dev, ctm, NULL);
|
||||
fz_close_device(ctx, dev);
|
||||
if (dark)
|
||||
fz_invert_pixmap_luminance(ctx, pix);
|
||||
int stride = (int)fz_pixmap_stride(ctx, pix);
|
||||
unsigned char *rows = fz_pixmap_samples(ctx, pix);
|
||||
for (int y = 0; y < tile[3]; y++)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
int ely_fail(fz_context *ctx);
|
||||
const char *ely_error(void);
|
||||
int ely_render(fz_context *ctx, fz_document *doc, int number, float scale, int rotate, const int tile[4], int dark,
|
||||
int ely_render(fz_context *ctx, fz_document *doc, int number, float scale, int rotate, const int tile[4],
|
||||
unsigned char *bgra);
|
||||
void ely_fail_also(fz_context *ctx, const char *what);
|
||||
pdf_document *ely_pdf_of(fz_context *ctx, fz_document *doc);
|
||||
|
||||
@@ -244,7 +244,7 @@ static void preview(fz_context *ctx, pdf_document *pdf, int number, int block, c
|
||||
tile[0] = (int)floorf(region.x0 * scale), tile[1] = (int)floorf(region.y0 * scale);
|
||||
tile[2] = (int)ceilf(region.x1 * scale) - tile[0], tile[3] = (int)ceilf(region.y1 * scale) - tile[1];
|
||||
*pixels = fz_malloc(ctx, (size_t)tile[2] * tile[3] * 4);
|
||||
if (ely_render(ctx, copy, number, scale, 0, tile, 0, *pixels) < 0)
|
||||
if (ely_render(ctx, copy, number, scale, 0, tile, *pixels) < 0)
|
||||
fz_throw(ctx, FZ_ERROR_GENERIC, "%s", ely_error());
|
||||
*w = tile[2], *h = tile[3];
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ unsafe extern "C" {
|
||||
scale: f32,
|
||||
rotate: c_int,
|
||||
tile: *const c_int,
|
||||
dark: c_int,
|
||||
bgra: *mut u8,
|
||||
) -> c_int;
|
||||
fn ely_text(
|
||||
@@ -143,7 +142,6 @@ impl Mupdf {
|
||||
number: usize,
|
||||
(scale, rotate): (f32, i32),
|
||||
tile: [i32; 4],
|
||||
dark: bool,
|
||||
) -> io::Result<Vec<u8>> {
|
||||
let (w, h) = (usize::try_from(tile[2]), usize::try_from(tile[3]));
|
||||
let (Ok(w), Ok(h)) = (w, h) else {
|
||||
@@ -158,7 +156,6 @@ impl Mupdf {
|
||||
scale,
|
||||
rotate,
|
||||
tile.as_ptr(),
|
||||
c_int::from(dark),
|
||||
pixels.as_mut_ptr(),
|
||||
)
|
||||
};
|
||||
|
||||
@@ -403,8 +403,7 @@ impl Worker {
|
||||
for value in &mut tile {
|
||||
*value = i32::try_from(ask.i64()?).map_err(io::Error::other)?;
|
||||
}
|
||||
let dark = ask.u64()? != 0;
|
||||
self.drawn(id, page, (scale, rotate), tile, dark)
|
||||
self.drawn(id, page, (scale, rotate), tile)
|
||||
}
|
||||
tag::TEXT => {
|
||||
let (id, page) = (ask.u64()?, ask.u64()? as usize);
|
||||
|
||||
@@ -101,9 +101,9 @@ impl crate::Worker {
|
||||
}
|
||||
|
||||
/// A tile, and whether drawing it met damage.
|
||||
pub(crate) fn drawn(&mut self, id: u64, page: usize, view: (f32, i32), tile: [i32; 4], dark: bool) -> io::Result<Vec<u8>> {
|
||||
pub(crate) fn drawn(&mut self, id: u64, page: usize, view: (f32, i32), tile: [i32; 4]) -> io::Result<Vec<u8>> {
|
||||
unsafe { ely_watch_begin(self.mupdf.ctx) };
|
||||
let pixels = self.mupdf.render(self.doc(id)?, page, view, tile, dark);
|
||||
let pixels = self.mupdf.render(self.doc(id)?, page, view, tile);
|
||||
let warned = unsafe { ely_watch_end(self.mupdf.ctx) } != 0;
|
||||
if warned {
|
||||
self.note_damage(id)?;
|
||||
|
||||
@@ -242,7 +242,6 @@ impl Worker {
|
||||
page: usize,
|
||||
(scale, rotate): (f32, i32),
|
||||
tile: [i32; 4],
|
||||
dark: bool,
|
||||
) -> io::Result<Tile> {
|
||||
let mut ask = self.on(&doc)?
|
||||
.u64(page as u64)
|
||||
@@ -251,7 +250,7 @@ impl Worker {
|
||||
for value in tile {
|
||||
ask = ask.i64(i64::from(value));
|
||||
}
|
||||
let reply = self.request(tag::RENDER, &ask.u64(u64::from(dark)).bytes())?;
|
||||
let reply = self.request(tag::RENDER, &ask.bytes())?;
|
||||
let mut reply = Unpack::new(&reply);
|
||||
let (damaged, bgra) = (reply.u64()? != 0, reply.blob()?);
|
||||
match bgra.len() == tile[2] as usize * tile[3] as usize * 4 {
|
||||
|
||||
@@ -257,7 +257,7 @@ fn long_clashing_field_names_still_get_a_number() {
|
||||
|
||||
/// Red pixels of a page at one pixel a point.
|
||||
fn red(worker: &mut Worker, doc: Doc, page: usize) -> usize {
|
||||
let pixels = worker.render(doc, page, (1.0, 0), [0, 0, 612, 792], false).expect("renders").bgra;
|
||||
let pixels = worker.render(doc, page, (1.0, 0), [0, 0, 612, 792]).expect("renders").bgra;
|
||||
pixels.chunks_exact(4).filter(|p| p[2] > 180 && p[1] < 80 && p[0] < 80).count()
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ fn note(page: usize, shape: Shape) -> NewAnnot {
|
||||
|
||||
/// Whether page one's pixels `at` hold colour `bgra`.
|
||||
fn has_color(worker: &mut Worker, doc: Doc, at: [i32; 4], bgra: [u8; 3]) -> bool {
|
||||
let pixels = worker.render(doc, 0, (1.0, 0), at, false).expect("draws").bgra;
|
||||
let pixels = worker.render(doc, 0, (1.0, 0), at).expect("draws").bgra;
|
||||
pixels.chunks_exact(4).any(|p| p[..3].iter().zip(bgra).all(|(a, b)| a.abs_diff(b) < 40))
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ const SCALE: f32 = 200.0 / 72.0;
|
||||
/// Page one of `doc`, saved as a gray scan.
|
||||
fn scan_of(worker: &mut Worker, doc: Doc, out: PathBuf) -> PathBuf {
|
||||
let (w, h) = ((612.0 * SCALE).ceil() as i32, (792.0 * SCALE).ceil() as i32);
|
||||
let bgra = worker.render(doc, 0, (SCALE, 0), [0, 0, w, h], false).expect("draws").bgra;
|
||||
let bgra = worker.render(doc, 0, (SCALE, 0), [0, 0, w, h]).expect("draws").bgra;
|
||||
let gray: Vec<u8> = bgra.chunks_exact(4).map(|p| ((u16::from(p[0]) + u16::from(p[1]) + u16::from(p[2])) / 3) as u8).collect();
|
||||
std::fs::write(&out, scan((612.0, 792.0), (w as u32, h as u32), &gray)).expect("writes");
|
||||
out
|
||||
@@ -49,12 +49,12 @@ fn a_scan_reads_and_its_text_layer_finds_without_drawing() {
|
||||
assert!(read.iter().any(|l| l.contains("Hello world")) && read.iter().any(|l| l.contains("Second line")), "{read:?}");
|
||||
let hello = lines.iter().find(|l| l.text.contains("Hello")).expect("hello");
|
||||
assert!((hello.rect[0] - 72.0).abs() < 6.0 && (hello.rect[3] - 76.0).abs() < 8.0, "in page points: {:?}", hello.rect);
|
||||
let before = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792], false).expect("draws").bgra;
|
||||
let before = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792]).expect("draws").bgra;
|
||||
let mark = worker.text_layer(doc, &[(0, lines)], false).expect("lays");
|
||||
doc = worker.now(doc).expect("the state");
|
||||
assert!(words(&mut worker, doc).contains("Hello world"), "searchable now");
|
||||
assert_eq!(worker.search(doc, 0, "second line").expect("finds").len(), 1);
|
||||
assert!(worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792], false).expect("draws").bgra == before, "nothing drawn");
|
||||
assert!(worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792]).expect("draws").bgra == before, "nothing drawn");
|
||||
worker.undo(doc, false).expect("undoes");
|
||||
doc = worker.now(doc).expect("the state");
|
||||
assert_eq!(words(&mut worker, doc), "", "one step");
|
||||
@@ -144,9 +144,9 @@ fn text_added_after_a_layer_still_shows() {
|
||||
let line = OcrLine { rect: [72.0, 60.0, 200.0, 78.0], text: "Hello world".into() };
|
||||
worker.text_layer(doc, &[(0, vec![line])], false).expect("lays");
|
||||
doc = worker.now(doc).expect("the state");
|
||||
let before = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792], false).expect("draws").bgra;
|
||||
let before = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792]).expect("draws").bgra;
|
||||
let writing = Writing { block: None, expected: String::new(), text: "VISIBLE".into(), font: "helvetica".into(), size: 24.0, rgb: 0, bx: [72.0, 600.0, 300.0] };
|
||||
assert!(matches!(worker.put_text(doc, 0, &writing, 0.0).expect("writes"), Wrote::Done(_)));
|
||||
doc = worker.now(doc).expect("the state");
|
||||
assert!(worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792], false).expect("draws").bgra != before, "the new text is drawn");
|
||||
assert!(worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792]).expect("draws").bgra != before, "the new text is drawn");
|
||||
}
|
||||
@@ -199,7 +199,7 @@ fn a_print_copy_shows_what_prints_to_any_screen_renderer() {
|
||||
// MuPDF draws by screen rules, as Windows' renderer does.
|
||||
let mut third = self::worker();
|
||||
let printed = third.open(&print).expect("opens").doc;
|
||||
let bgra = third.render(printed, 0, (1.0, 0), [0, 0, 612, 792], false).expect("draws").bgra;
|
||||
let bgra = third.render(printed, 0, (1.0, 0), [0, 0, 612, 792]).expect("draws").bgra;
|
||||
let at = |x: usize, y: usize| -> [u8; 3] {
|
||||
let p = &bgra[((792 - y) * 612 + x) * 4..][..3];
|
||||
[p[2], p[1], p[0]]
|
||||
@@ -219,7 +219,7 @@ fn a_broken_picture_shows_when_drawn_or_checked() {
|
||||
std::fs::write(&path, &bytes).expect("writes");
|
||||
let (mut worker, doc) = opened(&path);
|
||||
assert_eq!(worker.repair_report(doc).expect("asks"), None, "pictures wait to be drawn");
|
||||
let tile = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792], false).expect("draws");
|
||||
let tile = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792]).expect("draws");
|
||||
assert!(tile.damaged, "drawing finds it");
|
||||
assert!(worker.repair_report(doc).expect("asks").is_some());
|
||||
let (mut other, again) = opened(&path);
|
||||
@@ -249,7 +249,7 @@ fn an_unembedded_font_is_no_damage() {
|
||||
let (mut worker, doc) = opened(&path);
|
||||
// Read unwatched first: its repeat is pending.
|
||||
worker.text(doc, 0).expect("reads");
|
||||
let tile = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792], false).expect("draws");
|
||||
let tile = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792]).expect("draws");
|
||||
assert!(!tile.damaged, "a substituted font draws whole");
|
||||
assert_eq!(worker.repair_report(doc).expect("asks"), None);
|
||||
}
|
||||
@@ -262,7 +262,7 @@ fn unreadable_content_still_draws_as_damage() {
|
||||
let path = dir.path().join("doc.pdf");
|
||||
std::fs::write(&path, one_page("", "", content, &[])).expect("writes");
|
||||
let (mut worker, doc) = opened(&path);
|
||||
let tile = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792], false).expect("draws");
|
||||
let tile = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792]).expect("draws");
|
||||
assert!(tile.damaged, "{content} draws as damage");
|
||||
}
|
||||
}
|
||||
@@ -327,7 +327,7 @@ fn a_broken_picture_under_two_filters_fails_exports() {
|
||||
let (mut worker, doc) = opened(&path);
|
||||
assert!(worker.export_image(doc, 0, 72.0, &dir.path().join("page.png")).is_err(), "its page read whole");
|
||||
let (mut worker, doc) = opened(&path);
|
||||
let tile = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792], false).expect("draws");
|
||||
let tile = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792]).expect("draws");
|
||||
assert!(tile.damaged, "the picture draws as damage");
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ fn a_broken_picture_read_before_is_still_damage() {
|
||||
for (path, first) in files.iter().flat_map(|p| read.map(|r| (p, r))) {
|
||||
let (mut worker, doc) = opened(path);
|
||||
first(&mut worker, doc);
|
||||
let tile = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792], false).expect("draws");
|
||||
let tile = worker.render(doc, 0, (1.0, 0), [0, 0, 612, 792]).expect("draws");
|
||||
assert!(tile.damaged, "the picture draws as damage");
|
||||
assert!(worker.repair_report(doc).expect("asks").is_some());
|
||||
let (mut worker, doc) = opened(path);
|
||||
|
||||
@@ -67,9 +67,9 @@ fn a_picture_under_a_region_loses_those_pixels() {
|
||||
let out = dir.path().join("out.pdf");
|
||||
worker.redact(doc, &[Region { page: 0, rect: [72.0, 242.0, 122.0, 292.0] }], &out).expect("removes");
|
||||
let (mut other, written) = reopen(&out);
|
||||
let left = other.render(written, 0, (1.0, 0), [124, 244, 46, 46], false).expect("draws").bgra;
|
||||
let left = other.render(written, 0, (1.0, 0), [124, 244, 46, 46]).expect("draws").bgra;
|
||||
assert!(left.chunks_exact(4).any(|p| p[0] > 100 || p[1] > 100 || p[2] > 100), "the right half keeps its colour");
|
||||
let gone = other.render(written, 0, (1.0, 0), [74, 244, 46, 46], false).expect("draws").bgra;
|
||||
let gone = other.render(written, 0, (1.0, 0), [74, 244, 46, 46]).expect("draws").bgra;
|
||||
assert!(gone.chunks_exact(4).all(|p| p[0] < 40 && p[1] < 40 && p[2] < 40), "the left half is black");
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ fn a_shape_touching_a_region_goes_whole() {
|
||||
let report = worker.redact(doc, &[Region { page: 0, rect: [90.0, 45.0, 180.0, 100.0] }], &out).expect("removes");
|
||||
assert_eq!(report.objects, 0);
|
||||
let (mut other, read) = reopen(&out);
|
||||
let right = other.render(read, 0, (1.0, 0), [200, 55, 90, 30], false).expect("draws").bgra;
|
||||
let right = other.render(read, 0, (1.0, 0), [200, 55, 90, 30]).expect("draws").bgra;
|
||||
assert!(right.chunks_exact(4).all(|p| p[2] < 200 || p[1] > 200), "no red left past the box");
|
||||
}
|
||||
|
||||
|
||||
@@ -36,23 +36,15 @@ fn pages_measure_render_and_read_their_text() {
|
||||
);
|
||||
// Page one's top left, twice its size: text is dark.
|
||||
let tile = worker
|
||||
.render(doc, 0, (2.0, 0), [0, 0, 600, 300], false)
|
||||
.render(doc, 0, (2.0, 0), [0, 0, 600, 300])
|
||||
.expect("renders").bgra;
|
||||
assert_eq!(tile.len(), 600 * 300 * 4);
|
||||
let dark = tile.chunks_exact(4).filter(|p| p[0] < 128).count();
|
||||
assert!(dark > 100, "text shows: {dark}");
|
||||
let night = worker
|
||||
.render(doc, 0, (2.0, 0), [0, 0, 600, 300], true)
|
||||
.expect("renders dark").bgra;
|
||||
let light = night.chunks_exact(4).filter(|p| p[0] > 128).count();
|
||||
assert!(
|
||||
light > 100 && night[0] < 64,
|
||||
"dark mode turns paper dark and text light"
|
||||
);
|
||||
// A quarter turn makes the page tall side wide.
|
||||
assert!(
|
||||
worker
|
||||
.render(doc, 1, (1.0, 90), [0, 0, 595, 842], false)
|
||||
.render(doc, 1, (1.0, 90), [0, 0, 595, 842])
|
||||
.is_ok()
|
||||
);
|
||||
let text: String = worker
|
||||
@@ -135,7 +127,7 @@ fn a_thousand_pages_show_the_first_in_time() {
|
||||
assert_eq!(worker.pages(doc).expect("counts"), 1000);
|
||||
// What the viewer asks before its first frame.
|
||||
worker.bounds(doc, 0, 100).expect("the first sizes");
|
||||
worker.render(doc, 0, (2.0, 0), [0, 0, 512, 512], false).expect("the first tile");
|
||||
worker.render(doc, 0, (2.0, 0), [0, 0, 512, 512]).expect("the first tile");
|
||||
let took = started.elapsed();
|
||||
assert!(took < std::time::Duration::from_secs(3), "PERF-05: {took:?}");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user