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
+1
View File
@@ -506,3 +506,4 @@
{"time": "2026-09-23T03:04:18Z", "event": "port_round", "unit": "PORT-PLAN 2V0-e: native gameplay import stubs through prototype.RunApp", "ported": [], "adapted": ["27 native module import surfaces generated from 40250 UserInterface export names; functions log module.method and return a placeholder zero", "LocaleService default en/1252 from supplied Client/locale.cfg; ForceSetLocale stores requested path", "CPythonApplication::Create platform stub raises CREATE_DEVICE so prototype.RunApp handles failure as original Python code expects"], "divergent": ["Gameplay module methods and constants are placeholders, not ports; their calls do not implement gameplay", "The app platform adapter does not create a device, so RunApp exits before Logo/Popup"], "tests": ["godot --headless --path project --script python_host_test.gd -> PASS: system.py reaches prototype.RunApp, catches CREATE_DEVICE, and net/player/item are marked __port_stub__", "ctest --test-dir build --output-on-failure -j6 -> 29/29 passed, one skipped", "port_map.py check -> 0 errors"], "not_done": "2V0-f: real Godot UI adapter, visible interactive Logo/Popup, input/focus/clipping/text/image tests"}
{"time": "2026-09-23T03:27:45Z", "event": "port_round", "unit": "PORT-PLAN 2V0-f: Godot window input and Canvas UI command adapter (partial)", "ported": [], "adapted": ["40250 CWindowManager mouse/key/focus/update bridge into Godot", "CGraphicScreen Bar/Line viewport clip and CGraphicTextInstance text render commands", "CGraphicImage and CGraphicImageInstance image command generation; CPythonResource registration; TGA/DDS/PNG dimensions", "Godot Canvas Control renders native commands and decodes TGA images from 40250 pack", "CGraphicSubImage .sub registration, referenced image dimensions and crop bounds", "CGraphicExpandedImageInstance allocation, type identity and lifetime for script bindings"], "divergent": ["CPythonApplication::Create and Loop are still platform stubs: real system.py cannot show Logo/Popup", "Text metrics, fonts, vertical clipping and non-TGA packed image variants are not verified at parity", "ExpandedImage Canvas rendering still omits original rotation, scale, rendering rectangle and blend mode", "Exploratory monkeypatch past app.Create reaches logo setup but stopping that second RunApp crashes during Python finalization; lifecycle ownership remains unresolved"], "needs_live": [], "tests": ["cmake --build build --target mtgodot -j6: pass", "godot --headless --path project --script python_host_test.gd: pass input/focus/update, bar, clip, text, packed TGA texture, .sub and ExpandedImage create/delete", "ctest --test-dir build --output-on-failure -j6: 29/29 pass, one skipped", "git diff --check: pass"], "not_done": "2V0-f application lifecycle adapter and real visible interactive Logo/Popup; normal app route remains legacy and 2V0 acceptance gate is open", "status_note": "No audit/port-map entry changed. The skill mentions scripts/port_map.py, but that file is absent from this checkout; no port-map check was run."}
{"time": "2026-09-23T04:35:58Z", "event": "port_round", "unit": "PORT-PLAN 2V0-f: real system.py app loop in Godot (complete)", "ported": ["CGraphicExpandedImageInstance::OnRender and SetRenderingRect (40250 verbatim)", "CGraphicImageInstance::OnRender (40250 verbatim)", "CGraphicBase::GetColor / CPythonGraphic::GenerateColor"], "adapted": ["script fiber runs system.py app.Loop; UIUpdate = one CPythonApplication::Process", "image render commands carry base texture name + quad + UV (D3D -0.5 offset compensated)", "PythonBoot Stop clears the launcher before window manager teardown like 40250 Main", "MT_TEST_MODE=python_ui visible mode"], "tests": ["port.app_loop", "python_host_test.gd"], "todo": ["fnt/CGraphicText font pipeline and text alignment", "ExpandedImage blend modes"]}
{"time": "2026-09-23T05:15:20Z", "event": "port_round", "unit": "PORT-PLAN 2V0-g: .fnt font pipeline (CGraphicText/CGraphicFontTexture/CGraphicDib/CGraphicTextInstance)", "ported": ["EterLib/GrpText.cpp, GrpFontTexture.cpp, GrpDIB.cpp (40250 verbatim)", "EterLib/GrpTextInstance.cpp (verbatim except D3D draw -> UI render commands)", "EterLib/TextTag, EterLocale/StringCodec, Arabic, StringCodec_Vietnamese (port_copy)", "EterLib/Util.cpp code page / font face table, SetDefaultCodePage", "UserInterface/GameType.cpp DefaultFont_* block", "CGraphicImageTexture Create/Lock/Unlock memory texture path", "GetMaxTextureWidth/Height"], "adapted": ["GDI subset (CreateFontIndirect, CreateDIBSection, TextOutW, GetTextExtentPoint32W, GetCharABCWidthsFloatW) emulated over vendored FreeType 2.13.3 with GDI cell-height/win-metric/gasp rules", "MultiByteToWideChar/WideCharToMultiByte: hand UTF-8/1252, iconv for other code pages", "glyph pages reach Godot as mem:<id>@<revision> memory textures; Canvas caches by id", "PythonBoot::Start calls SetDefaultCodePage(LocaleService_GetCodePage()) like 40250 Main", "CPythonResource registers fnt -> CGraphicText"], "divergent": ["Android /system/fonts has no Tahoma/Gulim: substitute faces change metrics until fonts are bundled", "no per-pixel comparison against Windows GDI output yet"], "needs_live": [], "tests": ["port.text: pass (Tahoma 12 height 12, width, PixelPositionToCharacterPosition, centre align, CP949 round trip)", "port.app_loop: pass (popup glyph quads, inked glyph page)", "ctest 31/31 pass", "godot --headless --path project --script python_host_test.gd: pass", "login screen screenshot: server list, popup and button captions rendered"], "todo": ["ExpandedImage blend modes", "Android font bundling", "2V1 login/select"]}