docs: 0.2.6.3 — what was measured, the manual, and Sunday's checks

Why black and white is made with Ghostscript and how close it is to what
Elmer prints; why Print image goes through the engine's copy image, with
the table of what each other way failed on; what it cannot reach (a CSS
background picture) and what it costs (the clipboard lives in Wonder Ink
afterwards). The manual says Print page and Print image, and that the
preview turns grey. Sunday's paper checks for both, in testing.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ekklesia
2026-09-26 16:34:38 -05:00
co-authored by Claude Opus 5.5
parent cb12e59dea
commit f9a0ee08f9
7 changed files with 224 additions and 20 deletions
+139 -3
View File
@@ -71,7 +71,8 @@ wrong a teacher is standing in front of a class.
The right-click menu is built rather than filtered, so a future Qt cannot
grow view-source or save-page back into it without somebody noticing in
the code: back, forward, reload, open in a new tab when there is a link,
cut/copy/paste in a text field, print.
cut/copy/paste in a text field, print image when there is a picture under
the pointer, print page.
Keys: Ctrl+W closes a tab, Alt+Left and Alt+Right navigate, Ctrl+P prints,
Ctrl+Tab switches. Ctrl+T, Ctrl+N and Ctrl+L are deliberately unbound.
@@ -232,8 +233,9 @@ One dialog, for lessons and worksheets alike:
* **Pages** — all, or some: `2`, `1-3`, `1, 3, 5-6`, checked against the
document with the reason given if wrong;
* **Copies** — 1 to 50;
* **Colour** — colour or black and white, only where the printer's driver
has a grey mode, and asked for in that driver's own terms;
* **Color** — colour or black and white, only where the printer's driver
has a grey mode, and asked for in that driver's own terms. Since 0.2.6.3
the preview turns grey too (below);
* **Cancel** sends nothing; **Print** returns to the lesson once CUPS has
the job, and a notification says where it went. A refused job keeps the
preview open with CUPS's reason.
@@ -280,6 +282,140 @@ background is left off, measured.
Temporary PDFs live in the teacher's `$XDG_RUNTIME_DIR` and are removed
when the preview closes.
### Black and white is shown as it prints (0.2.6.3)
Printing through Elmer found that **Black and white** came out grey on
paper while the preview stayed in colour. 0.2.6.2 only told the driver:
the preview was the colour PDF, CUPS was given the colour PDF, and
`ColorModel=Grayscale` turned it grey inside Elmer's filters.
So black and white is now made before the preview, not after it. When it
is chosen, the preview makes a grey copy of the document with
Ghostscript, shows that copy, and Print hands CUPS that same file — still
with `ColorModel=Grayscale`, so Elmer's generic PCL 6 driver prints it
with `pxlmono` as before rather than as a colour job that happens to be
grey. Choosing **Color** shows and prints the colour document again.
Measured before building it (Ghostscript 10.05.1, in the lab):
| | |
| --- | --- |
| a lesson page, a picture page, a leader guide, a fillable form | grey and only grey; same pages, page sizes and words; text still text; a filled-in form field and a drawn mark kept, in grey |
| against what Elmer would have printed | Ghostscript's grey rendering of the colour original and of the grey copy give the **same greys**: within 1 level in 255 on every filled area and picture. Small text can land a fraction of a pixel over — on a real lesson page, 12 of 32,754 8×8 blocks, all on one line of body text, in pairs of opposite sign. Elmer's driver *is* Ghostscript. (poppler's own grey differs on 7% of a coloured page, which is why the copy is not made with poppler) |
| how long | 0.05 s for a worksheet, 0.2 s for a text lesson page, 1.3 s for a full-page photograph, 2 s for 42 pages — and **4.4 s** for one lesson page with eleven full-size pictures, under the real Plasma session. `-dUseFastColor` saves 40% and changes the greys, so it is not used |
| a PDF Ghostscript cannot read | exits 1 and **still leaves a file behind** |
From those:
* the copy is made in the background, the preview says *Preparing black
and white…* and Print waits for it — four seconds is long enough to
look like a frozen window. It has a minute before it is given up on,
not the 20 s a page render has: a lesson of photographs on a slower
laptop is slow, not stuck. Cancel stops it at once;
* it is made once per document and kept, and each drawn page is kept, so
turning Color and Black and white back and forth is instant after the
first time, and stays on the page the teacher was looking at;
* a conversion is judged by its exit status and its page count, never by
whether a file appeared. If it fails the preview says so and offers
Color. It **never prints the colour file in its place**: the teacher
asked for black and white;
* pages are never turned (pdfwrite otherwise rotates a page to match its
text), and annotations are drawn into the page as they print, so no
later filter can draw them again in colour;
* a printer whose driver has no grey mode is not offered black and white,
and choosing one returns the preview to colour.
`tools/lab/wonderink-print-check` shows a colourful lesson in colour,
turns it to black and white and back five times on page 2, and prints
page 2 twice: every grey preview is grey pixel for pixel, every colour
one is not, the grey copy is made once, and the job CUPS kept is
**byte-for-byte the file the preview showed**, grey on every page, sent
with `ColorModel=Grayscale` through `pxlmono`. The same for a worksheet,
a 50% top-left picture, a return to Color (which prints in colour through
`pxlcolor`), and Cancel.
### Print image: a picture from inside a lesson (0.2.6.3)
Right-clicking a picture in a lesson and choosing Print printed the whole
page around it. Some of Wonder Ink's pictures cannot be opened on their
own through the site at all, so a teacher had no way to give that
picture the picture layout 0.2.6.2 introduced.
The right-click menu now says what it will print. It asks the engine's
own hit test what is under the pointer:
| Under the pointer | Measured `mediaType` | The menu offers |
| --- | --- | --- |
| a picture (`<img>`, also inside a link, a frame, from `blob:` or `data:`) | Image | **Print image…** and **Print page…** |
| a `<canvas>` | Canvas | **Print image…** and **Print page…** |
| words, empty space, a CSS background picture | None | **Print page…** |
Print page is always there. Ctrl+P and the Print button print the page,
as before.
**How the picture is taken** was measured before anything was built, on
a lab site with each kind of picture a lesson might have, a real
right-click on each, and the site logging every request:
| | signed-in picture | hotlink-protected | one-time address | `blob:` / `data:` | another site's | canvas | WebP |
| --- | --- | --- | --- | --- | --- | --- | --- |
| engine's "download image" | ✓ | ✓ | **404** — fetched again | ✓ | ✓ | **nothing** | a file Qt cannot read |
| `page.download(url)` | ✓ | **403** — no Referer | **404** | – | ✓ | – | the same |
| `fetch()` from the page | ✓ | ✓ | ✓ | – | **refused** (CORS) | – | the same |
| draw it on a canvas | ✓ | ✓ | ✓ | ✓ | **refused** (tainted) | – | ✓ |
| **engine's "copy image"** | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Only the engine's own **copy image** hands over the picture in every
case, and it is what Wonder Ink uses. It is the bitmap the page has
already decoded — full size, transparency kept, any format Chromium
reads (Qt itself cannot read WebP here) — and **it fetches nothing**: the
site saw no request at all. So a picture behind the teacher's sign-in
needs no sign-in again, and a picture the site hands out once is still
there. 0.01 to 0.05 s in the lab.
It goes through the clipboard, which is the teacher's. So what is on it
is kept first and put back as soon as the picture arrives — whenever it
arrives, even after Cancel. Measured under the real Plasma session
(KWin, Wayland) with another program owning the clipboard: saved in
0.002 s, the picture in 0.016 s, and that other program then pasted its
own text again.
The picture then goes into exactly the 0.2.6.2 picture preview — drawn on
white, capped at 300 dpi across Letter, Size, Position, Paper, Fill the
whole page, Color — named *Picture from* the lesson's title.
**When it cannot be taken.** A picture that never loaded is still a
picture to the hit test, and the engine then copies nothing. After three
seconds the preview says *This picture could not be taken from the page*
and that nothing was printed, with Print off. It does **not** fall back
to printing the page; Print page is one right-click away and says what
it does.
What it cannot do, and says nothing about because it cannot know:
* **a CSS background picture** is not a picture to the engine's hit
test — Chrome's own menu has no "Save image" for one either. The menu
offers only Print page. If Wonder Ink's site draws its artwork this
way, that is the next thing to look at; nothing in the lab says it does;
* **a video** frame is not offered;
* **the teacher's clipboard is put back into Wonder Ink.** Under Wayland
with no clipboard manager — this session has none — the clipboard
belongs to whichever program last set it. After a Print image that is
Wonder Ink, so text copied in another program before it can still be
pasted while Wonder Ink is open, and is gone once Wonder Ink closes.
Measured in the lab session. Leaving the picture there instead would
lose it at once.
`tools/lab/wonderink-print-check` runs a signed-in lesson site
(`tools/lab/wonderink-lesson-site.py`: session cookie, one-time
addresses, a second origin) and right-clicks for real: the words (Print
page only, and the page prints), a JPEG, a PNG, a transparent PNG, a
one-time picture, another site's, a `blob:`, a WebP, a canvas, a picture
inside a link, a JPEG at 50% top left in black and white, a picture that
never loaded, and Cancel. Each is judged on the job CUPS kept: where and
how large, no ink elsewhere, the corner mark there — and **no request to
the site** while it printed, and the teacher's clipboard theirs again.
`tools/lab/wonderink-print-check` runs all of this against the installed
command in the lab, and judges every scenario by what CUPS actually
received. `tests/test-classroom-printing.sh` covers the CUPS side at every