xbintsc 0.5.31 → 0.5.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -10
- package/dist/src/binder/references.js +14 -1
- package/dist/src/binder/references.js.map +1 -1
- package/dist/src/cli/help.d.ts +1 -1
- package/dist/src/codegen/generator/module.d.ts +1 -0
- package/dist/src/codegen/generator/module.js +54 -0
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/statements/variables.js +6 -4
- package/dist/src/codegen/generator/statements/variables.js.map +1 -1
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/gui/css.d.ts +26 -0
- package/dist/src/extensions/gui/css.js +100 -0
- package/dist/src/extensions/gui/css.js.map +1 -0
- package/dist/src/extensions/gui/html.js +9 -2
- package/dist/src/extensions/gui/html.js.map +1 -1
- package/dist/src/extensions/gui/index.js +16 -2
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/gui/three.d.ts +16 -0
- package/dist/src/extensions/gui/three.js +22 -0
- package/dist/src/extensions/gui/three.js.map +1 -0
- package/dist/src/extensions/media/index.d.ts +6 -5
- package/dist/src/extensions/media/index.js +12 -14
- package/dist/src/extensions/media/index.js.map +1 -1
- package/dist/tests/e2e/compile-builtins.test.js +24 -0
- package/dist/tests/e2e/compile-builtins.test.js.map +1 -1
- package/dist/tests/e2e/compile-objects-classes.test.js +23 -0
- package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
- package/dist/tests/e2e/gui-browser.test.js +1 -1
- package/dist/tests/e2e/gui-browser.test.js.map +1 -1
- package/dist/tests/e2e/gui-effects.test.d.ts +6 -0
- package/dist/tests/e2e/gui-effects.test.js +262 -0
- package/dist/tests/e2e/gui-effects.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-webgl.test.d.ts +10 -0
- package/dist/tests/e2e/gui-example-webgl.test.js +75 -0
- package/dist/tests/e2e/gui-example-webgl.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-webgl2.test.d.ts +8 -0
- package/dist/tests/e2e/gui-example-webgl2.test.js +72 -0
- package/dist/tests/e2e/gui-example-webgl2.test.js.map +1 -0
- package/dist/tests/e2e/gui-layout.test.js +48 -0
- package/dist/tests/e2e/gui-layout.test.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.js +5 -4
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl.test.d.ts +11 -0
- package/dist/tests/e2e/gui-webgl.test.js +179 -0
- package/dist/tests/e2e/gui-webgl.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2.test.js +238 -0
- package/dist/tests/e2e/gui-webgl2.test.js.map +1 -0
- package/dist/tests/extensions/gui.test.js +41 -0
- package/dist/tests/extensions/gui.test.js.map +1 -1
- package/dist/tests/extensions/media.test.js +7 -3
- package/dist/tests/extensions/media.test.js.map +1 -1
- package/doc/ai/extensions.md +29 -9
- package/doc/ai/troubleshooting.md +12 -8
- package/doc/ai/zh-CN/extensions.md +26 -8
- package/doc/ai/zh-CN/troubleshooting.md +10 -6
- package/doc/gui/api.md +3 -2
- package/doc/gui/build.md +72 -16
- package/doc/gui/canvas.md +11 -3
- package/doc/gui/dom.md +33 -18
- package/doc/gui/known-issues.md +57 -24
- package/doc/gui/layout.md +18 -0
- package/doc/gui/media.md +17 -13
- package/doc/gui/rendering.md +50 -3
- package/doc/gui/webgl.md +256 -0
- package/doc/gui.md +108 -17
- package/doc/npm-package.md +6 -4
- package/doc/requirements.md +18 -9
- package/doc/zh-CN/gui/api.md +3 -2
- package/doc/zh-CN/gui/build.md +64 -15
- package/doc/zh-CN/gui/canvas.md +9 -2
- package/doc/zh-CN/gui/dom.md +20 -7
- package/doc/zh-CN/gui/known-issues.md +45 -19
- package/doc/zh-CN/gui/layout.md +14 -0
- package/doc/zh-CN/gui/media.md +15 -11
- package/doc/zh-CN/gui/rendering.md +41 -4
- package/doc/zh-CN/gui/webgl.md +115 -0
- package/doc/zh-CN/gui.md +89 -14
- package/doc/zh-CN/npm-package.md +9 -6
- package/doc/zh-CN/requirements.md +12 -6
- package/llms.txt +2 -0
- package/package.json +1 -1
- package/runtime/ext_gui/browser.cpp +39 -13
- package/runtime/ext_gui/canvas.cpp +3 -18
- package/runtime/ext_gui/canvas_internal.h +10 -0
- package/runtime/ext_gui/canvas_raster.cpp +60 -0
- package/runtime/ext_gui/clip_values.cpp +246 -0
- package/runtime/ext_gui/css.cpp +94 -0
- package/runtime/ext_gui/css.h +22 -1
- package/runtime/ext_gui/css_match.cpp +3 -0
- package/runtime/ext_gui/css_selector.cpp +9 -0
- package/runtime/ext_gui/css_sheet.cpp +89 -45
- package/runtime/ext_gui/document.cpp +4 -1
- package/runtime/ext_gui/document.h +2 -0
- package/runtime/ext_gui/dom.h +16 -0
- package/runtime/ext_gui/dom_api.cpp +1 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +17 -80
- package/runtime/ext_gui/dom_api_canvas_extra.cpp +130 -1
- package/runtime/ext_gui/dom_api_canvas_pending.cpp +41 -0
- package/runtime/ext_gui/dom_api_internal.h +259 -0
- package/runtime/ext_gui/dom_api_webgl.cpp +376 -0
- package/runtime/ext_gui/dom_api_webgl2.cpp +434 -0
- package/runtime/ext_gui/dom_api_webgl2_draw.cpp +269 -0
- package/runtime/ext_gui/dom_api_webgl_buffer.cpp +212 -0
- package/runtime/ext_gui/dom_api_webgl_rt.h +30 -0
- package/runtime/ext_gui/dom_api_webgl_shader.cpp +443 -0
- package/runtime/ext_gui/dom_api_webgl_state.cpp +444 -0
- package/runtime/ext_gui/dom_api_webgl_texture.cpp +445 -0
- package/runtime/ext_gui/effect_values.cpp +312 -0
- package/runtime/ext_gui/gradient_values.cpp +476 -0
- package/runtime/ext_gui/grid_values.cpp +230 -0
- package/runtime/ext_gui/gui_canvas.cpp +50 -2
- package/runtime/ext_gui/gui_engine.h +27 -0
- package/runtime/ext_gui/gui_events.cpp +4 -1
- package/runtime/ext_gui/gui_media.cpp +1 -1
- package/runtime/ext_gui/gui_webgl.cpp +83 -0
- package/runtime/ext_gui/layout.cpp +21 -0
- package/runtime/ext_gui/layout_flow.cpp +81 -4
- package/runtime/ext_gui/layout_flow_internal.h +31 -0
- package/runtime/ext_gui/layout_grid.cpp +374 -0
- package/runtime/ext_gui/media.h +1 -1
- package/runtime/ext_gui/media_api.h +2 -2
- package/runtime/ext_gui/media_query.cpp +211 -0
- package/runtime/ext_gui/paint.cpp +111 -77
- package/runtime/ext_gui/paint.h +33 -3
- package/runtime/ext_gui/paint_background.cpp +229 -0
- package/runtime/ext_gui/paint_clip.cpp +268 -0
- package/runtime/ext_gui/paint_effects.cpp +324 -0
- package/runtime/ext_gui/paint_internal.h +85 -0
- package/runtime/ext_gui/renderer.cpp +8 -31
- package/runtime/ext_gui/renderer_clip.cpp +196 -0
- package/runtime/ext_gui/renderer_image.cpp +13 -8
- package/runtime/ext_gui/renderer_internal.h +15 -8
- package/runtime/ext_gui/renderer_text.cpp +6 -31
- package/runtime/ext_gui/style.cpp +343 -20
- package/runtime/ext_gui/style.h +144 -3
- package/runtime/ext_gui/style_print.cpp +134 -1
- package/runtime/ext_gui/style_values.cpp +152 -126
- package/runtime/ext_gui/style_values_internal.h +35 -0
- package/runtime/ext_gui/webgl.h +466 -0
- package/runtime/ext_gui/webgl2_constants.h +274 -0
- package/runtime/ext_gui/webgl_buffer.cpp +565 -0
- package/runtime/ext_gui/webgl_constants.h +317 -0
- package/runtime/ext_gui/webgl_context.cpp +466 -0
- package/runtime/ext_gui/webgl_draw.cpp +495 -0
- package/runtime/ext_gui/webgl_glsl.h +125 -0
- package/runtime/ext_gui/webgl_glsl_compile.cpp +431 -0
- package/runtime/ext_gui/webgl_glsl_rewrite.cpp +349 -0
- package/runtime/ext_gui/webgl_glsl_scan.cpp +581 -0
- package/runtime/ext_gui/webgl_msl.cpp +62 -0
- package/runtime/ext_gui/webgl_msl.h +33 -0
- package/runtime/ext_gui/webgl_pipeline.cpp +274 -0
- package/runtime/ext_gui/webgl_program_internal.h +18 -0
- package/runtime/ext_gui/webgl_shader.cpp +582 -0
- package/runtime/ext_gui/webgl_texture.cpp +293 -0
- package/runtime/ext_gui/webgl_uniform.cpp +167 -0
- package/runtime/ext_gui/webgl_webgl2.cpp +224 -0
- package/runtime/ext_media/media.cpp +1 -1
- package/runtime/ext_media/media_bridge.c +9 -3
- package/runtime/rt_internal.h +1 -0
- package/runtime/xt_containers/access.inc +8 -0
- package/runtime/xt_regex/api.inc +2 -0
- package/runtime/xt_regex/matcher.inc +16 -3
- package/runtime/xt_regex/parser.inc +8 -2
- package/runtime/xt_regex/types.inc +3 -0
- package/runtime/xt_stdlib2/regexp-match.inc +60 -21
- package/runtime/xt_stdlib2/regexp.inc +1 -0
- package/runtime/xt_typed_array.c +1 -1
- package/scripts/build-gui.ts +90 -3
- package/scripts/build-media.ts +323 -58
- package/scripts/setup-vs-toolchain.ps1 +152 -0
- package/src/binder/references.ts +13 -1
- package/src/codegen/generator/module.ts +50 -0
- package/src/codegen/generator/statements/variables.ts +6 -3
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/css.ts +113 -0
- package/src/extensions/gui/html.ts +9 -2
- package/src/extensions/gui/index.ts +16 -2
- package/src/extensions/gui/three.ts +25 -0
- package/src/extensions/media/index.ts +13 -16
package/doc/zh-CN/gui.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> 语言 / Language:[English](../gui.md) | **简体中文**
|
|
4
4
|
|
|
5
|
-
状态:**
|
|
5
|
+
状态:**M19** —— 功能(M1–M15)已全部完成:HTML 解析、CSS 选择器匹配、层叠(cascade)、计算样式与布局(块级、行内、Flexbox 与 CSS 定位)均已就位,引擎还会**绘制**:它构建一个由矩形、图像与排版后的文本 run 组成的显示列表,并通过 SDL_GPU 渲染。输入事件会经过命中测试并投递给原生 TS 处理器,`:hover`/`:focus` 会被动态匹配,`<img>` 依据其固有尺寸确定大小并从纹理绘制——位图(PNG/JPEG/…)与 SVG 文件皆可,后者按绘制尺寸光栅化,因此矢量图保持清晰——CSS transition 会为绘制属性做动画。**M16** 让内联 `<svg>` 子树获得同样的处理:子树被序列化回 SVG 文档,并按绘制设备尺寸光栅化,因此图标不再需要单独的文件。**M8** 增加了交互式 DOM:具有稳定标识的元素句柄、变更操作(`appendChild`、`textContent`、`classList`、`style` 等)以及支持捕获/冒泡的元素级事件。**M9** 会提前编译 `<script>` 主体(内联与 `<script src>`)——参见 `gui-scripts.md`。**M10** 增加 `requestAnimationFrame` 以及若干 DOM 辅助方法。**M11** 增加 `position: relative`/`absolute`/`fixed` 及其偏移,`examples/gui/pelican-bike`(一个可玩的 2D 游戏)就构建在它之上。**M12** 明确了 DOM 节点生命周期(哪些变更释放、哪些保留),并让引擎内存有界:参见[节点生命周期](./gui/dom.md)与[内存与 GC](./gui/runtime.md)。**M13** 真正播放
|
|
6
6
|
`<video>`/`<audio>`——可选的 `media` 扩展用 vendored 的最小 FFmpeg 在主线程解码,
|
|
7
7
|
视频帧走图像纹理路径、音频进入 SDL 流,DOM 媒体 API 暴露
|
|
8
8
|
`play`/`pause`/`currentTime`/… 与媒体事件。只启用 `gui` 不会链接 FFmpeg。**M14** 增加了 `<canvas>`,配一个自研的 2D 软件光栅器(抗锯齿
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
渲染器,因此盒子(以及其中的文本、图像与子元素)可以被平移、缩放与旋转而
|
|
13
13
|
不触发任何重排——再加上 `transition: transform`,这些姿态可以动画(自绘的示例
|
|
14
14
|
`examples/gui/pelican-svg` 正是用它让矢量画动起来)。参见
|
|
15
|
-
[布局](./gui/layout.md#变换m15)与[动画](./gui/animation.md#css-transformm15)。本总览记录了锁定决策、架构、里程碑计划与当前进度;引擎本身按功能拆分在以上各页中。
|
|
15
|
+
[布局](./gui/layout.md#变换m15)与[动画](./gui/animation.md#css-transformm15)。**M17** 增加了真正的 **WebGL 1.0**,**M18** 增加了 **WebGL 2.0**:`<canvas>.getContext("webgl2")` 接受 `#version 300 es` 着色器、顶点数组对象、实例化绘制与采样器对象,全部由内置 glslang 编译为 SPIR-V(Metal 上再由内置 SPIRV-Cross 转成 MSL)并通过 SDL_GPU 渲染,几何、光照、纹理采样与混合都在 GPU 上完成,页面直接合成颜色纹理而无须读回——见 [WebGL](./gui/webgl.md)。**M19** 补齐 CSS 装饰层:`@media` 查询、生成内容(`::before`/`::after`)、线性/径向多层背景、`text-shadow`、`clip-path` 与 `filter` 颜色/阴影效果。`backdrop-filter` 与真正的组模糊需要离屏合成器,仍为有文档说明的近似或未支持——见[绘制](./gui/rendering.md#背景生成内容与特效m19)。本总览记录了锁定决策、架构、里程碑计划与当前进度;引擎本身按功能拆分在以上各页中。
|
|
16
16
|
|
|
17
17
|
## 目录
|
|
18
18
|
|
|
@@ -135,19 +135,24 @@ FFmpeg `7.1`(供可选的 `media` 归档使用;可用 `SDL3_TAG` /
|
|
|
135
135
|
- **M6b — transition/动画** ✅ `transition` 简写 + 长写、对
|
|
136
136
|
`background-color`/`color`/`border-color`/`border-radius` 的动画、重定向
|
|
137
137
|
与 `win.advance(ms)`。`@keyframes` 仍待完成。
|
|
138
|
-
7. **M7 — CI 与发布** ✅(Linux/macOS 构建) / 🚧(运行 + Windows)
|
|
138
|
+
7. **M7 — CI 与发布** ✅(Linux/macOS 构建) / 🚧(运行 + Windows arm64)
|
|
139
139
|
- `compile-examples` 在 Linux 与 macOS 上构建 `gui.a` 与 `media.a`(必需),
|
|
140
140
|
然后在 Linux 上的 Xvfb + lavapipe 下运行示例与 `tests/e2e/gui-*.test.ts`
|
|
141
141
|
(必需)。macOS 运行在确认 WindowServer 之前为试验性;它被保护起来,失败
|
|
142
142
|
只记录日志而不标注运行。
|
|
143
|
-
- `package` job 在组装发布之前构建 `gui.a` 与 `media.a
|
|
144
|
-
runtime 归档一起发布(`package-release` 复制整个
|
|
145
|
-
|
|
143
|
+
- `package` job 在组装发布之前构建 `gui.a`/`gui.lib` 与 `media.a`/`media.lib`,
|
|
144
|
+
因此两者都会随现有 runtime 归档一起发布(`package-release` 复制整个
|
|
145
|
+
`runtime/`)。Windows x64 已包含;Windows arm64 仍跳过。
|
|
146
|
+
- `vendor/`(GUI 归档的 SDL3/FreeType/HarfBuzz,以及 `media` 的 FFmpeg,
|
|
146
147
|
缓慢的部分)按 OS/arch 缓存,以 `scripts/build-gui.ts` /
|
|
147
|
-
`scripts/build-media.ts` 为键。
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
`scripts/build-media.ts` 为键。Windows x64 有独立的源码 + FFmpeg 安装前缀
|
|
149
|
+
缓存。
|
|
150
|
+
- Windows x64 在 CI 中构建两个归档并链接一个 `gui,media` 程序;托管 runner
|
|
151
|
+
没有 GPU/Vulkan 驱动,因此 GUI/媒体示例的*运行*仍为试验性(失败只记录
|
|
152
|
+
日志而不标注运行)。Windows arm64 仍跳过两个归档(见
|
|
153
|
+
[待决问题](./gui/known-issues.md))。CI 通过
|
|
154
|
+
`.github/actions/vs-toolchain` → `scripts/setup-vs-toolchain.ps1` 使用与
|
|
155
|
+
本地构建相同的 Visual Studio MSVC + 自带 LLVM 工具链。
|
|
151
156
|
8. **M8 — 交互式 DOM** ✅
|
|
152
157
|
- 具有稳定标识的元素/文档句柄、通过运行时访问器读写属性、遍历/特性/查询、
|
|
153
158
|
带有延迟重算样式/重新布局的变更
|
|
@@ -225,6 +230,47 @@ FFmpeg `7.1`(供可选的 `media` 归档使用;可用 `SDL3_TAG` /
|
|
|
225
230
|
通过与 SVG 文件相同的 NanoSVG 缓存(`svg.{h,cpp}`)解析并光栅化;markup
|
|
226
231
|
缓存有界,DOM 变更会在下一次布局时重新序列化。e2e 见
|
|
227
232
|
`tests/e2e/gui-inline-svg.test.ts`。
|
|
233
|
+
17. **M17 — WebGL** ✅
|
|
234
|
+
- `canvas.getContext("webgl")` 创建真正的 GPU 上下文(`webgl.{h,cpp}`):
|
|
235
|
+
一张离屏 RGBA8 颜色纹理加一张深度纹理、自己的 SDL_GPU 命令缓冲,并根据
|
|
236
|
+
程序、顶点布局与固定功能状态惰性创建管线。页面通过既有图像路径直接合成
|
|
237
|
+
颜色纹理,不需要 CPU 读回。
|
|
238
|
+
- `webgl_glsl*.cpp` 把 GLSL ES 1.00/3.00 改写为 Vulkan GLSL ES 3.10
|
|
239
|
+
(属性/`varying` 位置、`gl_FragColor`、`texture2D`、每阶段一个 std140
|
|
240
|
+
uniform 块、显式采样器绑定),用静态打包的 glslang 编译,反射 SPIR-V
|
|
241
|
+
得到 uniform 偏移,并在 Metal 上用内置 SPIRV-Cross(`webgl_msl.cpp`)
|
|
242
|
+
把同一份模块交叉编译为 MSL。
|
|
243
|
+
- `dom_api_webgl*.cpp` 暴露 WebGL 1.0 接口,包括纹理、mipmap、
|
|
244
|
+
渲染到纹理的 framebuffer 与 `readPixels`。见 [WebGL](./gui/webgl.md);
|
|
245
|
+
e2e 见 `tests/e2e/gui-webgl.test.ts` 与
|
|
246
|
+
`tests/e2e/gui-example-webgl.test.ts`,示例见 `examples/gui/webgl-cube`。
|
|
247
|
+
18. **M18 — WebGL 2** ✅
|
|
248
|
+
- `canvas.getContext("webgl2")` 返回的上下文原型继承 WebGL 1 原型,并带有
|
|
249
|
+
WebGL 2 常量与方法。
|
|
250
|
+
- GLSL ES 3.00 源码(`#version 300 es`、`in`/`out`、命名片元输出、
|
|
251
|
+
`gl_InstanceID`)走同一个改写器编译。
|
|
252
|
+
- 顶点数组对象保存/恢复属性表,实例化绘制使用 SDL 的按实例输入频率,采样器
|
|
253
|
+
对象覆盖纹理单元的过滤/环绕状态。`texStorage2D`、`copyBufferSubData`、
|
|
254
|
+
`getBufferSubData` 与 `clearBuffer*` 已实现;查询/栅栏/UBO 与 transform
|
|
255
|
+
feedback 入口存在并优雅降级。见 [WebGL](./gui/webgl.md);e2e 见
|
|
256
|
+
`tests/e2e/gui-webgl2.test.ts` 与 `tests/e2e/gui-example-webgl2.test.ts`,
|
|
257
|
+
示例见 `examples/gui/webgl2-cubes`。
|
|
258
|
+
19. **M19 — 装饰性 CSS** ✅
|
|
259
|
+
- `@media` 块递归解析,并按视口求值(宽高范围、朝向、hover/pointer 与偏好
|
|
260
|
+
特性);`matchMedia()` 使用同一个求值器。
|
|
261
|
+
- 生成内容:`::before`/`::after` 选择器、继承的伪样式、`content` 字符串/
|
|
262
|
+
转义/`attr()`,以及不会泄漏到 DOM 遍历的合成布局盒。
|
|
263
|
+
- 多层 `background-image` 的线性与径向渐变,自下而上按纯色带绘制
|
|
264
|
+
(线性 18 条、径向 32 个同心椭圆)。
|
|
265
|
+
- `text-shadow` 作为阴影文本 run,并带九次采样模糊近似。
|
|
266
|
+
- `clip-path` 多边形(`inset`/`circle`/`ellipse`/`polygon`)解析到设备空间,
|
|
267
|
+
用耳切法三角化,并在 `renderer_clip.cpp` 中与图形几何求交——不需要模板/
|
|
268
|
+
shader 改动。
|
|
269
|
+
- `filter` 颜色函数、九次采样 `blur()` 与轮廓 `drop-shadow()`;
|
|
270
|
+
`backdrop-filter` 会解析并参与层叠,但需要离屏背景通道(见
|
|
271
|
+
[已知问题](./gui/known-issues.md))。
|
|
272
|
+
- e2e 覆盖见 `tests/e2e/gui-effects.test.ts`;参见
|
|
273
|
+
[绘制](./gui/rendering.md#背景生成内容与特效m19)。
|
|
228
274
|
|
|
229
275
|
## 进度日志
|
|
230
276
|
|
|
@@ -252,10 +298,13 @@ FFmpeg `7.1`(供可选的 `media` 归档使用;可用 `SDL3_TAG` /
|
|
|
252
298
|
按绘制设备像素尺寸光栅化并按该尺寸缓存,因此缩放与 HiDPI 保持清晰。
|
|
253
299
|
- **M6b** ✅ CSS transition(在 `style.*` 中解析、在 `document.*` 中维护动画
|
|
254
300
|
时钟与 transition 状态、`advance`/`advance(ms)` 钩子、e2e 覆盖)。
|
|
255
|
-
- **M7** ✅ 在 CI 中于 Linux 与
|
|
256
|
-
|
|
257
|
-
`vendor/` 被缓存,`ar -M`
|
|
258
|
-
Windows
|
|
301
|
+
- **M7** ✅ 在 CI 中于 Linux、macOS 与 Windows x64 上构建 `gui.a`/`gui.lib` 与
|
|
302
|
+
`media.a`/`media.lib`(必需),并在 Linux 的 Xvfb 下运行示例与 GUI e2e 套件;
|
|
303
|
+
`package` 发布这些归档(Windows x64 已包含),`vendor/` 被缓存,`ar -M` 合并
|
|
304
|
+
在 GNU/Linux、macOS 与 COFF/Windows 上可用。macOS 运行、Windows 示例的*运行*
|
|
305
|
+
以及 Windows arm64 在 CI 中仍为试验性。Windows job 通过
|
|
306
|
+
`.github/actions/vs-toolchain` 使用与本地构建相同的 Visual Studio MSVC +
|
|
307
|
+
自带 LLVM 工具链。
|
|
259
308
|
- **M8** ✅ 元素/文档句柄(`dom_api.*`)、带延迟重算样式/重新布局的 DOM 变更
|
|
260
309
|
(`document.*`、`xt_gui_flush_dom`)、带捕获/冒泡与 `stopPropagation` 的
|
|
261
310
|
元素事件分发(`dom_api.*`、`gui.cpp`),以及
|
|
@@ -325,4 +374,30 @@ FFmpeg `7.1`(供可选的 `media` 归档使用;可用 `SDL3_TAG` /
|
|
|
325
374
|
markup 采用有界 LRU)按绘制设备像素尺寸光栅化。`win.inlineSvg` 诊断钩子
|
|
326
375
|
暴露序列化文档,`tests/e2e/gui-inline-svg.test.ts` 固定了尺寸、命中测试、
|
|
327
376
|
渐变、CSS 盒样式与 DOM 变更。
|
|
377
|
+
- **M17** ✅ WebGL。`xtgui::WebGLContext`(`webgl.{h,cpp}`)拥有离屏颜色/深度
|
|
378
|
+
目标与命令缓冲,`webgl_buffer/texture/draw/shader` 实现 GL 对象模型,
|
|
379
|
+
`webgl_glsl*.cpp` 用内置 glslang 把 GLSL ES 翻译为 SPIR-V
|
|
380
|
+
(`webgl_msl.cpp`/SPIRV-Cross 在 Metal 上把该模块转成 MSL),
|
|
381
|
+
`dom_api_webgl*.cpp` 绑定 WebGL 1.0 接口。`renderer_image.cpp` 按 canvas id
|
|
382
|
+
返回上下文的颜色纹理,页面直接合成 GPU 输出。示例
|
|
383
|
+
`examples/gui/webgl-cube`;e2e 见 `tests/e2e/gui-webgl.test.ts` 与
|
|
384
|
+
`tests/e2e/gui-example-webgl.test.ts`。
|
|
385
|
+
- **M18** ✅ WebGL 2。`webgl2_proto()` 在 WebGL 1 原型上增加 WebGL 2 常量与
|
|
386
|
+
方法;`webgl_webgl2.cpp` 实现顶点数组对象与采样器/查询/栅栏句柄,
|
|
387
|
+
`webgl_draw.cpp` 增加实例化绘制(由 `vertexAttribDivisor` 决定输入频率)与
|
|
388
|
+
整数属性,`webgl_texture.cpp` 增加 `texStorage2D` 与 `clearBuffer*`。着色器
|
|
389
|
+
改写器为 `#version 300 es` 输出分配连续 location,块反射会把结构体字段展开
|
|
390
|
+
成 three.js 灯光可寻址的成员。three.js r160 已在真实渲染器上跑通基础/标准/
|
|
391
|
+
Phong 材质、纹理、灯光、雾、精灵、线段、点与实例化;Canvas2D 回退已删除。
|
|
392
|
+
示例 `examples/gui/webgl2-cubes`(64 个立方体,一次实例化绘制);e2e 见
|
|
393
|
+
`tests/e2e/gui-webgl2.test.ts` 与 `tests/e2e/gui-example-webgl2.test.ts`。
|
|
394
|
+
- **M19** ✅ 装饰性 CSS。`css_sheet.cpp` 解析嵌套 `@media` 块,
|
|
395
|
+
`media_query.cpp` 按视口求值(`matchMedia` 也用它);`css_selector.cpp`
|
|
396
|
+
识别 `::before`/`::after`。`style.cpp` 把伪样式算进每次重算样式时重建的
|
|
397
|
+
arena、解析 `content`,布局在真实子元素前后插入它们的盒子。
|
|
398
|
+
`gradient_values.cpp` 建模背景层列表(线性/径向、形状/尺寸/位置/色标),
|
|
399
|
+
`paint_background.cpp` 绘制它,`paint_effects.cpp` 应用滤镜颜色函数与九次
|
|
400
|
+
采样模糊/投影并生成 `text-shadow` run,`paint_clip.cpp`/`renderer_clip.cpp`
|
|
401
|
+
对三角化的 `clip-path` 多边形裁剪几何。e2e 见
|
|
402
|
+
`tests/e2e/gui-effects.test.ts`。
|
|
328
403
|
|
package/doc/zh-CN/npm-package.md
CHANGED
|
@@ -58,8 +58,9 @@ TypeScript 编译器。
|
|
|
58
58
|
- 预编译的运行时归档(`runtime/lib/<os>-<arch>/core.a`)。驱动会在首次使用时
|
|
59
59
|
从随包发布的源码编译 C 运行时并缓存目标文件,所以第一次构建会更慢
|
|
60
60
|
(见[首次构建与缓存](#首次构建与缓存));
|
|
61
|
-
- GUI/media 的原生归档(`gui.a`、`media.a`)。如果你需要
|
|
62
|
-
`--ext media`,请使用 Linux/macOS
|
|
61
|
+
- GUI/media 的原生归档(`gui.a`/`gui.lib`、`media.a`/`media.lib`)。如果你需要
|
|
62
|
+
`--ext gui` 或 `--ext media`,请使用 Linux/macOS/Windows x64 的发布压缩包,
|
|
63
|
+
或从源码检出中构建这些归档。
|
|
63
64
|
|
|
64
65
|
## 环境要求
|
|
65
66
|
|
|
@@ -339,8 +340,10 @@ jobs:
|
|
|
339
340
|
目标文件名是内容哈希,因此旧缓存不会污染新构建。
|
|
340
341
|
- xbintsc 只为**宿主**平台构建,不是交叉编译器:要给多个平台产出产物,请使用
|
|
341
342
|
CI matrix(每个 OS/arch 一个 job)。
|
|
342
|
-
- macOS runner 已经带有 Xcode Command Line Tools;Windows runner 需要安装
|
|
343
|
-
|
|
343
|
+
- macOS runner 已经带有 Xcode Command Line Tools;Windows runner 需要安装
|
|
344
|
+
Visual Studio C++ 生成工具(MSVC + 自带的 LLVM),产物是 `build\main.exe`。
|
|
345
|
+
在源码检出中可运行 `pwsh -File scripts/setup-vs-toolchain.ps1` 显式导入该
|
|
346
|
+
工具链。
|
|
344
347
|
|
|
345
348
|
## npm 包还是发布压缩包?
|
|
346
349
|
|
|
@@ -348,7 +351,7 @@ jobs:
|
|
|
348
351
|
| --- | --- | --- |
|
|
349
352
|
| 需要 Node.js | 是,22+ | 否 |
|
|
350
353
|
| 首次构建 | 从源码编译 C 运行时 | 直接链接预编译运行时 |
|
|
351
|
-
| GUI / media 扩展 | 不包含 | Linux/macOS 压缩包包含 |
|
|
354
|
+
| GUI / media 扩展 | 不包含 | Linux/macOS 与 Windows x64 压缩包包含 |
|
|
352
355
|
| 安装方式 | `npm install` + lockfile / provenance | 下载、校验 `.sha256`、解压 |
|
|
353
356
|
| 编程 API | 有 | 无(仅 CLI) |
|
|
354
357
|
| 交叉编译 | 否——只构建宿主平台 | 否——只构建宿主平台 |
|
|
@@ -383,7 +386,7 @@ jobs:
|
|
|
383
386
|
| 第一次构建很慢 | 正常:正在编译并缓存运行时 C 源码。后续构建会复用 `.xbintsc/`;`--time` 可确认。如果冷启动必须快,请使用发布压缩包。 |
|
|
384
387
|
| 写 `.xbintsc/` 权限错误 | 用 `xbintsc_CACHE_DIR` 指向可写目录,或在可写目录中运行。 |
|
|
385
388
|
| `module 'fs' is provided by the 'node' extension` | 加 `--ext node`,或在配置里写 `"extensions": ["node"]`。 |
|
|
386
|
-
| `GUI native library not found` / `media native library not found` | npm 包不包含 `gui.a`/`media.a`;请使用 Linux/macOS 发布压缩包,或从源码检出构建。 |
|
|
389
|
+
| `GUI native library not found` / `media native library not found` | npm 包不包含 `gui.a`/`gui.lib` 或 `media.a`/`media.lib`;请使用 Linux/macOS/Windows x64 发布压缩包,或从源码检出构建。 |
|
|
387
390
|
| `require("xbintsc")` 失败 | 包只提供 ESM;使用 `import`(或动态 `import()`)。 |
|
|
388
391
|
| Windows 链接时报缺少 MSVC 库 | 在 Native Tools 命令提示符中运行,安装 VS C++ 生成工具,并检查 `npx xbintsc doctor`。 |
|
|
389
392
|
| `npm ci --omit=dev` 后构建找不到 `xbintsc` | 在构建阶段安装 devDependencies,或把 `xbintsc` 移到 `dependencies`。 |
|
|
@@ -116,19 +116,21 @@ sudo apk add clang lld # Alpine
|
|
|
116
116
|
用 `clang --version` 验证。如果 xbintsc 用错了链接器,可用 `xbintsc_CLANG` 指定
|
|
117
117
|
clang,并通过 `xbintsc_LINKER_ARGS` 追加参数(例如 `-fuse-ld=lld`)。
|
|
118
118
|
|
|
119
|
-
## Windows —— 安装 MSVC C++
|
|
119
|
+
## Windows —— 安装 MSVC C++ 生成工具(含 LLVM)
|
|
120
120
|
|
|
121
|
-
Windows 上的 xbintsc 面向 **MSVC ABI
|
|
122
|
-
|
|
121
|
+
Windows 上的 xbintsc 面向 **MSVC ABI**。一条 `winget` 命令即可安装 Visual
|
|
122
|
+
Studio C++ 工作负载、MSBuild,以及本地构建脚本与 CI 使用的 Clang 组件:
|
|
123
123
|
|
|
124
124
|
```powershell
|
|
125
|
-
winget install -e --id LLVM.LLVM
|
|
126
125
|
winget install -e --id Microsoft.VisualStudio.2022.BuildTools `
|
|
127
|
-
--override "--quiet --wait --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"
|
|
126
|
+
--override "--quiet --wait --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --includeRecommended"
|
|
128
127
|
```
|
|
129
128
|
|
|
130
129
|
Visual Studio 2022 自带的 LLVM(`VC\Tools\Llvm\x64\bin\clang.exe`,当前版本
|
|
131
|
-
19.1.5
|
|
130
|
+
19.1.5)就是 `scripts/setup-vs-toolchain.ps1` 选择的工具链。独立安装的 LLVM
|
|
131
|
+
(`winget install -e --id LLVM.LLVM`)对 `xbintsc` 本身也可用,但 GUI/媒体
|
|
132
|
+
归档构建与 CI 都使用 Visual Studio 这一套,从而让运行时、预编译归档与最终
|
|
133
|
+
二进制出自同一条工具链。无论哪种,编译器必须以 MSVC ABI 为目标
|
|
132
134
|
(`Target: *-windows-msvc`):面向其他 Windows ABI 的 clang 无法与 MSVC
|
|
133
135
|
运行库链接,`xbintsc` 会直接给出明确错误并拒绝使用。
|
|
134
136
|
|
|
@@ -141,6 +143,10 @@ Visual Studio 2022 自带的 LLVM(`VC\Tools\Llvm\x64\bin\clang.exe`,当前
|
|
|
141
143
|
& "$env:ProgramFiles\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
|
|
142
144
|
```
|
|
143
145
|
|
|
146
|
+
在源码检出中,`pwsh -File scripts/setup-vs-toolchain.ps1` 会完成同样的导入,
|
|
147
|
+
并把 `xbintsc_CLANG` 指向该 Visual Studio 安装自带的 LLVM。CI 调用的是同一个
|
|
148
|
+
脚本,因此本地构建、发布归档与 CI 共用一条 Visual Studio 工具链。
|
|
149
|
+
|
|
144
150
|
用 `xbintsc doctor`(或 `clang --version`)验证;输出会列出解析到的编译器、
|
|
145
151
|
版本与目标。
|
|
146
152
|
|
package/llms.txt
CHANGED
|
@@ -75,6 +75,8 @@
|
|
|
75
75
|
- [doc/gui/input.md](https://raw.githubusercontent.com/zy445566/xbintsc/main/doc/gui/input.md): hit testing, events and `:hover`/`:focus`
|
|
76
76
|
- [doc/gui/animation.md](https://raw.githubusercontent.com/zy445566/xbintsc/main/doc/gui/animation.md): `requestAnimationFrame` and CSS transitions
|
|
77
77
|
- [doc/gui/runtime.md](https://raw.githubusercontent.com/zy445566/xbintsc/main/doc/gui/runtime.md): event loop integration, the native bridge and memory
|
|
78
|
+
- [doc/gui/canvas.md](https://raw.githubusercontent.com/zy445566/xbintsc/main/doc/gui/canvas.md): `<canvas>` and the 2D context
|
|
79
|
+
- [doc/gui/webgl.md](https://raw.githubusercontent.com/zy445566/xbintsc/main/doc/gui/webgl.md): WebGL 1.0 on the GPU — GLSL ES to SPIR-V, textures, framebuffers and readback
|
|
78
80
|
- [doc/gui/build.md](https://raw.githubusercontent.com/zy445566/xbintsc/main/doc/gui/build.md): building `gui.a` and running the examples
|
|
79
81
|
- [doc/gui/known-issues.md](https://raw.githubusercontent.com/zy445566/xbintsc/main/doc/gui/known-issues.md): known issues and open questions
|
|
80
82
|
- [doc/gui-scripts.md](https://raw.githubusercontent.com/zy445566/xbintsc/main/doc/gui-scripts.md): the GUI scripting surface
|
package/package.json
CHANGED
|
@@ -156,15 +156,25 @@ xt_value win_location_get(xt_value self, xt_value env, int32_t argc, xt_value *a
|
|
|
156
156
|
return g_location;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
xt_value media_list_build(const std::string &query, bool matches);
|
|
160
|
+
|
|
161
|
+
/** `matchMedia(query)` -> a MediaQueryList-shaped object evaluated against the
|
|
162
|
+
* current window's viewport, using the same evaluator as `@media` rules. The
|
|
163
|
+
* list is a snapshot (there is no live change event), which matches the
|
|
164
|
+
* engine's restyle-on-resize model. */
|
|
162
165
|
xt_value win_match_media(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
163
|
-
(void)self;
|
|
164
166
|
(void)env;
|
|
165
|
-
|
|
166
|
-
(
|
|
167
|
-
|
|
167
|
+
std::string query;
|
|
168
|
+
if (argc >= 1) query = cstr(xt_arg(argc, argv, 0));
|
|
169
|
+
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
170
|
+
if (win == NULL) {
|
|
171
|
+
xt_value handle = xt_gui_ensure_window();
|
|
172
|
+
win = xt_gui_window_from_this(handle);
|
|
173
|
+
}
|
|
174
|
+
float width = 0.0f;
|
|
175
|
+
float height = 0.0f;
|
|
176
|
+
if (win != NULL) xt_gui_window_viewport(win, &width, &height);
|
|
177
|
+
return media_list_build(query, xtgui::xt_css_media_matches(query, width, height));
|
|
168
178
|
}
|
|
169
179
|
|
|
170
180
|
/** `getComputedStyle(el)`: the engine exposes the element's style handle, which
|
|
@@ -243,10 +253,10 @@ xt_value location_build(void) {
|
|
|
243
253
|
return location;
|
|
244
254
|
}
|
|
245
255
|
|
|
246
|
-
xt_value media_list_build(
|
|
256
|
+
xt_value media_list_build(const std::string &query, bool matches) {
|
|
247
257
|
xt_value list = xt_object_new();
|
|
248
|
-
set_prop(list, "media",
|
|
249
|
-
set_prop(list, "matches", XT_FALSE);
|
|
258
|
+
set_prop(list, "media", xt_string_from_cstr(query.c_str()));
|
|
259
|
+
set_prop(list, "matches", matches ? XT_TRUE : XT_FALSE);
|
|
250
260
|
set_method(list, "addListener", (void *)noop);
|
|
251
261
|
set_method(list, "removeListener", (void *)noop);
|
|
252
262
|
set_method(list, "addEventListener", (void *)noop);
|
|
@@ -332,6 +342,21 @@ xt_value type_proto(const std::string &name) {
|
|
|
332
342
|
return domapi::event_proto();
|
|
333
343
|
}
|
|
334
344
|
if (name == "AudioContext" || name == "webkitAudioContext") return xt_gui_audio_proto();
|
|
345
|
+
if (name == "WebGLRenderingContext") return domapi::webgl_proto();
|
|
346
|
+
if (name == "WebGL2RenderingContext") return domapi::webgl2_proto();
|
|
347
|
+
if (name == "WebGLBuffer") return domapi::webgl_object_proto("buffer");
|
|
348
|
+
if (name == "WebGLTexture") return domapi::webgl_object_proto("texture");
|
|
349
|
+
if (name == "WebGLShader") return domapi::webgl_object_proto("shader");
|
|
350
|
+
if (name == "WebGLProgram") return domapi::webgl_object_proto("program");
|
|
351
|
+
if (name == "WebGLFramebuffer") return domapi::webgl_object_proto("framebuffer");
|
|
352
|
+
if (name == "WebGLRenderbuffer") return domapi::webgl_object_proto("renderbuffer");
|
|
353
|
+
if (name == "WebGLUniformLocation") return domapi::webgl_object_proto("uniform");
|
|
354
|
+
if (name == "WebGLActiveInfo") return domapi::webgl_object_proto("info");
|
|
355
|
+
if (name == "WebGLVertexArrayObject") return domapi::webgl_object_proto("vertexarray");
|
|
356
|
+
if (name == "WebGLSampler") return domapi::webgl_object_proto("sampler");
|
|
357
|
+
if (name == "WebGLQuery") return domapi::webgl_object_proto("query");
|
|
358
|
+
if (name == "WebGLSync") return domapi::webgl_object_proto("sync");
|
|
359
|
+
if (name == "WebGLTransformFeedback") return domapi::webgl_object_proto("transformfeedback");
|
|
335
360
|
return domapi::node_proto();
|
|
336
361
|
}
|
|
337
362
|
|
|
@@ -382,6 +407,8 @@ void install_window_globals(xt_value win) {
|
|
|
382
407
|
set_prop(win, "Audio", type_value("Audio"));
|
|
383
408
|
set_prop(win, "Event", type_value("Event"));
|
|
384
409
|
set_prop(win, "CustomEvent", type_value("CustomEvent"));
|
|
410
|
+
set_prop(win, "WebGLRenderingContext", type_value("WebGLRenderingContext"));
|
|
411
|
+
set_prop(win, "WebGL2RenderingContext", type_value("WebGL2RenderingContext"));
|
|
385
412
|
set_prop(win, "isSecureContext", XT_TRUE);
|
|
386
413
|
set_number(win, "screenX", 0);
|
|
387
414
|
set_number(win, "screenY", 0);
|
|
@@ -402,7 +429,7 @@ void ensure_singletons(void) {
|
|
|
402
429
|
xt_gc_add_root(&g_location);
|
|
403
430
|
}
|
|
404
431
|
if (!XT_IS_OBJECT(g_media_list)) {
|
|
405
|
-
g_media_list = media_list_build();
|
|
432
|
+
g_media_list = media_list_build("", false);
|
|
406
433
|
xt_gc_add_root(&g_media_list);
|
|
407
434
|
}
|
|
408
435
|
}
|
|
@@ -500,8 +527,7 @@ xt_value xt_browser_type(int32_t argc, xt_value *argv) {
|
|
|
500
527
|
(void)argv;
|
|
501
528
|
if (argc < 1) return XT_UNDEFINED;
|
|
502
529
|
std::string name = cstr(xt_arg(argc, argv, 0));
|
|
503
|
-
if (name == "
|
|
504
|
-
name == "XRWebGLLayer" || name == "XRWebGLBinding" || name == "OffscreenCanvas" ||
|
|
530
|
+
if (name == "XRWebGLLayer" || name == "XRWebGLBinding" || name == "OffscreenCanvas" ||
|
|
505
531
|
name == "ImageBitmap" || name == "ImageData" || name == "Response" ||
|
|
506
532
|
name == "ReadableStream" || name == "Request" || name == "Headers" ||
|
|
507
533
|
name == "DOMParser") {
|
|
@@ -457,24 +457,9 @@ void Canvas2D::draw_image(const Image &source, float dx, float dy, float dw, flo
|
|
|
457
457
|
canvas_detail::draw_image(image_.pixels, image_.width, image_.height, source, x0, y0, x1 - x0,
|
|
458
458
|
y1 - y0, sx, sy, sw, sh, state_.global_alpha);
|
|
459
459
|
} else {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
float minX = 0.0f, minY = 0.0f, maxX = 0.0f, maxY = 0.0f;
|
|
464
|
-
for (int i = 0; i < 4; i++) {
|
|
465
|
-
to_device(corners[i][0], corners[i][1], &cornersX[i], &cornersY[i]);
|
|
466
|
-
if (i == 0) {
|
|
467
|
-
minX = maxX = cornersX[i];
|
|
468
|
-
minY = maxY = cornersY[i];
|
|
469
|
-
} else {
|
|
470
|
-
minX = std::min(minX, cornersX[i]);
|
|
471
|
-
maxX = std::max(maxX, cornersX[i]);
|
|
472
|
-
minY = std::min(minY, cornersY[i]);
|
|
473
|
-
maxY = std::max(maxY, cornersY[i]);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
canvas_detail::draw_image(image_.pixels, image_.width, image_.height, source, minX, minY,
|
|
477
|
-
maxX - minX, maxY - minY, sx, sy, sw, sh, state_.global_alpha);
|
|
460
|
+
canvas_detail::draw_image_affine(image_.pixels, image_.width, image_.height, source, dx, dy,
|
|
461
|
+
dw, dh, sx, sy, sw, sh, state_.transform,
|
|
462
|
+
state_.global_alpha);
|
|
478
463
|
}
|
|
479
464
|
generation_++;
|
|
480
465
|
}
|
|
@@ -48,6 +48,16 @@ void draw_image(std::vector<unsigned char> &pixels, int width, int height, const
|
|
|
48
48
|
float dx, float dy, float dw, float dh, float sx, float sy, float sw, float sh,
|
|
49
49
|
float alpha);
|
|
50
50
|
|
|
51
|
+
/** Blit an RGBA8 source through a full affine transform. The destination
|
|
52
|
+
* rectangle is mapped to a parallelogram by `transform`; each device pixel is
|
|
53
|
+
* inverse-mapped and sampled from the source rectangle. This is the path that
|
|
54
|
+
* makes rotated/skewed `drawImage` (and perspective-grid canvas textures) draw
|
|
55
|
+
* the image instead of squashing it into the bounding box. */
|
|
56
|
+
void draw_image_affine(std::vector<unsigned char> &pixels, int width, int height,
|
|
57
|
+
const Image &source, float dx, float dy, float dw, float dh, float sx,
|
|
58
|
+
float sy, float sw, float sh, const CanvasTransform &transform,
|
|
59
|
+
float alpha);
|
|
60
|
+
|
|
51
61
|
/** Composite one grayscale glyph bitmap at `(x, baselineY)` with `paint`. */
|
|
52
62
|
void blit_glyph(std::vector<unsigned char> &pixels, int width, int height,
|
|
53
63
|
const std::vector<unsigned char> &glyph, int glyphWidth, int glyphHeight, int left,
|
|
@@ -269,6 +269,66 @@ void draw_image(std::vector<unsigned char> &pixels, int width, int height, const
|
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
+
|
|
273
|
+
void draw_image_affine(std::vector<unsigned char> &pixels, int width, int height,
|
|
274
|
+
const Image &source, float dx, float dy, float dw, float dh, float sx,
|
|
275
|
+
float sy, float sw, float sh, const CanvasTransform &transform,
|
|
276
|
+
float alpha) {
|
|
277
|
+
if (source.width <= 0 || source.height <= 0 || dw <= 0.0f || dh <= 0.0f || sw <= 0.0f ||
|
|
278
|
+
sh <= 0.0f)
|
|
279
|
+
return;
|
|
280
|
+
CanvasTransform inverse = transform.inverted();
|
|
281
|
+
float cornersX[4];
|
|
282
|
+
float cornersY[4];
|
|
283
|
+
const float corners[4][2] = {{dx, dy}, {dx + dw, dy}, {dx + dw, dy + dh}, {dx, dy + dh}};
|
|
284
|
+
float minX = 0.0f, minY = 0.0f, maxX = 0.0f, maxY = 0.0f;
|
|
285
|
+
for (int i = 0; i < 4; i++) {
|
|
286
|
+
transform.apply(corners[i][0], corners[i][1], &cornersX[i], &cornersY[i]);
|
|
287
|
+
if (i == 0) {
|
|
288
|
+
minX = maxX = cornersX[i];
|
|
289
|
+
minY = maxY = cornersY[i];
|
|
290
|
+
} else {
|
|
291
|
+
minX = std::min(minX, cornersX[i]);
|
|
292
|
+
maxX = std::max(maxX, cornersX[i]);
|
|
293
|
+
minY = std::min(minY, cornersY[i]);
|
|
294
|
+
maxY = std::max(maxY, cornersY[i]);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
int ix0 = std::max(0, (int)std::floor(minX));
|
|
298
|
+
int ix1 = std::min(width, (int)std::ceil(maxX));
|
|
299
|
+
int iy0 = std::max(0, (int)std::floor(minY));
|
|
300
|
+
int iy1 = std::min(height, (int)std::ceil(maxY));
|
|
301
|
+
for (int py = iy0; py < iy1; py++) {
|
|
302
|
+
for (int px = ix0; px < ix1; px++) {
|
|
303
|
+
float ux = 0.0f;
|
|
304
|
+
float uy = 0.0f;
|
|
305
|
+
inverse.apply((float)px + 0.5f, (float)py + 0.5f, &ux, &uy);
|
|
306
|
+
float u = (ux - dx) / dw;
|
|
307
|
+
float v = (uy - dy) / dh;
|
|
308
|
+
if (u < 0.0f || u >= 1.0f || v < 0.0f || v >= 1.0f) continue;
|
|
309
|
+
int sxi = (int)(sx + u * sw);
|
|
310
|
+
int syi = (int)(sy + v * sh);
|
|
311
|
+
if (sxi < 0) sxi = 0;
|
|
312
|
+
if (syi < 0) syi = 0;
|
|
313
|
+
if (sxi >= source.width) sxi = source.width - 1;
|
|
314
|
+
if (syi >= source.height) syi = source.height - 1;
|
|
315
|
+
const unsigned char *texel =
|
|
316
|
+
source.pixels.data() + ((size_t)syi * (size_t)source.width + (size_t)sxi) * 4;
|
|
317
|
+
unsigned char *dst = pixels.data() + ((size_t)py * (size_t)width + (size_t)px) * 4;
|
|
318
|
+
if (alpha >= 0.999f) {
|
|
319
|
+
const unsigned char ta = texel[3];
|
|
320
|
+
if (ta == 255) {
|
|
321
|
+
dst[0] = texel[0]; dst[1] = texel[1]; dst[2] = texel[2]; dst[3] = 255;
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
if (ta == 0) continue;
|
|
325
|
+
}
|
|
326
|
+
float color[4] = {texel[0] / 255.0f, texel[1] / 255.0f, texel[2] / 255.0f, texel[3] / 255.0f};
|
|
327
|
+
blend_pixel(dst, color, 1.0f, alpha);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
272
332
|
void blit_glyph(std::vector<unsigned char> &pixels, int width, int height,
|
|
273
333
|
const std::vector<unsigned char> &glyph, int glyphWidth, int glyphHeight, int left,
|
|
274
334
|
int top, float x, float baselineY, const CanvasPaint &paint, float alpha) {
|