Skip to content

Poy-Coder/cjk-pptx-engine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Python 3.9+ MIT License Alpha

CJK PPTX Engine · 中文 PPT 量字引擎

让 AI 生成的中文 PPT 不再「字顶穿框」。
根治 python-pptx 中文文字溢出,专为 AI 生成 PPT 设计。 真字体测量 + 精确折行 + 自动缩字 + 交付审计。
已校准:微软雅黑 / 宋体 / 黑体 / 楷体 / 仿宋 / 等线。


问题

python-pptx 做中文 PPT 时,文字溢出是最常见的缺陷。根因是 python-pptx 不做文字度量——它把文字放进固定大小的框里,然后默认能放下。一旦中文字多了、换行多了、字体不同了,字就顶穿框、甚至顶穿页面

现有方案靠「中文字 ≈ 1em」估算,误差可达 14%(因为不同字体的行高/字宽差异很大),正好落在「看着差不多、实际放不下」的坑里。

场景 旧方案(估算) 本引擎(真字体测量)
微软雅黑 14pt 3 行 0.583in ❌ 溢出 0.781in ✅ 刚好
宋体 14pt 3 行 0.583in ❌ 溢出 0.677in ✅ 刚好
正文框固定高度,字多时 手动试错 / 大概缩 fit_size 自动缩到放得下

校准方法:生成测试 PPTX,每页在引擎预测的文本底部画红色标线,PowerPoint 目视验证。参见 workspace/calibration_v3.pptx

解法

真字体测量 → 精确折行 → 精确高度 → 自动缩字/分页 → 交付前审计。

                        ┌─  resolve_font:别名 → 真实字体文件
  原文本 ─→ 逐字量宽 ──┼─  折行(尊重 \n) ─→ 精确行数
                        └─  读 font metrics + lineGap → 精确行高
                                    │
                                    ▼
                           fit_size / clip_to_box / 分页
                                    │
                                    ▼
                           audit_pptx:交付闸门(BOUNDS + OVERFLOW + 字体替换)
                                    │
                                    ▼
                           美学 lint:对齐 / 假斜体 / 对比度 / 字号节奏 / 重叠

定位

这个工具是给没有视觉的大模型用的。

AI 做 PPT 时最大的短板就是"看不见"。它不知道文字放进去会不会溢出、两个框是不是重叠了——因为它看不到渲染后的画面

传统方案需要截图 + 视觉模型 review,成本高、速度慢、数据还可能出境。

这个引擎不一样:它用字体文件算,不用眼睛看。 所有测量都是纯数学(逐字量宽、读字体度量表、几何重叠检测),零视觉、零 token、不挑模型。

AI 做 PPT 的痛点 本引擎的解法
"看不见"字溢出 用真字体文件量 → 精确到 0.001 英寸
"看不见"框重叠 算几何交集 + z-order → 纯逻辑判定
"不知道"字体会不会对不齐 读字体文件的 lineGap 表 → PowerPoint 级精度
每次生成都要视觉模型 review 一次性数学测量 → 不花 token、不出境

精度

PowerPoint 实际渲染校准验证(14pt 中文本, 3 行):

字体 引擎测量(含lineGap) vs PowerPoint
微软雅黑 1.34× 字号 ✅ 匹配
宋体 / 黑体 / 楷体 / 仿宋 1.16× 字号(lineGap 修正) ✅ 匹配
等线 1.05× 字号 ⚠️ +5%(safety_factor 可选)

校准方法:生成测试 PPTX,每页在预测底部画红色标线,PowerPoint 目视验证。见 workspace/calibration_v3.pptx

安装

pip install cjk-pptx-engine

或从源码安装:

git clone https://github.com/Poy-Coder/cjk-pptx-engine.git
cd cjk-pptx-engine
pip install -e .

快速上手

🤖 给 AI 用的快捷指令

想让你的 AI(Claude / ChatGPT 等)做中文 PPT 时不溢出?直接把 PROMPT.md 发给它就行。

➡️ 打开 PROMPT.md

一行命令安装

pip install git+https://github.com/Poy-Coder/cjk-pptx-engine.git

最简单的用法(不会溢出)

from pptx import Presentation
from cjk_measure import safe_textbox

prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6])

# 自动量字、自动缩到刚好放下、自动钉字体
safe_textbox(slide, left=1, top=1, width=8, height=1.2,
             text="违法行为事实清楚,证据确凿充分,应予处罚。",
             font_name="仿宋", font_size=14)

safe_textboxadd_textbox 用法一样,但它会在后台:

  1. 用真字体量文字占多高 → 放不下就自动缩字号
  2. 钉死 ea 字体槽 → 换机打开不对不齐
  3. 关掉 PowerPoint 自动缩字 → 不会跑偏
from cjk_measure import measure_h, wrap_lines

text = "根据《中华人民共和国行政处罚法》第五十四条的规定,行政机关应当依法作出行政处罚决定。"

# 量一下这段文字在 8 英寸宽的框里占多高
h = measure_h(text, pt=14, box_w_in=8.0, font_name="微软雅黑")
print(f"需要 {h:.3f} 英寸高")  # → 0.781 in (3行)

# 看具体怎么折行的
lines = wrap_lines(text, pt=14, box_w_in=8.0, font_name="微软雅黑")
for i, l in enumerate(lines, 1):
    print(f"  行{i}: {l}")

生成 PPTX 时使用(完整示例)

from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import MSO_AUTO_SIZE
from cjk_measure import measure_h, fit_size

prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6])

text = "违法行为事实清楚,证据确凿充分,且依据有关法律法规应当给予行政处罚的。"
box_w, box_h = 8.0, 1.2  # 英寸

# 先量——用渲染时的真实字体
predicted = measure_h(text, pt=14, box_w_in=box_w, font_name="仿宋")
print(f"文字需要 {predicted:.3f}in,框高 {box_h:.1f}in")

# 如果放不下,自动缩到最大可容字号
if predicted > box_h:
    safe_pt = fit_size(text, box_w, box_h, want_pt=14, font_name="仿宋")
    print(f"缩到 {safe_pt:.0f}pt")
else:
    safe_pt = 14

# 创建文本框(尺寸精确,关掉自动缩字)
txBox = slide.shapes.add_textbox(
    Inches(1), Inches(1), Inches(box_w), Inches(box_h)
)
tf = txBox.text_frame
tf.word_wrap = True
tf.auto_size = MSO_AUTO_SIZE.NONE
tf.margin_left = Inches(0)
tf.margin_right = Inches(0)
tf.margin_top = Inches(0)
tf.margin_bottom = Inches(0)

p = tf.paragraphs[0]
p.line_spacing = 1.0
run = p.add_run()
run.text = text
run.font.size = Pt(safe_pt)
run.font.name = "仿宋"

# 交付前审计
import subprocess
subprocess.run(["cjk-audit", "my_deck.pptx"])

一键审计已生成的 PPTX

# 溢出 + 越界 + 字体替换 + 重叠检测 + 美学检查
cjk-audit my_deck.pptx

# 输出示例:
#   slide 13.333x7.500 in
#   — BLOCKING: bounds/overflow = 0
#   — AESTHETIC: P1=0 others=3 (纯逻辑建议)
#   RESULT: PASS — 0 越界 · 0 溢出。
# 严格模式(美学 P1 也阻断交付)
cjk-audit my_deck.pptx --strict

美学检查(单独运行)

# 纯逻辑检查:对齐、重叠、对比度、假斜体、字号节奏…
python -m cjk_measure.aesthetic_lint my_deck.pptx

字体诊断

# 查看本机已安装/待替换的字体
cjk-measure registry

# 量一段具体文字
cjk-measure measure "违法行为事实清楚" --font 宋体 --size 14 --width 8

集成指南

方式 A:紧集成(推荐 — 生成时防御)

txt() 助手函数替换 python-pptx 原生的 add_textbox(),所有文字框自动走量字逻辑:

from pptx.util import Inches, Pt
from pptx.enum.text import MSO_AUTO_SIZE
from cjk_measure import measure_h, fit_size, clip_to_box

def add_textbox(slide, left, top, width, height, text, font_name, font_size,
                line_spacing=1.0, fit=False, clip=False):
    """
    安全的文本框:自动缩字/裁剪,钉死东亚字体,不溢出。
    
    参数:
        fit: True → 文字放不下时自动缩小字号
        clip: True → 超过 N 行时裁剪加 "…"
    """
    if fit:
        font_size = fit_size(text, width, height, font_size,
                             font_name=font_name, line_spacing=line_spacing)
    
    tb = slide.shapes.add_textbox(Inches(left), Inches(top), Inches(width), Inches(height))
    tf = tb.text_frame
    tf.word_wrap = True
    tf.auto_size = MSO_AUTO_SIZE.NONE
    tf.margin_left = Inches(0)
    tf.margin_right = Inches(0)
    tf.margin_top = Inches(0)
    tf.margin_bottom = Inches(0)
    
    p = tf.paragraphs[0]
    p.alignment = PP_ALIGN.LEFT
    p.line_spacing = line_spacing
    run = p.add_run()
    run.text = text
    run.font.size = Pt(font_size)
    run.font.name = font_name
    run.font.color.rgb = RGBColor(0x33, 0x33, 0x33)
    
    # 钉死东亚字体槽(CJK 走 ea,换机打开也不会走样)
    from pptx.oxml.ns import qn
    rPr = run._r.get_or_add_rPr()
    ea = rPr.makeelement(qn('a:ea'), {'typeface': font_name})
    rPr.append(ea)
    
    return tb


# 使用示例
slide = prs.slides.add_slide(prs.slide_layouts[6])
add_textbox(slide, 1, 1, 8, 1.5, 
            "违法行为事实清楚,证据确凿……",
            font_name="仿宋", font_size=14, fit=True)

方式 B:松集成(审计模式 — 适合任何工具生成的 PPTX)

不管 PPTX 是谁生成的(GordenPPT、ppt-master、Copilot、ChatGPT…),交付前跑一遍审计:

# 检查溢出 + 越界 + 字体替换 + 重叠 + 美学
cjk-audit generated_deck.pptx

# 集成到 CI / 自动化流程
python -c "
from cjk_measure import audit_pptx
blocking, subs, sw, sh = audit_pptx.audit('generated_deck.pptx')
if blocking:
    print(f'❌ {len(blocking)} 个阻塞问题,拒绝交付')
    exit(1)
print('✅ 通过')
"

方式 C:AI 生成流程的标准接入

AI 在写 python-pptx 代码时,按这个模板做就能避免溢出:

1. 规划内容 → 用 measure_h 算每段文字的真实占高
2. 够放 → 直接放;不够 → fit_size 缩字号 或 分页
3. 创建文本框 → 钉死 ea 字体槽
4. 交付前 → cjk-audit 审计闸门

对应到提示词工程,就是让 LLM 在生成代码时默认套用 add_textbox() 助手函数(见方式 A),而不是直接调 python-pptx 的 add_textbox()

与现有 PPT 工具的集成参考

工具 接入点 方式 说明
ppt-master svg_to_pptx/drawingml_utils.pyestimate_text_width() 紧集成 替换宽度估算函数为 wrap_lines(),并在 convert_text() 中用 measure_h() 算行高
GordenPPT 模板渲染器的文本框创建步骤 紧集成 add_textbox() 助手替换原生 add_textbox()
任意 python-pptx 脚本 审计 松集成 生成后跑 cjk-audit deck.pptx

接入遇到问题?提 Issue 或 PR。

在自己机器上验证精度

不同操作系统、Office 版本、字体文件版本可能导致渲染差异。仓库提供了自校准脚本:

# 在本机跑一遍,验证引擎精度
python scripts/self_calibrate.py

这会生成一个 self_calibrate.pptx,每页包含:

  • 🔴 红线 = 引擎预测的文本底部
  • 🔵 蓝线 = ×1.10 安全系数

打开 PPTX 看文字底部与哪条线对齐,把结果截图贴到 Issue 里,帮更多人校准 🦊

核心函数

函数 用途
wrap_lines(text, pt, box_w, ...)list[str] 逐字量宽,精确折行
measure_h(text, pt, box_w, ...)float 精确渲染高度(英寸)
fit_size(text, w, h, want_pt, ...)float 最大可容字号
clip_to_box(text, pt, w, max_lines, ...)str 裁 N 行加"…"
resolve_font(name, bold)FontResolution 字体别名→真实文件路径
registry_report()dict 字体安装状态报告

字体覆盖

支持 6 个度量类、30+ 款主流中文字体,覆盖:

Windows 标配:微软雅黑、宋体、黑体、楷体、仿宋、等线
Office 标配:等线(DengXian)
政务公文:方正小标宋、方正仿宋_GBK、方正楷体_GBK、方正黑体_GBK
思源系列:思源黑体/宋体、Noto Sans CJK/SC
macOS 标配:苹方(PingFang SC)
现代 UI:阿里巴巴普惠体、HarmonyOS Sans、MiSans、OPPO Sans
标题/装饰:得意黑、优设标题黑

未安装的字体自动按字宽度量类寻找替身(偏宽 = 保守 = 不漏判溢出)。详见 measure_engine.py_ALIAS_CLASS 表。

美学检查

无需视觉模型,纯逻辑判定(aesthetic_lint.py):

检查项 说明 级别
TEXT_OVERLAP 两个文本框重叠 P1
TEXT_COVERED 填充形状覆盖文字 P1
ITALIC_CJK 中文设斜体(假斜) P1
LOW_CONTRAST 文字/背景对比度不足 P1/P2
ALIGN_NEAR_MISS 近似对齐(差一笔) P2
SIZE_SOUP 字号级数过多 P2
TITLE_INCONSISTENT 标题跨页不统一 P2
PALETTE_SPRAWL 用色过多 P3
EDGE_HUG 文字贴安全边 P3

项目背景

本项目最初是 Poy-Coder 内部工作流的一部分,用于解决 AI 批量生成中文 PPT 时「文字溢出」这一系统性缺陷。经过 PowerPoint 实际校准验证后整理成独立工具开源。

License

MIT © 2026 Poy-Coder


项目早期,欢迎参与。 校准测试、字体覆盖、新功能……看 CONTRIBUTING.md 找你能帮上忙的方向 🦊

About

中文PPT量字引擎 - 根治python-pptx文字溢出/重叠, AI生成中文PPT的排版防翻车工具。CJK text measurement for AI-generated slides.

Topics

Resources

License

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages