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:
ZacharyZhang-NYandClaude committed 2026-10-18 19:42:13 -04:00
1 parent d4cb274749
commit 6f1eebb4b5
42 files changed
+204 -209

No files matched your search

+6 -18
View File
@@ -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");
}
}
+5 -7
View File
@@ -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]
+1 -1
View File
@@ -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;
+4 -4
View File
@@ -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,
+3 -3
View File
@@ -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).
+13 -25
View File
@@ -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());
+49 -23
View File
@@ -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]
+1 -3
View File
@@ -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++)
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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)?;
+1 -2
View File
@@ -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 {
+1 -1
View File
@@ -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()
}
+1 -1
View File
@@ -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))
}
+5 -5
View File
@@ -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");
}
+6 -6
View File
@@ -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);
+3 -3
View File
@@ -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");
}
+3 -11
View File
@@ -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:?}");
}