Generate the documentation's figures from the listings they illustrate
Chapters 6 and 8 described what a verb draws in prose. Eight figures now show it, and each one is produced by running the BASIC listing printed immediately above it -- so a picture cannot drift away from the code beside it, which is the way a screenshot goes wrong and the way nothing notices. tools/screenshot.c is a second SDL host, much smaller than the frontend: dummy video driver, software renderer, run to completion, read the target back, write a PNG. It draws no text layer on purpose, so a READY in the corner is not noise in a figure about BOX and no font has to be resolved. tools/docs_screenshots.sh reads the new screenshot=NAME fence tag straight out of the markdown. size=WxH is the second tag, and SCALE's figure uses it: the point being made is a 320x200 listing filling a larger window, which cannot be made on a 320x200 surface. Two gates, answering different questions. docs_examples fails a tagged block with no image, in both configurations, so a figure cannot be added and forgotten. docs_screenshots -- a CTest, AKGL build only -- re-renders every figure and compares byte for byte, so a listing edited without regenerating fails. Only the second catches a stale picture. The PNGs are checked in because a reader on the forge has no build tree, and docs/images/README.md says loudly that they are generated. Regenerating is never part of a build: the target is run deliberately, so a make cannot put eight binary diffs in front of whoever ran it. Drawing the BOX figure caught a defect in TODO.md itself. Deviation 16 claimed in bold that BOX fills on a negative angle while its own paragraph said the fill was filed rather than implemented. BOX cannot fill, and filled_rect is reached by no verb as a result. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
83
TODO.md
83
TODO.md
@@ -793,10 +793,23 @@ behaviour to port. They matter to somebody typing in a listing out of a C128 man
|
||||
is not its size. Nothing in BASIC does any of those to a shape string except a program
|
||||
deliberately poking at it.
|
||||
|
||||
16. **`BOX` fills on a negative angle rather than on a seventh argument.** 7.0's last
|
||||
argument selects outline or fill and sits *after* the rotation, which would make a filled
|
||||
box a seven-argument call. That is filed rather than implemented; today a rotation of zero
|
||||
outlines through the renderer's rectangle and any other rotation draws four lines.
|
||||
16. **`BOX` cannot fill at all, and the plan for it is to spell fill as a negative angle.**
|
||||
7.0's last argument selects outline or fill and sits *after* the rotation, which would
|
||||
make a filled box a seven-argument call — one more than `akbasic_cmd_box()` collects.
|
||||
Spelling it as a negative rotation instead is the intended answer and **is not
|
||||
implemented**: today a rotation of zero outlines through the renderer's rectangle and any
|
||||
other rotation, negative included, draws four lines.
|
||||
|
||||
**This entry used to claim in bold that it fills**, with the body then saying it was
|
||||
filed rather than implemented — a headline that contradicted its own paragraph, which is
|
||||
exactly how a reader ends up believing a feature exists. Found by writing a
|
||||
documentation figure for `BOX` and getting an outline back. `PAINT` is the fill a
|
||||
program has today.
|
||||
|
||||
**`akbasic_GraphicsBackend::filled_rect` is dead from the language's side** as a direct
|
||||
consequence: `src/graphics_akgl.c` implements it and `tests/mockdevice.h` records it, but
|
||||
no BASIC verb reaches it. It is the entry point this fix would call, so it is waiting
|
||||
rather than unused — worth knowing before somebody tidies it away.
|
||||
|
||||
17. **`GRAPHIC` records its mode but honours only one consequence of it.** 7.0's five modes
|
||||
differ in bitmap resolution and in whether the bottom of the screen stays text. Neither
|
||||
@@ -1588,12 +1601,13 @@ requirement; exactly one case has diverged on purpose since, and
|
||||
| Gate | Result |
|
||||
|---|---|
|
||||
| `ctest` | 95/95 — 41 reference golden cases, 15 local ones, 36 unit tests, 2 embedding examples, and `docs_examples` |
|
||||
| `ctest` with `-DAKBASIC_WITH_AKGL=ON` | 94/94 on a machine with a display; 93 passed + 1 skipped headless. The same set minus the three `no_device` cases the SDL driver contradicts, plus `akgl_backends`, `akgl_frontend` and `akgl_typing` — the last of which is the skip, and the `akgl_build` CI job is where it skips |
|
||||
| `docs_examples` | Every fenced block in `README.md`, `MAINTENANCE.md` and `docs/` executed and byte-compared: 37 programs, 9 transcripts, 45 output comparisons, 6 C snippets, 1 excerpt and 2 shell blocks in the default build; 50 programs and 7 C snippets in the AKGL one. `MAINTENANCE.md` documents the fence-tag convention |
|
||||
| `ctest` with `-DAKBASIC_WITH_AKGL=ON` | 95/95 on a machine with a display; 94 passed + 1 skipped headless. The same set minus the three `no_device` cases the SDL driver contradicts, plus `akgl_backends`, `akgl_frontend`, `docs_screenshots` and `akgl_typing` — the last of which is the skip, and the `akgl_build` CI job is where it skips |
|
||||
| `docs_examples` | Every fenced block in `README.md`, `MAINTENANCE.md` and `docs/` executed and byte-compared: 41 programs, 9 transcripts, 49 output comparisons, 2 excerpts, 2 shell blocks and 8 figures in the default build; 57 programs and 48 output comparisons in the AKGL one. The C-snippet count reads 0 when the harness is run by hand without `--cflags-file`; CTest passes it. `MAINTENANCE.md` documents the fence-tag convention |
|
||||
| `docs_screenshots` | 8/8 figures re-rendered and byte-identical to the checked-in PNGs. AKGL build only — rendering a picture needs the SDL half |
|
||||
| Golden corpus | 41/41 byte-exact from `tests/reference/` — **and 41/41 again through the SDL binary**, which is most of what proves the frontend changes no output |
|
||||
| ASan + UBSan | 77/77 |
|
||||
| Line coverage | 94.6% (3857/4076) — above the 90% gate |
|
||||
| Function coverage | 98.6% (287/291) |
|
||||
| ASan + UBSan | 95/95 |
|
||||
| Line coverage | 95.1% (5916/6222) — above the 90% gate |
|
||||
| Function coverage | 98.5% (403/409) |
|
||||
| Warnings | none under `-Wall -Wextra` |
|
||||
| `doxygen Doxyfile` | clean |
|
||||
| Mutation (`src/symtab.c`) | 74.1%, against a gate of 65 — see `.gitea/workflows/ci.yaml` |
|
||||
@@ -1666,6 +1680,14 @@ and `src/graphics_tables.c` 100%, `src/runtime_input.c` 100%, `src/runtime_graph
|
||||
`src/runtime_audio.c` 98%, `src/play.c` 87%. The `akbasic_akgl` target is not in the coverage
|
||||
figure — it is not built in a default configuration.
|
||||
|
||||
**The denominator moved a long way and this is not an explanation of why.** The line total
|
||||
went from 4076 to 6222 between the previous entry and this one, which is far more than the
|
||||
work since added — so one of the two measurements is counting something the other is not,
|
||||
and which one is right has not been established. Both figures were produced with
|
||||
`gcovr --filter 'src/.*'` over a clean tree. Recorded rather than quietly overwritten,
|
||||
because a coverage percentage whose denominator nobody can account for is worth exactly as
|
||||
much as the accounting. The *ratio* is above the gate on either reading.
|
||||
|
||||
**A note on reading that number, because it was misread once while producing it.** A stale
|
||||
`build-cov/` left in the source directory from an earlier session was silently folded into the
|
||||
report by `gcovr --root .`, which produced the *previous* run's 92.3% for a tree that had grown
|
||||
@@ -1856,6 +1878,45 @@ What remains, in priority order:
|
||||
recorded above. And `VAL` reports a dependency's status code where the interpreter has
|
||||
one of its own, which is §6 item 21 and is filed rather than fixed.
|
||||
|
||||
12. Screenshots for graphics operations
|
||||
12. ~~**Screenshots for graphics operations.**~~ **Done** — eight figures, six in
|
||||
`docs/06-graphics.md` and two in `docs/08-sprites.md`. The item said chapter 8; chapter 8
|
||||
is sprites and chapter 6 is the drawing verbs, so both got them.
|
||||
|
||||
Chapter 8 of the documentation should include screenshots of various graphics operations being performed.
|
||||
**A figure here is output, not an asset**, which is the part worth keeping. Each one is
|
||||
generated by running the listing printed immediately above it:
|
||||
|
||||
- `tools/screenshot.c` is a second SDL host, and a much smaller one than
|
||||
`src/frontend_akgl.c` — dummy video driver, software renderer, run to completion,
|
||||
`SDL_RenderReadPixels`, `IMG_SavePNG`. The pattern is `deps/libakgl/tests/draw.c`'s and
|
||||
this is its third user. It draws no text layer on purpose: a `READY` in the corner is
|
||||
noise in a figure about `BOX`, and skipping it means no font has to be resolved.
|
||||
- `tools/docs_screenshots.sh` reads the new `screenshot=NAME` fence tag straight out of
|
||||
the markdown, so the picture cannot drift from the code beside it without somebody
|
||||
editing one of the two. `size=WxH` is the second tag, and `SCALE`'s figure uses it —
|
||||
640x400, because the point being illustrated is a 320x200 listing filling a larger
|
||||
window, and that point cannot be made on a 320x200 surface.
|
||||
- **Two gates, and they answer different questions.** `docs_examples` checks that a
|
||||
tagged block *has* an image, in both configurations, so a figure cannot be added and
|
||||
forgotten. `docs_screenshots` — a CTest, AKGL build only — re-renders every figure and
|
||||
compares byte for byte, so a listing edited without regenerating fails. The first
|
||||
catches a missing picture; only the second catches a *stale* one, which is the failure
|
||||
this whole arrangement exists against.
|
||||
|
||||
The byte comparison is a deliberate bet that the dummy driver and the software renderer
|
||||
are reproducible, which is the same bet `tests/reference/` already makes about golden
|
||||
output. Verified run-to-run and build-to-build here; what is untested is an SDL upgrade
|
||||
that moves one pixel of a diagonal. **If that happens, regenerate the figures in the same
|
||||
commit as the bump** — do not weaken the test to a size check, which would pass for every
|
||||
wrong picture that happened to be 320x200.
|
||||
|
||||
The PNGs are checked in, because a reader on the forge has no build tree, and
|
||||
`docs/images/README.md` says loudly that they are generated so nobody hand-edits one.
|
||||
Regenerating is never part of a build: `cmake --build build-akgl --target
|
||||
docs_screenshots` is a deliberate act, so a `make` cannot quietly put eight binary diffs
|
||||
in front of whoever ran it.
|
||||
|
||||
**Writing them turned up a documentation defect of this file's own**, recorded at §5
|
||||
deviation 16: that entry claimed in bold that `BOX` fills on a negative angle, while its
|
||||
own body said the fill was filed rather than implemented. Drawing the figure and getting
|
||||
an outline back is what caught it. `akbasic_GraphicsBackend::filled_rect` is implemented,
|
||||
recorded by the mock, and reached by no verb at all as a result.
|
||||
|
||||
Reference in New Issue
Block a user