From e17c650ea7f1054f3c5045dd3f95257a8a05631f Mon Sep 17 00:00:00 2001 From: Martino Ferrari Date: Sun, 4 Oct 2026 20:11:42 +0200 Subject: [PATCH] docs: correct the spec's icon verification to a build-time check The spec asserted that a paintable's intrinsic size reads 0x0 for an SVG librsvg refuses. It does not: gtk_icon_theme_lookup_icon() never returns NULL and always reports the requested size, and a valid icon, a malformed one and an absent name all snapshot to the same texture node. GMarkup accepts the double hyphen, and gdk-pixbuf goes through glycin here and refuses our own icons. So the malformed file is caught by preprocess="xml-stripblanks", which runs xmllint during glib-compile-resources and fails the build with file, line and column. The runtime line keeps its format but asserts only what it can: the name resolves, the resource is present, and the root element declares the size. Co-Authored-By: Claude Opus 4.6 --- ...10-04-app-icon-and-desktop-entry-design.md | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/docs/superpowers/specs/2026-10-04-app-icon-and-desktop-entry-design.md b/docs/superpowers/specs/2026-10-04-app-icon-and-desktop-entry-design.md index 047527b..5676086 100644 --- a/docs/superpowers/specs/2026-10-04-app-icon-and-desktop-entry-design.md +++ b/docs/superpowers/specs/2026-10-04-app-icon-and-desktop-entry-design.md @@ -189,15 +189,38 @@ passes; the existing `toolbar icons:` line already guards that class with cannot see it — and these SVGs have already been bitten once by librsvg, which rejects a file for a `--` inside an XML comment. -So the new assertion distinguishes *named* from *renderable*: +The two are therefore caught in two different places, because **no runtime GTK call can see the +malformed one.** This was measured rather than assumed, and three candidate checks were tried and +rejected: + +- `gtk_icon_theme_lookup_icon()` never returns `NULL` and its paintable's intrinsic size is the + size that was *asked for*, so it reads `128x128` for a valid icon, a malformed one and a name + that does not exist at all. The same three cases snapshot to an identical `GSK_TEXTURE_NODE` of + the requested bounds, since GTK substitutes `image-missing`. There is nothing to compare. +- `GMarkup` accepts `` without complaint. It is a deliberately lenient subset + parser, so it cannot stand in for the strict one that refuses the file. +- `gdk_pixbuf_new_from_file()` on an SVG goes through glycin on this system, which sandboxes a + subprocess per load, emits fontconfig errors, and refuses this project's existing icons outright + for reasons of its own. Not a usable oracle. + +So the malformed file is caught at **build time**, which is better than a probe anyway: every +`` line in `src/icons/udpscope.gresource.xml` gains `preprocess="xml-stripblanks"`, which +makes `glib-compile-resources` pipe each SVG through `xmllint`. A double hyphen inside a comment +then **fails the build** with the file, line and column, instead of drawing nothing at runtime. +The four existing icons already pass it. The cost is that the `xmllint` binary becomes a build +dependency; it ships with libxml2, which GTK already requires. + +The runtime line then asserts what a runtime check genuinely can: ``` app icons: org.udpscope.app(ok 128x128) org.udpscope.app-symbolic(ok 16x16) ``` -It looks each icon up and queries the resulting paintable's intrinsic size. **Both entries must read -`ok` with a non-zero size**; a parse failure reports `0x0` with the name still resolving, which is -precisely the case the existing check misses. +`ok` is `gtk_icon_theme_has_icon()` **and** the resource bytes being present under the registered +path, and the size is the one the file's root `` element declares, read out of those bytes. +**Both entries must read `ok` at those sizes.** That covers the unregistered-path case, a renamed +or mis-pathed file, and a canvas size that drifted off the HIG's 128 — and it is computed on the +first tick beside `toolbar icons:`, not in the dump, which runs after the window is destroyed. Alongside it: @@ -212,7 +235,9 @@ Alongside it: ## Documentation -- **CLAUDE.md**: the `app icons:` dump line as a documented assertion; the windows invariant revised +- **CLAUDE.md**: the `app icons:` dump line as a documented assertion, and the `xml-stripblanks` + build-time check beside the five existing icon-authoring rules — the sixth rule is that the + malformed-SVG failure is a *build* error now and no runtime check can replace it; the windows invariant revised to one `GtkWindow` and two `AdwDialog`s; the `desktop-entry` target and the build-path caveat; and the icon-authoring rules amended so "filled paths only" is scoped to symbolic icons. - **README.md**: the feature narrative — the icon's HIG constraints and the two omissions