Skip to content

Enhance PPTX export with editable text, multi-slide decks, and in-memory output - #3643

Merged
shlzxjp merged 22 commits into
mainfrom
feature/onionsyu_export_ppt3
Aug 1, 2026
Merged

Enhance PPTX export with editable text, multi-slide decks, and in-memory output#3643
shlzxjp merged 22 commits into
mainfrom
feature/onionsyu_export_ppt3

Conversation

@OnionsYu

@OnionsYu OnionsYu commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

概述

本 PR 完善 PAGX 到 PPTX 的导出能力,重点支持原生可编辑文本、多文档多页导出和内存导出。对于携带预排版 GlyphRun 的文本,可选择牺牲字形级还原精度,改为输出可在 PowerPoint 中继续编辑和重新换行的原生文本。

同时修复 SVG、HTML 以及 PPTX 非烘焙路径中,遮罩图层被重复当作可见内容输出的问题。

主要改动

原生可编辑 PPTX 文本

  • 新增 PPTExportOptions::ignoreGlyphRuns 和 CLI 选项 --ppt-ignore-glyphruns:忽略 GlyphRun 几何,使用 Text::text 生成原生 PowerPoint 文本。
  • convertTextToPath / --text-to-path 与上述选项语义相反;两者同时启用时,text-to-path 优先。
  • 使用内嵌 GlyphRun 的 pen origin、advance span、bounds 和 baseline 保持文本框位置、宽高及多行垂直对齐,避免逐行文本重叠、居中重复应用和文本框尺寸漂移。
  • 对带有固定 inline extent 或 Justify 对齐的文本保留 PowerPoint 原生换行能力,使 Web/WASM 与桌面端字体环境不一致时仍可正确重新换行。
  • 将满足条件的 modifier-only TextBox runs 合并为单个原生富文本 shape,并按基线对齐位图 emoji,改善混排文本的可编辑性和视觉一致性。

多页和内存导出

  • PPTExporter::ToFile() 改为接收 std::vector<PAGXDocument*>,每个文档按传入顺序生成一页;整份 PPTX 使用第一个文档的画布尺寸。
  • 新增 PPTExporter::ToData(),可直接获得完整 PPTX 的内存数据,无需先写入磁盘。
  • pagx export 支持重复传入 --input 生成多页 PPTX;SVG 和 HTML 仍只接受单个输入。
  • 任一输入加载失败或包含未解析的 import 时终止整次导出,避免静默生成缺页文件。

遮罩导出修复

  • SVG、HTML 及 bakeUnsupported=false 的 PPTX 路径不再将图层自身的 mask child 作为可见内容重复输出。
  • mask 仍用于 clip/mask 定义,避免遮罩填充以不透明图层覆盖实际内容。

兼容性说明

  • PPTExporter::ToFile(PAGXDocument&, ...) 单文档重载已移除,调用方需要改为传入文档指针列表;单元素列表仍生成单页 PPTX。
  • ignoreGlyphRuns 会放弃 GlyphRun 中无法由原生 OOXML 文本表达的字形 ID、逐字偏移、锚点和旋转信息。默认行为保持不变,只有显式启用时才优先获得可编辑文本。

测试

新增和完善自动化测试,覆盖:

  • ToFile / ToData 的单页、多页、空输入、空指针、不同画布尺寸和跨页媒体命名;
  • CLI 多输入、默认输出名、失败输入、非 PPTX 多输入校验,以及文本选项优先级;
  • 可编辑文本的位置、尺寸、换行、Justify、多行对齐、富文本合并和 emoji 基线;
  • SVG、HTML 与 PPTX 非烘焙路径的 mask child 回归场景。

OnionsYu added 18 commits July 27, 2026 10:54
…t to match the authoritative glyph-path placement.
…suring the real advance-width span instead of a crude per-character estimate.
…th so the mask fill no longer paints an opaque patch over the masked content.
…xporters so the mask fill no longer paints an opaque patch over the masked content.
…en offset and optical alignment with siblings.
…ine extent even when PAGX line metadata is present so Web/WASM font differences can still rewrap lines.
@codecov-commenter

codecov-commenter commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.37356% with 134 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.16%. Comparing base (05aebeb) to head (43c8cdb).

Files with missing lines Patch % Lines
src/pagx/ppt/PPTExporter.cpp 69.58% 41 Missing and 18 partials ⚠️
src/pagx/ppt/PPTTextWriter.cpp 71.92% 28 Missing and 20 partials ⚠️
src/cli/CommandExport.cpp 82.97% 6 Missing and 2 partials ⚠️
test/src/PAGXPPTTest.cpp 98.72% 5 Missing and 3 partials ⚠️
src/pagx/utils/TextUtils.cpp 88.33% 3 Missing and 4 partials ⚠️
test/src/PAGXHtmlTest.cpp 75.00% 2 Missing ⚠️
src/pagx/TextLayout.cpp 0.00% 0 Missing and 1 partial ⚠️
src/pagx/ppt/PPTWriter.h 90.90% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3643      +/-   ##
==========================================
+ Coverage   83.04%   83.16%   +0.11%     
==========================================
  Files         712      712              
  Lines       94876    96165    +1289     
  Branches    26597    26762     +165     
==========================================
+ Hits        78793    79977    +1184     
- Misses      10410    10455      +45     
- Partials     5673     5733      +60     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

OnionsYu added 2 commits July 31, 2026 14:06
…at are auto-sized along the inline axis, so PowerPoint keeps a target line width instead of silently falling back to start alignment.
…s by using the embedded authoring glyph-run bounds for the envelope instead of the platform-dependent runtime layout width.

@shlzxjp shlzxjp left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码评审报告(PR #3643

专业评审团队从架构、可扩展性、可维护性、可读性、健壮性、安全性、性能、防御性编程、代码规范多维度审查,并逐条读源码复核以排除误报。

总体结论:质量高,可合入。 未发现 blocker / major 级实现缺陷;对外 API(ToFile 多文档化、新增 ToDataignoreGlyphRuns)设计合理、精简、无冗余,convertTextToPath 优先的文档承诺在 PPTWriter.h 构造函数中确有实现。以下为经验证的真实问题(已按行级标注),供确认与后续处理。

亮点:ToFile/ToData 共用 WriteZipEntries 保证字节一致(有 memcmp 测试);多页状态隔离正确(imageIndexBase 防媒体命名冲突、_embeddedBaselineOffsets 为实例成员);MemZipSeek 拒绝越界 seek;SVG/HTML/PPT mask 修复三路一致无回归;emoji 基线补偿语义正确。规范完全符合项目约定。

Comment thread src/pagx/utils/TextUtils.cpp Outdated
Comment thread src/pagx/utils/TextUtils.cpp
Comment thread src/pagx/ppt/PPTBoilerplate.cpp
Comment thread src/pagx/ppt/PPTExporter.cpp Outdated
Comment thread test/src/PAGXPPTTest.cpp
@OnionsYu OnionsYu changed the title Support exporting PAGX to editable native PowerPoint text and multi-slide PPTX Enhance PPTX export with editable text, multi-slide decks, and in-memory output Jul 31, 2026
…eports a layout error instead of silently emitting a blank slide, clamp zero or non-finite slide sizes to the minimum legal OOXML extent, and skip null glyph runs when computing text bounds.
@shlzxjp
shlzxjp merged commit b711563 into main Aug 1, 2026
9 checks passed
@shlzxjp
shlzxjp deleted the feature/onionsyu_export_ppt3 branch August 1, 2026 01:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants