Skip to content

feat(cairo): 2D 矢量绘制 —— 后端做成 feature,X11 默认关 - #312

Merged
Sunrisepeak merged 1 commit into
mainfrom
feat/cairo
Aug 30, 2026
Merged

feat(cairo): 2D 矢量绘制 —— 后端做成 feature,X11 默认关#312
Sunrisepeak merged 1 commit into
mainfrom
feat/cairo

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

路径、描边、填充、文字排布,以及承载它们的表面。只做合成的合成器用不到它;桌面外壳(面板、启动器、通知)是靠它画的,pango 也经它渲染文字。

配套 fork:mcpplibs/cairo(新建,CI 绿)。

判据修正:决定 fork 难度的是生成器,不是行数

行数 生成器
fontconfig 26k 7 个(python + gperf)
cairo 104k 0 个

上游 meson 只出两个产物,config.hcairo-features.h,两个都是 configure_file —— 探测答案,不是生成的代码。设计文档此前按行数把 cairo 标成更大的活,那是错的。

build.mcpp 只用来生成模块包装,因为导出面随 feature 变

后端做成 feature

default = ["ft", "fc", "png"]     # Wayland-first

上游把每个后端做成 get_option(),等于让发行版替所有人决定一次。索引不能这样。所以在 Wayland 程序里画个圆不会拖进 libX11;要 X11 的人写 cairo = { features = ["xlib"] }

fork CI 在产物上验证这件事,不是在 manifest 上:没有 cairo-xlib-*.o,任何 .o 里都没有 XOpenDisplay

每个 feature 的 sources 逐个文件列出 —— feature 源选通按字面条目匹配,glob 会把那个后端编进每一个消费者。

归档是源码,不是测试套件

cairo 的发布物带 61 MB 参考图(test/),这个包一个都不编。整包发出去是「下 47 MB 用 6 MB 源码」。test/perf/ 已裁掉,而 fork 的「upstream 与发布物一致」检查改为比对剩下的树 —— 构建能碰到的每个文件仍然逐一 diff。

47.8 MB → 1.8 MB。

⚠ 一个探测答案,别「修」它

WORDS_BIGENDIAN / FLOAT_WORDS_BIGENDIAN 在 config.h 里缺席,不是定义成 0 —— cairo 用 #ifdef 测(cairoint.h:196),0 的含义是大端。x86-64 上的后果:

编过、链过、cairo_status 全程 SUCCESS、cairo_paint 正常
cairo_rectangle(4,4,16,16) -> path_extents  -8.03e+06 … 4.37e+06
cairo_in_fill(40,40)       -> 1     (点在外面)
cairo_fill / cairo_stroke  -> 改动 0 个像素

我为此查了一小时「缺源文件」。测试因此同时断言像素和 path_extents:前者只会说「描边没画」,把人引向缺文件;后者直接指出算术错在哪。

测试

(56,8)  = 191 128 64 255      画上去的背景,精确
(32,32) = 255 255 255 255     8px 白色对角描边覆盖中心
path_extents = 4 4 20 20      in_fill(10,10)=1  in_fill(40,40)=0
feature ft / fc / png  ON     feature xlib / xcb  OFF
module 导出 cairo.h 内部 #if 守住的名字,以及 feature 头里的名字
0 check(s) failed

只改了 pkgs/tests/examples/

路径、描边、填充、文字排布,以及承载它们的表面。只做合成的合成器用不到它;
桌面**外壳**——面板、启动器、通知——是靠它画的,pango 也是经它渲染文字。

## 判据修正:决定 fork 难度的是生成器,不是行数

104k 行 C,**没有任何代码生成**。上游 meson 只出两个产物,config.h 和
cairo-features.h,两个都是 configure_file(探测答案,不是生成的代码)。
fontconfig 是它四分之一大小,却有七个生成器。

设计文档此前按行数把 cairo 标成更大的活,那是错的。

## 后端做成 feature,X11 默认关

    default = [ft, fc, png]

上游把每个后端做成 get_option(),等于让发行版替所有人决定一次。索引不能这样:
合成器和 X11 应用要的是同一个包的不同构建。所以在 Wayland 程序里画个圆不会因此
拖进 libX11;要 X11 的人写 features = ["xlib"] 并且说出来。

fork CI 在**产物上**验证这件事,不是在 manifest 上:没有 cairo-xlib-*.o,任何
.o 里都没有 XOpenDisplay。

## 归档是源码,不是测试套件

cairo 的发布物带 61 MB 参考图(test/),这个包一个都不编。整包发出去是「下 47 MB
用 6 MB 源码」。test/ 和 perf/ 已裁掉,而 fork 的「upstream 与发布物一致」检查改为
比对**剩下的树**,所以构建能碰到的每个文件仍然逐一 diff。47.8 MB -> 1.8 MB。

## ⚠ 一个探测答案,别「修」它

WORDS_BIGENDIAN 和 FLOAT_WORDS_BIGENDIAN 在 config.h 里是**缺席**,不是定义成 0
——cairo 用 #ifdef 测(cairoint.h:196),0 的含义是大端。在 x86-64 上后果是:编过、
链过、报 SUCCESS、cairo_paint 照常工作,而每条**路径**拿到垃圾定点坐标:
cairo_rectangle(4,4,16,16) 的 extents 变成 -8.03e+06 … 4.37e+06,cairo_fill 改动
零个像素。实测。

测试因此同时断言像素和 path_extents:前者只会说「描边没画」,把人引向缺文件;
后者直接指出算术错在哪。

只改了 pkgs/ 与 tests/examples/。
@Sunrisepeak
Sunrisepeak merged commit afde8dd into main Aug 30, 2026
11 checks passed
@Sunrisepeak
Sunrisepeak deleted the feat/cairo branch August 30, 2026 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant