fix: 用量百分比数字补零并加字符间距,避免两位数贴连

F16(16/12x 非整数倍缩放)下数字字形墨迹宽度等于步进宽度、无侧边距,
两位数(如 12%/36%)几乎贴在一起;加统一补零格式 + 手动字符间距(track)修复。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 15:16:54 +08:00
parent b32007483a
commit 097b9d1d64

View File

@@ -40,14 +40,26 @@ class DashboardRenderer:
self.F48 = ImageFont.truetype(font_path, 48)
# ---------- 基础绘制工具 ----------
def _tw(self, s, ft):
def _tw(self, s, ft, track=0):
# track额外字符间距(px)。非整数倍缩放字号(如 F16=16/12x)下,数字字形墨迹宽度
# 等于步进宽度(无侧边距),相邻字符几乎零间隙,需手动加距才不会紧贴。
if track:
return sum(self.d.textlength(c, font=ft) for c in s) + track * (len(s) - 1)
return self.d.textlength(s, font=ft)
def _draw(self, x, y, s, ft, fill, bold):
def _draw(self, x, y, s, ft, fill, bold, track=0):
# 伪粗体:点阵字体单一字重,按 1~bold px 偏移叠绘加粗笔画
self.d.text((x, y), s, font=ft, fill=fill)
for dx in range(1, bold + 1):
self.d.text((x + dx, y), s, font=ft, fill=fill)
if not track:
self.d.text((x, y), s, font=ft, fill=fill)
for dx in range(1, bold + 1):
self.d.text((x + dx, y), s, font=ft, fill=fill)
return
cx = x
for ch in s:
self.d.text((cx, y), ch, font=ft, fill=fill)
for dx in range(1, bold + 1):
self.d.text((cx + dx, y), ch, font=ft, fill=fill)
cx += self.d.textlength(ch, font=ft) + track
def text(self, x, y, s, ft, fill=BLACK, bold=0):
self._draw(x, y, s, ft, fill, bold)
@@ -102,17 +114,18 @@ class DashboardRenderer:
if right:
self.rtext(self.W - 10, y, right, self.F12)
def _mid(self, x, cy, s, ft, fill=BLACK, bold=0, align="l"):
def _mid(self, x, cy, s, ft, fill=BLACK, bold=0, align="l", track=0):
"""按字符串「墨迹竖直中心」对齐到 cy 绘制——跨字号(F12/F24)也能真正居中,
避免不同字号按顶部对齐时的视觉错位。align: l 左对齐 / r 右对齐 / c 居中于 x。"""
避免不同字号按顶部对齐时的视觉错位。align: l 左对齐 / r 右对齐 / c 居中于 x。
track见 _tw用于给紧贴的字符手动加间距。"""
_, t, _, b = ft.getbbox(s) # 该串墨迹在字身框内的上/下沿
y = cy - (t + b) / 2.0
w = self._tw(s, ft)
w = self._tw(s, ft, track)
if align == "r":
x -= w + bold
elif align == "c":
x -= (w + bold) / 2.0
self._draw(x, y, s, ft, fill, bold)
self._draw(x, y, s, ft, fill, bold, track)
def _pace(self, xr, cy, diff):
"""时间维度对比pace = 用量% 时间%>0 超前↑红;<0 节余↓黑;=0 持平。
@@ -137,6 +150,7 @@ class DashboardRenderer:
pct = max(0, min(100, int(raw))) if ok else 0
color = RED if (ok and pct >= warn) else BLACK
LABEL_W, G1, G2, H = 26, 13, 8, 15 # G1 进度条↔百分比、G2 百分比↔pace视觉约 12/11
PCT_TRACK = 2 # F16(16/12x 非整数倍缩放)数字墨迹无侧边距、紧贴,手动加字符间距
cy = y + 10 # 行竖直中心
self._mid(x0, cy, bar["k"], self.F13, bold=1) # 左标签 F13
# 右侧从右往左pace(最右) → 百分比 → 进度条
@@ -144,10 +158,10 @@ class DashboardRenderer:
if ok and "time_pct" in bar:
pace_w = self._pace(x1, cy, pct - int(bar["time_pct"]))
pct_r = x1 - pace_w - G2
pct_txt = f"{pct}%" if ok else "--"
self._mid(pct_r, cy, pct_txt, self.F16, fill=color, bold=1, align="r") # 百分比 F16
pct_txt = f"{pct:02d}%" if ok else "--"
self._mid(pct_r, cy, pct_txt, self.F16, fill=color, bold=1, align="r", track=PCT_TRACK) # 百分比 F16
bx0 = x0 + LABEL_W
bx1 = pct_r - self._tw(pct_txt, self.F16) - G1
bx1 = pct_r - self._tw(pct_txt, self.F16, PCT_TRACK) - G1
by = cy - H // 2
self.d.rectangle([bx0, by, bx1, by + H], outline=color, width=1) # 轨道边框随条色
fw = (bx1 - bx0) * pct / 100.0