2V0-g: port the .fnt font pipeline over a FreeType GDI emulation

CGraphicText, CGraphicFontTexture and CGraphicDib are the 40250 bodies
verbatim; CGraphicTextInstance is verbatim except that its D3D draws become
UI render commands (one image quad per glyph, Bar for cursor/underline).

- platform/Win32Gdi.cpp: the GDI subset those files call, over vendored
  FreeType 2.13.3, following GDI's LOGFONT cell height, win metrics and gasp
  rules; system font lookup with substitute and CJK fallback faces
- Win32Crt: MultiByteToWideChar / WideCharToMultiByte (UTF-8 and 1252 by
  hand, other code pages through iconv)
- CGraphicImageTexture memory textures: glyph pages reach Godot as
  "mem:<id>@<revision>"; Metin2PythonHost.memory_texture + Canvas cache
- Util.cpp code page / font face table, SetDefaultCodePage at boot,
  DefaultFont_* block, fnt resource type, GetMaxTextureWidth/Height
- TextTag, StringCodec, Arabic, Vietnamese copied from 40250
- tests: port.text (Tahoma 12 metrics, alignment, CP949), port.app_loop
  and python_host_test.gd now check glyph quads instead of text commands

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-23 14:17:25 +09:00
co-authored by Claude Opus 5.5
parent 141206cb69
commit afe63bfa61
272 changed files with 137097 additions and 316 deletions
+2 -1
View File
@@ -400,7 +400,8 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次
| 2V0-c | `wndMgr` / `grp` / `grpImage` / `grpText` / `grpThing` 模块 | 绑定已移植并通过导入/窗口句柄测试;图形绘制仍属 2V0-f |
| 2V0-d | 42 个 `UserInterface` 头(都在 `PythonApplication.h` 后面)+ `PythonApplicationModule.cpp`(`app`) | 头与绑定已编译、链接并导入;应用生命周期 adapter 仍属 2V0-f |
| 2V0-e | `dbg` 等桩模块补齐,`system.py` 跑到 `prototype.RunApp()` | 完成:27 个玩法 native 模块导出名桩记录每次调用;真实 `system.py` 已进入 `RunApp()`,目前由待实现的 `app.Create()` 报 `CREATE_DEVICE` |
| 2V0-f | Godot 渲染器上的 platform UI adapter;Logo/Popup 可显示可操作 | 完成:真实 `system.py` 在 app 进程内的脚本纤程上跑 `app.Loop()`(每个 `UIUpdate` = 一次 `CPythonApplication::Process()`),Logo→Login 切换、Popup ESC/点击、`app.Exit` 收尾(按 40250 Main 先 `pyLauncher.Clear()`);图像统一为基贴图 + UV 的四边形命令(`.sub` 共用父贴图名),ExpandedImage 缩放/旋转/RenderingRect 原样移植;`grp.GenerateColor` 已移植(ThinBoard 半透明底)。`port.app_loop` + `python_host_test.gd` 覆盖输入/焦点/裁剪/文字/图像;`MT_TEST_MODE=python_ui` 可视运行。TODO:`.fnt`/`CGraphicText` 字体管线(现用 Godot 回退字体、无对齐)、ExpandedImage 混合模式(SCREEN/COLOR_DODGE/MODULATE)未应用。 |
| 2V0-f | Godot 渲染器上的 platform UI adapter;Logo/Popup 可显示可操作 | 完成:真实 `system.py` 在 app 进程内的脚本纤程上跑 `app.Loop()`(每个 `UIUpdate` = 一次 `CPythonApplication::Process()`),Logo→Login 切换、Popup ESC/点击、`app.Exit` 收尾(按 40250 Main 先 `pyLauncher.Clear()`);图像统一为基贴图 + UV 的四边形命令(`.sub` 共用父贴图名),ExpandedImage 缩放/旋转/RenderingRect 原样移植;`grp.GenerateColor` 已移植(ThinBoard 半透明底)。`port.app_loop` + `python_host_test.gd` 覆盖输入/焦点/裁剪/文字/图像;`MT_TEST_MODE=python_ui` 可视运行。TODO:ExpandedImage 混合模式(SCREEN/COLOR_DODGE/MODULATE)未应用(字体管线见 2V0-g)。 |
| 2V0-g | `.fnt` 字体管线:`CGraphicText` / `CGraphicFontTexture` / `CGraphicDib` / `CGraphicTextInstance` | 完成:四个文件原样移植(`GrpTextInstance` 只把 D3D 绘制换成 UI 命令:每个字形一个四边形,光标/IME 下划线为 Bar);GDI 子集(`CreateFontIndirect`/`CreateDIBSection`/`TextOutW`/`GetTextExtentPoint32W`/`GetCharABCWidthsFloatW`)在 `platform/Win32Gdi.cpp` 用 FreeType 按 GDI 规则模拟(LOGFONT 负高度=字符格高、win ascent/descent、gasp 决定单色/灰度、v35 解释器、斜体 oblique),字体按文件名在系统字体目录找,缺字体按 Arial/Roboto 等替换、缺字按 CJK 字体回退;字形页作为内存纹理(`mem:<id>@<rev>`)交给 Godot,Canvas 按 id 缓存、rev 变了才重取;`MultiByteToWideChar`/`WideCharToMultiByte`(UTF-8/1252 手写,其余代码页走 iconv);`Util.cpp` 代码页→字体表、`SetDefaultCodePage` 在启动时按 40250 Main 调用;`DefaultFont_*` 原样;`fnt` 资源类型注册。`port.text`(Tahoma 12 行高 12、宽度/字符定位/居中、CP949 往返)+ `port.app_loop` + `python_host_test.gd` 验证。TODO:Android 的 `/system/fonts` 没有 Tahoma/Gulim,需要随包带字体(现走 Roboto/Noto 替换,度量与原版不同);字形与 Windows GDI 的逐像素对比未做。 |
2. **2V1 — 登录/选角**:加入 `PythonNetworkStream{,PhaseHandShake,PhaseLogin,PhaseSelect,PhaseLoading}.cpp`、
`PythonNetworkStreamModule.cpp`、AccountConnector 及登录/选角脚本真实调用到的模块。验收为 FakeServer 离线完成 phase 顺序,
再以真服 smoke 证明登录、角色列表和选择进入 Loading;未验证的服务器分支记 `NEEDS_LIVE`。
+20 -1
View File
@@ -8,7 +8,8 @@ build. Crypto++ joined later (2026-09-02) with the `MT_PROTOCOL=classic` 40250
backend and was vendored the same way from the start.
CPython joined on 2026-09-23 with 批次 2P (the embedded 40250 script layer) and is
vendored source as well.
vendored source as well. FreeType joined the same day with 批次 2V0-g (the 40250
font path over an emulated GDI).
Everything lives under `extension/third_party/` and is wired by
`extension/third_party/CMakeLists.txt`, which exposes five aliases:
@@ -20,6 +21,7 @@ Everything lives under `extension/third_party/` and is wired by
| `mt3p::minilzo` | `minilzo` | `mtproto` |
| `mt3p::cryptopp` | `cryptopp` | `mtnet` (classic backend) |
| `mt3p::python` | `mtpython` | the script layer (`py_embed_test`) |
| `mt3p::freetype` | `freetype` | `port_platform` (`platform/Win32Gdi.cpp`) |
No source file changed: `#include <sodium.h>`, `#include <zstd.h>`,
`#include <lzo/lzo1x.h>` and `#include <cryptopp/…>` all still resolve (the LZO
@@ -143,6 +145,23 @@ one via a 1-line shim header, see below).
only obligation is keeping the license and a change notice, which this section
and the patched files' comments serve.
## FreeType 2.13.3 — vendored source, trimmed (not a submodule)
* **Files:** `extension/third_party/freetype-2.13.3/` (~5 MB): the official
`freetype-2.13.3.tar.xz` (source URL and sha256 in the directory's
`CMakeLists.txt` header) cut down to `include/`, `src/{base,sfnt,truetype,smooth,raster,psnames,gzip}`,
`LICENSE.TXT` and `docs/FTL.TXT`.
* **Build:** our own `CMakeLists.txt` (upstream's pulls in optional deps we don't
want); `mt-config/freetype/config/ftmodule.h` replaces the stock module list with
TrueType + sfnt + the mono and gray rasterizers. No upstream file is modified.
* **Why:** 40250's `CGraphicFontTexture` / `CGraphicDib` render glyphs with GDI
(`CreateFontIndirect`, `TextOutW` into a DIB section). `platform/Win32Gdi.cpp`
implements that GDI subset over FreeType with GDI's cell-height, win-metric and
gasp rules, so the 40250 font code stays verbatim.
* **License:** FreeType License (`docs/FTL.TXT`, BSD-style with credit clause):
the shipped product's documentation must credit "Portions of this software are
copyright © The FreeType Project (www.freetype.org)".
## Rebuilding / fetching
`./build.sh` auto-runs `git submodule update --init --recursive` if any of the