Complete remaining client gap features

This commit is contained in:
shenlei
2026-09-04 13:25:05 +09:00
parent 13ccb8d02d
commit 9a4a044da5
47 changed files with 6667 additions and 140 deletions
+141
View File
@@ -0,0 +1,141 @@
# text_metrics_test —— §8.8 seam ⑦ / ⑩:文本尺寸换真实字体度量(GetTextSize 1:1)。
# text_size(空 / null / 非法 size -> ZERO;真实度量为正、随串长 / 字号单调)、
# width_of(空串 0 / 无字体回退字符数*px / 有字体 == text_size.x / font_size<=0 回退)、
# label_widthLabel3D.font 未设回落 ThemeDB.fallback_font / null -> 0)、
# height_of / label_height(增量 124:空串 0 / 无字体回退 15px / 有字体 == text_size.y /
# 与串内容无关随字号单调 / font_size<=0 回退)、
# string_width_like / string_height_like(增量 125:量 label 字体下的任意子串 —— owner
# 子串独立度量;label null -> 回退字符数*px / 单行估高;空串 -> 0)。
# godot --headless --path project --script text_metrics_test.gd
# 退出码 0 = 全过。
extends SceneTree
const TextMetrics = preload("res://text_metrics.gd")
var _fail := 0
func _ck(c: bool, m: String) -> void:
if not c:
_fail += 1
printerr("FAIL: " + m)
func _feq(a: float, b: float, m: String) -> void:
_ck(absf(a - b) < 0.0001, "%s (got %f want %f)" % [m, a, b])
func _init() -> void:
_run()
if _fail == 0:
print("PASS: text_metrics_test (§8.8 seam ⑦/⑩ 文本宽 w 123 / 高 h 124 / owner 子串独立度量 125 换真实字体度量 GetTextSize 1:1)")
quit(0)
else:
printerr("%d check(s) failed" % _fail)
quit(1)
func _run() -> void:
# --- 0. 常量 -----------------------------------------------------------
_feq(TextMetrics.FALLBACK_CHAR_W_PX, 7.0, "FALLBACK_CHAR_W_PX = 旧 SUBTAG/TAG_CHAR_W_PX 7.0")
var font: Font = ThemeDB.fallback_font
# --- 1. text_size 退化输入 -> Vector2.ZERO --------------------------
_ck(TextMetrics.text_size(font, "", 16) == Vector2.ZERO, "空串 -> ZERO")
_ck(TextMetrics.text_size(null, "abc", 16) == Vector2.ZERO, "font 为 null -> ZERO")
_ck(TextMetrics.text_size(font, "abc", 0) == Vector2.ZERO, "font_size 0 -> ZERO")
_ck(TextMetrics.text_size(font, "abc", -4) == Vector2.ZERO, "font_size 负 -> ZERO")
# --- 2. text_size 真实度量(有 fallback_font 时)------------------
if font != null:
var w5 := TextMetrics.text_size(font, "MMMMM", 24).x
var w10 := TextMetrics.text_size(font, "MMMMMMMMMM", 24).x
_ck(w5 > 0.0, "非空串 @ 有效字号 -> 宽为正")
_ck(w10 > w5, "更长的串更宽(GetTextSize 逐字形累加)")
var wSmall := TextMetrics.text_size(font, "Test", 12).x
var wBig := TextMetrics.text_size(font, "Test", 48).x
_ck(wBig > wSmall, "同串更大字号更宽")
# width_of 有字体时应完全等于 text_size(...).x
_feq(TextMetrics.width_of(font, "Hello", 20),
TextMetrics.text_size(font, "Hello", 20).x, "width_of 有字体 == text_size.x")
else:
printerr("note: ThemeDB.fallback_font 为 null,跳过真实度量断言(仅测回退路径)")
# --- 3. width_of 回退与边界 --------------------------------------------
_feq(TextMetrics.width_of(font, "", 16), 0.0, "空串宽恒 0")
_feq(TextMetrics.width_of(null, "abcd", 16, 7.0), 28.0, "无字体 -> 字符数 * 7 = 28")
_feq(TextMetrics.width_of(null, "abcd", 16), 4.0 * TextMetrics.FALLBACK_CHAR_W_PX,
"无字体默认回退用 FALLBACK_CHAR_W_PX")
_feq(TextMetrics.width_of(font, "ab", 0, 5.0), 10.0, "有字体但 font_size 0 -> 回退 2*5")
_feq(TextMetrics.width_of(null, "x", 16, 3.0), 3.0, "单字符回退 = char_px")
# --- 4. label_widthLabel3D---------------------------------------
_ck(TextMetrics.label_width(null) == 0.0, "label 为 null -> 0")
var lbl := Label3D.new()
lbl.text = "WWWW"
lbl.font_size = 24
get_root().add_child(lbl)
var lw := TextMetrics.label_width(lbl, 7.0)
if font != null:
_ck(lw > 0.0, "Label3D.font 未设 -> 回落 ThemeDB.fallback_font 量得正宽")
_feq(lw, TextMetrics.text_size(ThemeDB.fallback_font, "WWWW", 24).x,
"label_width 用节点自身 text / font_size")
else:
_feq(lw, 4.0 * 7.0, "无 fallback_font -> label_width 回退字符数*px")
var lbl_empty := Label3D.new()
lbl_empty.text = ""
lbl_empty.font_size = 24
get_root().add_child(lbl_empty)
_feq(TextMetrics.label_width(lbl_empty), 0.0, "空 Label3D 宽 0")
# --- 5. height_of / label_height(增量 124GetTextSize 的 h--------
_feq(TextMetrics.FALLBACK_LINE_H_PX, 15.0, "FALLBACK_LINE_H_PX = 旧 TAG_LINE_H_PX 15.0")
_feq(TextMetrics.height_of(font, "", 16), 0.0, "空串高恒 0")
_feq(TextMetrics.height_of(null, "abcd", 16, 15.0), 15.0, "无字体 -> 回退 15")
_feq(TextMetrics.height_of(null, "abcd", 16), TextMetrics.FALLBACK_LINE_H_PX,
"无字体默认回退用 FALLBACK_LINE_H_PX")
_feq(TextMetrics.height_of(font, "ab", 0, 9.0), 9.0, "有字体但 font_size 0 -> 回退 9")
if font != null:
var h_short := TextMetrics.height_of(font, "x", 20)
var h_long := TextMetrics.height_of(font, "WWWWWWWWWW", 20)
_ck(h_short > 0.0, "非空串 @ 有效字号 -> 高为正")
_feq(h_short, h_long, "单行高与串内容无关(≈ 字体行高)")
var h12 := TextMetrics.height_of(font, "Test", 12)
var h48 := TextMetrics.height_of(font, "Test", 48)
_ck(h48 > h12, "更大字号更高")
_feq(TextMetrics.height_of(font, "Hello", 20),
TextMetrics.text_size(font, "Hello", 20).y, "height_of 有字体 == text_size.y")
_ck(TextMetrics.label_height(null) == 0.0, "label 为 null -> 高 0")
if font != null:
_feq(TextMetrics.label_height(lbl, 15.0),
TextMetrics.text_size(ThemeDB.fallback_font, "WWWW", 24).y,
"label_height 用节点自身 text / font_size、回落 fallback_font")
else:
_feq(TextMetrics.label_height(lbl, 15.0), 15.0, "无 fallback_font -> label_height 回退 15")
_feq(TextMetrics.label_height(lbl_empty), 0.0, "空 Label3D 高 0")
# --- 6. string_width_like / string_height_like(增量 125owner 子串独立度量)------
_feq(TextMetrics.string_width_like(null, "abcd", 7.0), 28.0, "label null -> 字符数 * 7")
_feq(TextMetrics.string_width_like(null, "abcd"), 4.0 * TextMetrics.FALLBACK_CHAR_W_PX,
"label null 默认回退用 FALLBACK_CHAR_W_PX")
_feq(TextMetrics.string_width_like(null, "", 7.0), 0.0, "label null + 空串 -> 0")
_feq(TextMetrics.string_height_like(null, "", 15.0), 0.0, "空串高恒 0(不占行)")
_feq(TextMetrics.string_height_like(lbl, ""), 0.0, "有 label + 空串 -> 0")
_feq(TextMetrics.string_height_like(null, "abcd", 15.0), 15.0, "label null + 非空 -> 回退 15")
_feq(TextMetrics.string_height_like(null, "abcd"), TextMetrics.FALLBACK_LINE_H_PX,
"label null 默认回退用 FALLBACK_LINE_H_PX")
if font != null:
# 量的是「给定子串」而非 label.textlbl.text = "WWWW"
_feq(TextMetrics.string_width_like(lbl, "Hello"),
TextMetrics.text_size(ThemeDB.fallback_font, "Hello", 24).x,
"string_width_like 用 label 字号量给定子串(非 label.text)")
_feq(TextMetrics.string_height_like(lbl, "Hello"),
TextMetrics.text_size(ThemeDB.fallback_font, "Hello", 24).y,
"string_height_like == text_size(子串).y")
_ck(TextMetrics.string_width_like(lbl, "WWWWWWWW") > TextMetrics.string_width_like(lbl, "WW"),
"更长子串更宽")
else:
_feq(TextMetrics.string_width_like(lbl, "Hello", 7.0), 5.0 * 7.0,
"无 fallback_font -> string_width_like 回退字符数*px")
_feq(TextMetrics.string_height_like(lbl, "Hello", 15.0), 15.0,
"无 fallback_font -> string_height_like 回退单行估高")
lbl.queue_free()
lbl_empty.queue_free()