# 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_width(Label3D.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_width(Label3D)--------------------------------------- _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(增量 124:GetTextSize 的 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(增量 125:owner 子串独立度量)------ _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.text(lbl.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()