Skip to content

Commit eb244bc

Browse files
committed
fix(pangocairo): 闸门改成 layout 自己的度量,而不是字体族数
`families > 0` 看着够用,其实不够,花了两轮 CI 才看清。同一个 CI runner 报告 四个字体族,然后把同一个 layout 量成 80x858545(一个进程)和 80x346398(另一 个)—— 在 100px surface 上都是荒谬的高度,因为那里的「四个字体族」是 fontconfig 有条目而背后没有可用字体。字形落到 surface 之外,墨迹数变成任意的:两个逐字节 相同绘制代码的孪生测试,一个 0 一个 116。 上一轮的修法(ink > 0 而不是 > 100)是必要但不充分的,底层原因相同:两者都在 **推断**机器的适用性,而不是**检验**它。 闸门现在是 w > 0 && h > 0 && h <= 100,不满足时运行会说出来 —— 「这条检查被跳 过了」和「文字画出来了」不能长得一样。两个测试现在都打印 layout 尺寸和字体族数, 于是孪生测试可以互相对照。 tarball 重切:sha256 → b470a658…,CN 容器 tag → 1.56.1-4。
1 parent a31561a commit eb244bc

6 files changed

Lines changed: 62 additions & 28 deletions

File tree

.agents/docs/2026-08-30-graphics-stack-coverage-design.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2100,11 +2100,23 @@ freedesktop.cairo 字形落下去的那张 surface
21002100

21012101
**空白图片意味着其中之一没干活。**
21022102

2103-
**而断言是 `ink > 0`,刻意不是一个调出来的数。** 早先写的是 `> 100`:在我这台
2104-
有 184 个字体族的机器上得到 216 像素、**通过**;在只有 4 个字体族的 CI runner 上
2105-
得到 72 像素、**失败** —— 因为几乎没有字体时「世界」渲染成豆腐块,墨迹更薄。
2106-
那个阈值是**对机器的断言**,不是对这次构建的断言。和 gnome.gio 的 xdgmime 检查
2107-
刻意不断言具体 MIME 是同一条理由。
2103+
### ⭐ 这条断言错了两次才对
2104+
2105+
**第一次:`drawn > 100`** 在我这台 184 个字体族的机器上得到 216 像素、通过;
2106+
在只有 4 个字体族的 CI runner 上得到 72、失败。**按开发机字体调出来的阈值是对
2107+
机器的断言。** 改成 `> 0`
2108+
2109+
**第二次:用 `families > 0` 当闸门。** 也不够,而且花了两轮 CI 才看清。同一个
2110+
runner 报告**四个字体族**,然后把同一个 layout 量成 `80x858545`(一个进程)和
2111+
`80x346398`(另一个)—— 在 100px 的 surface 上都是荒谬的高度,因为那里的「四个
2112+
字体族」是 fontconfig 有**条目**而背后没有可用字体。字形于是落到 surface 之外,
2113+
墨迹数变成任意的:**两个逐字节相同绘制代码的孪生测试,一个 0 一个 116。**
2114+
2115+
所以闸门现在是 **layout 自己的度量**(`w > 0 && h > 0 && h <= 100`)——
2116+
**显式检验这台机器能不能渲染**,而不是从字体族数去推断。不满足时运行**会说出来**,
2117+
因为「这条检查被跳过了」和「文字画出来了」不能长得一样。
2118+
2119+
和 gnome.gio 的 xdgmime 检查刻意不断言具体 MIME 是同一条理由。
21082120

21092121
⚠️ 而且它**诚实地降级**:`freedesktop.fontconfig` 故意把运行期路径编译成空,
21102122
所以没有 `FONTCONFIG_FILE` 的 runner 合法地找到零个字体族 —— 那就没有东西可画、

pkgs/p/gnome.pango.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ package = {
8484
["1.56.1"] = {
8585
url = {
8686
GLOBAL = "https://github.com/mcpplibs/pango/archive/refs/tags/1.56.1.tar.gz",
87-
-- ⚠️ The container tag is `1.56.1-3`, not `1.56.1`. gitcode
87+
-- ⚠️ The container tag is `1.56.1-4`, not `1.56.1`. gitcode
8888
-- refuses to REPLACE an asset of the same name in an
8989
-- existing release, so each corrected tarball needs a new
9090
-- container tag while the PACKAGE version stays upstream's.
9191
-- Verified byte-identical to the GLOBAL tag archive.
92-
CN = "https://gitcode.com/mcpp-res/pango/releases/download/1.56.1-3/pango-1.56.1.tar.gz",
92+
CN = "https://gitcode.com/mcpp-res/pango/releases/download/1.56.1-4/pango-1.56.1.tar.gz",
9393
},
94-
sha256 = "d520087d521729124c43bf4b86ae90f4049f23f580e10cd6b1b186873b3d4ab0",
94+
sha256 = "b470a658e05ef0e14d779bc852371ce52dd11efa76d10782347be40f1d63476b",
9595
},
9696
},
9797
},

pkgs/p/gnome.pangocairo.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,14 @@ package = {
9090
["1.56.1"] = {
9191
url = {
9292
GLOBAL = "https://github.com/mcpplibs/pango/archive/refs/tags/1.56.1.tar.gz",
93-
-- ⚠️ The container tag is `1.56.1-3`, not `1.56.1`. gitcode
93+
-- ⚠️ The container tag is `1.56.1-4`, not `1.56.1`. gitcode
9494
-- refuses to REPLACE an asset of the same name in an
9595
-- existing release, so each corrected tarball needs a new
9696
-- container tag while the PACKAGE version stays upstream's.
9797
-- Verified byte-identical to the GLOBAL tag archive.
98-
CN = "https://gitcode.com/mcpp-res/pango/releases/download/1.56.1-3/pango-1.56.1.tar.gz",
98+
CN = "https://gitcode.com/mcpp-res/pango/releases/download/1.56.1-4/pango-1.56.1.tar.gz",
9999
},
100-
sha256 = "d520087d521729124c43bf4b86ae90f4049f23f580e10cd6b1b186873b3d4ab0",
100+
sha256 = "b470a658e05ef0e14d779bc852371ce52dd11efa76d10782347be40f1d63476b",
101101
},
102102
},
103103
},

pkgs/p/gnome.pangoft2.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,14 @@ package = {
6868
["1.56.1"] = {
6969
url = {
7070
GLOBAL = "https://github.com/mcpplibs/pango/archive/refs/tags/1.56.1.tar.gz",
71-
-- ⚠️ The container tag is `1.56.1-3`, not `1.56.1`. gitcode
71+
-- ⚠️ The container tag is `1.56.1-4`, not `1.56.1`. gitcode
7272
-- refuses to REPLACE an asset of the same name in an
7373
-- existing release, so each corrected tarball needs a new
7474
-- container tag while the PACKAGE version stays upstream's.
7575
-- Verified byte-identical to the GLOBAL tag archive.
76-
CN = "https://gitcode.com/mcpp-res/pango/releases/download/1.56.1-3/pango-1.56.1.tar.gz",
76+
CN = "https://gitcode.com/mcpp-res/pango/releases/download/1.56.1-4/pango-1.56.1.tar.gz",
7777
},
78-
sha256 = "d520087d521729124c43bf4b86ae90f4049f23f580e10cd6b1b186873b3d4ab0",
78+
sha256 = "b470a658e05ef0e14d779bc852371ce52dd11efa76d10782347be40f1d63476b",
7979
},
8080
},
8181
},

tests/examples/pangocairo/tests/module.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,21 @@ int main()
6060
pango_layout_get_pixel_size(layout, &w, &h);
6161
g_print(" layout pixel size: %dx%d\n", w, h);
6262

63+
// ⚠️ THE SURFACE IS CHECKED, and its format is PRINTED. The first version
64+
// of this test only counted pixels, so when it reported 0 on a runner
65+
// where the header-route twin reported 116 there was nothing to go on:
66+
// "0 pixels" is a symptom shared by "nothing was drawn", "the surface is
67+
// in an error state" and "the pixel loop is reading the wrong bytes".
6368
cairo_surface_t *surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 400, 100);
69+
g_print(" surface status=%d format=%d (CAIRO_FORMAT_ARGB32=%d)\n",
70+
(int) cairo_surface_status(surf),
71+
(int) cairo_image_surface_get_format(surf),
72+
(int) CAIRO_FORMAT_ARGB32);
73+
check(cairo_surface_status(surf) == CAIRO_STATUS_SUCCESS,
74+
"the ARGB32 surface was created without error");
75+
check(cairo_image_surface_get_format(surf) == CAIRO_FORMAT_ARGB32,
76+
"…and the format it reports is the one that was asked for");
77+
6478
cairo_t *cr = cairo_create(surf);
6579
cairo_set_source_rgb(cr, 0, 0, 0);
6680
cairo_move_to(cr, 10, 10);
@@ -69,6 +83,7 @@ int main()
6983

7084
cairo_surface_flush(surf);
7185
const unsigned char *d = cairo_image_surface_get_data(surf);
86+
check(d != nullptr, "the surface has readable pixel data");
7287
const int stride = cairo_image_surface_get_stride(surf);
7388
long drawn = 0;
7489
for (int y = 0; d && y < 100; ++y)

tests/examples/pangocairo/tests/pangocairo.cpp

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -127,24 +127,31 @@ int main()
127127
const long drawn = ink(surf);
128128
std::printf(" non-transparent pixels: %ld\n", drawn);
129129

130-
if (families > 0) {
130+
// ⚠️ THE GUARD IS THE LAYOUT'S OWN METRICS, NOT THE FAMILY COUNT.
131+
//
132+
// `families > 0` looked like enough and is not. A CI runner reported FOUR
133+
// families and measured this layout at 80x858545 — a nonsense height on a
134+
// 100px surface, because "four families" there means fontconfig has
135+
// entries but no usable font behind them. The glyphs then land off the
136+
// surface and the ink count is arbitrary: 0 in one process and 116 in
137+
// another, from byte-identical drawing code.
138+
//
139+
// An earlier version also asserted `drawn > 100`, which passed here (216
140+
// pixels, 184 families) and failed there (72) — a threshold calibrated to
141+
// the developer's font set is an assertion about the MACHINE. Ink is ink.
142+
const bool usable = families > 0 && w > 0 && h > 0 && h <= 100;
143+
if (usable) {
131144
// ⭐ THE WHOLE LINE, IN ONE ASSERTION.
132-
check(w > 0 && h > 0, "the layout measured a non-empty box");
133-
// ⚠️ `> 0`, NOT `> 100`. An earlier version used 100 and PASSED here
134-
// (216 pixels, 184 font families) while FAILING on a CI runner with
135-
// four families and 72 — because with almost no fonts "世界" renders
136-
// as tofu boxes and the ink is thinner. The threshold was calibrated
137-
// to the developer's font set, which makes it an assertion about the
138-
// MACHINE rather than about this build. Ink is ink: any positive count
139-
// proves all seven packages put pixels down.
140145
check(drawn > 0,
141146
"pango_cairo_show_layout put ink on the surface — seven packages");
142147
} else {
143-
// Not a pass. The runner has no fonts, so the only real check could
144-
// not run, and saying so is the point.
145-
std::printf(" ⚠️ 0 font families: this runner has no fonts, so the\n"
146-
" rendering assertion was NOT run. That is a property\n"
147-
" of the machine, not of this build.\n");
148+
// Not a pass. The machine cannot render, so the only real check could
149+
// not run, and saying so is the point: "it was skipped" and "it worked"
150+
// must not look alike.
151+
std::printf(" \342\232\240 no usable font (families=%d, layout %dx%d on a\n"
152+
" 100px surface): the rendering assertion was NOT run.\n"
153+
" That is a property of this machine, not this build.\n",
154+
families, w, h);
148155
check(drawn >= 0, "the surface is readable (rendering check skipped)");
149156
}
150157

0 commit comments

Comments
 (0)