116 lines
6.6 KiB
GDScript
116 lines
6.6 KiB
GDScript
# text_metrics —— §8.8 seam ⑦ / ⑩ 收口:头顶子标签 / 掉落名条排版的文本尺寸
|
||
# 从「字符数 * 约 7px」/「单行 15px」估算换成 CGraphicTextInstance::GetTextSize 的
|
||
# 真实字体度量 1:1(增量 123 换宽 w、增量 124 换高 h、增量 125 加 owner 子串独立度量)。
|
||
# ArrangeTextTail(PythonTextTail.cpp:211-320 角色块、:160-190 item 块)里
|
||
# iNameWidth / iTitleWidth / iLevelWidth / guildW,以及 item 尾标框的 xSize / ySize
|
||
# (框 yEnd = ySize,:749 / :809),参考端全部来自 `pTextInstance->GetTextSize(&w, &h)`。
|
||
# Godot 的 Font.get_string_size() 是 1:1 对应物——本模块把它包成纯静态查询,并在无字体
|
||
# (headless / 未配主题)时回退到旧的字符数估宽 / 单行估高,保持 name_tail_layout /
|
||
# text_tail_arrange 的接口不变。
|
||
# (与 name_color.gd / text_tail.gd / chat_tail.gd / name_show.gd / damage_effect.gd /
|
||
# target_board.gd / pick_show.gd / name_tail_layout.gd / text_tail_arrange.gd 同一套
|
||
# 纯静态镜像套路,本模块是第 30 个 canonical。)
|
||
#
|
||
# REF(40250 ClientVS22 source/ 为唯一基线):
|
||
# UserInterface/PythonTextTail.cpp:225 pGuildNameInstance->GetTextSize(&iWidth, &iHeight)
|
||
# UserInterface/PythonTextTail.cpp:233 pTextTail->pTextInstance->GetTextSize(&iNameWidth, &iNameHeight)
|
||
# UserInterface/PythonTextTail.cpp:240 pTitle->GetTextSize(&iTitleWidth, &iTitleHeight)
|
||
# UserInterface/PythonTextTail.cpp:267 pLevel->GetTextSize(&iLevelWidth, &iLevelHeight)(有称号分支)
|
||
# UserInterface/PythonTextTail.cpp:297 pLevel->GetTextSize(&iLevelWidth, &iLevelHeight)(只有等级分支)
|
||
# UserInterface/PythonTextTail.cpp:733 pOwnerTextInstance->GetTextSize(&xOwnerSize, &yOwnerSize)
|
||
# UserInterface/PythonTextTail.cpp:748 pTextInstance->GetTextSize(&xSize, &ySize)(SetTextTailOwnerText)
|
||
# UserInterface/PythonTextTail.cpp:809 pTextInstance->GetTextSize(&xSize, &ySize)(SetTextTailText,item 框尺寸)
|
||
# —— GetTextSize 由 CGraphicTextInstance 转发到字体的实际字形排版度量(含字距、非等宽),
|
||
# 不是「字符数 * 定宽」。poc 之前的 SUBTAG_CHAR_W_PX / TAG_CHAR_W_PX(7.0) 是它 w 的近似、
|
||
# TAG_LINE_H_PX(15.0) 是它 h 的近似。
|
||
#
|
||
# seam ⑦ / ⑩:本模块只负责「量文本宽 / 高」。有字体时 = get_string_size 的精确像素(1:1);
|
||
# 无字体时回退字符数估宽 / 单行估高(headless 测试、或工程未配 Label3D.font 且无
|
||
# ThemeDB.fallback_font 的极端情况)。折算成世界坐标仍由调用方按各 Label3D 的 pixel_size
|
||
# 处理(见 name_tail_layout.subtag_world_x / text_tail_arrange)。子标签竖排 vs 参考同一
|
||
# 屏幕行、无公会徽记 mark 实体这两条 seam ⑦ 遗留不在本模块范围。
|
||
extends RefCounted
|
||
|
||
# 无字体 / font_size 非法时的每字符估宽(=增量 121 之前 net_world.SUBTAG_CHAR_W_PX、
|
||
# ground_items.TAG_CHAR_W_PX 用的 7.0)。仅作兜底,有字体时不参与。
|
||
const FALLBACK_CHAR_W_PX := 7.0
|
||
|
||
# 无字体 / font_size 非法时的单行估高(=增量 124 之前 ground_items.TAG_LINE_H_PX 用的
|
||
# 15.0)。仅作兜底,有字体时走 get_string_size(...).y。
|
||
const FALLBACK_LINE_H_PX := 15.0
|
||
|
||
# GetTextSize(&w, &h) 1:1:text 在 font @ font_size 下的像素尺寸。
|
||
# 空串 / font 为 null / font_size <= 0 -> Vector2.ZERO(对齐参考端未建 text instance
|
||
# 时该子标签不参与 ArrangeTextTail 的宽度计算)。
|
||
static func text_size(font: Font, text: String, font_size: int) -> Vector2:
|
||
if text == "" or font == null or font_size <= 0:
|
||
return Vector2.ZERO
|
||
return font.get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size)
|
||
|
||
# ArrangeTextTail 里各 iXxxWidth 取的就是 GetTextSize 的 w。
|
||
# 有字体且量得正宽 -> 精确像素;否则(无字体 / 非法 size)-> 字符数 * fallback_char_px。
|
||
# 空串恒 0(参考端无 text instance -> 该项不占宽)。
|
||
static func width_of(font: Font, text: String, font_size: int,
|
||
fallback_char_px := FALLBACK_CHAR_W_PX) -> float:
|
||
if text == "":
|
||
return 0.0
|
||
var w := text_size(font, text, font_size).x
|
||
if w > 0.0:
|
||
return w
|
||
return float(text.length()) * fallback_char_px
|
||
|
||
# Label3D 便捷入口:从节点自身取字体(Label3D.font 未设时回落 ThemeDB.fallback_font)
|
||
# 和 font_size,量出该 Label3D 当前文本的像素宽。label 为 null -> 0。
|
||
static func label_width(label: Label3D, fallback_char_px := FALLBACK_CHAR_W_PX) -> float:
|
||
if label == null:
|
||
return 0.0
|
||
var f: Font = label.font
|
||
if f == null:
|
||
f = ThemeDB.fallback_font
|
||
return width_of(f, label.text, label.font_size, fallback_char_px)
|
||
|
||
# GetTextSize 的 h:item 尾标框 yEnd = ySize(PythonTextTail.cpp:749 / :809)。单行文本的
|
||
# ySize ≈ 字体行高(ascent + descent),与具体字形无关。空串恒 0(参考端无 text
|
||
# instance -> 不占高);有字体量得正高 -> 精确像素;否则(无字体 / 非法 size)-> fallback。
|
||
static func height_of(font: Font, text: String, font_size: int,
|
||
fallback_line_px := FALLBACK_LINE_H_PX) -> float:
|
||
if text == "":
|
||
return 0.0
|
||
var h := text_size(font, text, font_size).y
|
||
if h > 0.0:
|
||
return h
|
||
return fallback_line_px
|
||
|
||
# Label3D 便捷入口:同 label_width,量该 Label3D 当前文本的像素高。label 为 null -> 0。
|
||
static func label_height(label: Label3D, fallback_line_px := FALLBACK_LINE_H_PX) -> float:
|
||
if label == null:
|
||
return 0.0
|
||
var f: Font = label.font
|
||
if f == null:
|
||
f = ThemeDB.fallback_font
|
||
return height_of(f, label.text, label.font_size, fallback_line_px)
|
||
|
||
# 增量 125(seam ⑩ 末尾 SetItemTextTailOwner):owner 后缀在参考端是与名字分开的
|
||
# pOwnerTextInstance,单独 GetTextSize。poc 只有一个合并 Label3D,故提供「用某 Label3D 的
|
||
# 字体 / 字号量任意子串」入口,让 ground_items 把名字子串、owner 子串分别度量。
|
||
# label 为 null -> 回退(宽 = 字符数 * fallback_char_px;高 = 空串 0 / 非空 fallback_line_px)。
|
||
static func string_width_like(label: Label3D, text: String,
|
||
fallback_char_px := FALLBACK_CHAR_W_PX) -> float:
|
||
if label == null:
|
||
return float(text.length()) * fallback_char_px
|
||
var f: Font = label.font
|
||
if f == null:
|
||
f = ThemeDB.fallback_font
|
||
return width_of(f, text, label.font_size, fallback_char_px)
|
||
|
||
static func string_height_like(label: Label3D, text: String,
|
||
fallback_line_px := FALLBACK_LINE_H_PX) -> float:
|
||
if text == "":
|
||
return 0.0
|
||
if label == null:
|
||
return fallback_line_px
|
||
var f: Font = label.font
|
||
if f == null:
|
||
f = ThemeDB.fallback_font
|
||
return height_of(f, text, label.font_size, fallback_line_px)
|