From 8edc124b89c759dc13b410ef1d8ad0c095e710b2 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 27 Aug 2026 12:34:23 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=A0=87=E9=A2=98=E6=8D=A2=E8=A1=8C?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E4=BD=BF=E7=94=A8=E5=8E=9F=E5=A7=8Bfont=5Fsi?= =?UTF-8?q?ze=EF=BC=8C=E4=B8=8ECSS=E9=A2=84=E8=A7=88=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 _wrap_title_text 中对 _compensate_ass_fontsize 的调用 - 换行计算直接使用 font_size,1.35x补偿仅用于ASS Fontsize渲染 - 修复 font_size=113 时每行字数从6个变为8个,与CSS预览一致 - 新增3个测试验证换行逻辑正确性 Fixes #任务C --- packages/domain/ass_subtitle_builder.py | 6 +-- .../unit/domain/test_ass_subtitle_builder.py | 42 +++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/packages/domain/ass_subtitle_builder.py b/packages/domain/ass_subtitle_builder.py index ed4d2733f..4e79a52d4 100755 --- a/packages/domain/ass_subtitle_builder.py +++ b/packages/domain/ass_subtitle_builder.py @@ -224,8 +224,8 @@ def _wrap_title_text( if available_width <= 0: return text - # 换行宽度必须与实际渲染(补偿后的 ASS Fontsize)一致,否则换行位置会错位 - ass_font_size = _compensate_ass_fontsize(font_size) + # 换行计算使用原始 font_size,与 CSS 预览一致;1.35x 补偿仅用于 ASS Fontsize 渲染 + # 先按已有 \N 分段,每段独立自动换行,最后用 \N 拼回 segments = text.split("\\N") @@ -238,7 +238,7 @@ def _wrap_title_text( for ch in seg: # CJK 字符按全角估算,其他按半角 - char_width = float(ass_font_size) if ord(ch) > 0x2E80 else ass_font_size * 0.55 + char_width = float(font_size) if ord(ch) > 0x2E80 else font_size * 0.55 if current_width + char_width > available_width and current_line: lines.append(current_line) diff --git a/tests/unit/domain/test_ass_subtitle_builder.py b/tests/unit/domain/test_ass_subtitle_builder.py index a9a9c8e68..15cb76256 100644 --- a/tests/unit/domain/test_ass_subtitle_builder.py +++ b/tests/unit/domain/test_ass_subtitle_builder.py @@ -15,6 +15,7 @@ from packages.domain.ass_subtitle_builder import ( TITLE_MARGIN_BOTTOM, TITLE_MARGIN_SIDE, TITLE_MARGIN_TOP, + _wrap_title_text, build_ass_content, build_ass_style, escape_ass_text, @@ -579,3 +580,44 @@ class TestConstants: assert isinstance(TITLE_MARGIN_TOP, int) assert isinstance(TITLE_MARGIN_BOTTOM, int) assert isinstance(TITLE_MARGIN_SIDE, int) + +# ============================================================ +# _wrap_title_text 换行逻辑验证 +# ============================================================ + + +class TestWrapTitleTextFontSizeConsistency: + """验证换行计算使用原始 font_size,与 CSS 预览一致。""" + + def test_font_size_113_uses_original_not_compensated(self): + """font_size=113 时,每行应容纳8个字(113px字宽),而非6个字(153px字宽)。""" + # 标题"永康拾掇脚阔头"共7个字 + # 可用宽度 = 1080 - 60 - 60 = 960px + # 用 font_size=113:char_width=113,960/113 ≈ 8.5,每行8个字 + # 7个字 < 8个字,应该在一行内 + title = "永康拾掇脚阔头" + result = _wrap_title_text(title, video_width=1080, font_size=113, margin_l=60, margin_r=60) + # 不应该有换行 + assert "\\N" not in result + assert result == title + + def test_long_title_wraps_correctly(self): + """长标题应该按 font_size 字宽正确换行。""" + # 16个中文字,每行8个字,应该换行为2行 + title = "永康拾掇脚阔头来一个笑一个哈哈哈" + result = _wrap_title_text(title, video_width=1080, font_size=113, margin_l=60, margin_r=60) + # 应该有一个换行 + assert result.count("\\N") == 1 + # 每行8个字 + lines = result.split("\\N") + assert len(lines) == 2 + assert len(lines[0]) == 8 + assert len(lines[1]) == 8 + + def test_mixed_cjk_and_ascii(self): + """混合中英文时,英文按半角宽度计算。""" + # "测试test" = 2个中文(2*113=226) + 4个英文(4*113*0.55=248.6) = 474.6px + title = "测试test" + result = _wrap_title_text(title, video_width=1080, font_size=113, margin_l=60, margin_r=60) + # 总宽度474.6px < 960px,应该在一行内 + assert "\\N" not in result -- 2.54.0