feat(性能优化): 优化PDF字形复用,降低多页导出耗时与内存分配
build.yaml / build (push) Successful in 42s

This commit is contained in:
xiaoqidun committed 2026-09-13 23:49:21 +08:00
1 parent e488d25775
commit ad00e95ae6
3 files changed
+28 -1

No files matched your search

+2 -1
View File
@@ -244,13 +244,14 @@ func (r *Renderer) renderPDFPages(pages []pdfPage, writer io.Writer) error {
} }
start := buf.Len() start := buf.Len()
p := pdf.New(buf, pages[0].Box.W, pages[0].Box.H, nil) p := pdf.New(buf, pages[0].Box.W, pages[0].Box.H, nil)
renderer := &pdfRenderer{PDF: p, glyphPaths: make(map[*canvas.Path]*canvas.Path)}
p.SetInfo("", "", "", "", "xiaoqidun/ofdgo") p.SetInfo("", "", "", "", "xiaoqidun/ofdgo")
for i, page := range pages { for i, page := range pages {
if i > 0 { if i > 0 {
p.NewPage(page.Box.W, page.Box.H) p.NewPage(page.Box.W, page.Box.H)
} }
navigation.apply(p, i) navigation.apply(p, i)
if err := r.renderPageToContext(canvas.NewContext(p), page.Content, true); err != nil { if err := r.renderPageToContext(canvas.NewContext(renderer), page.Content, true); err != nil {
buf.Truncate(start) buf.Truncate(start)
return fmt.Errorf("failed to render page %d: %w", i+1, err) return fmt.Errorf("failed to render page %d: %w", i+1, err)
} }
+21
View File
@@ -21,6 +21,27 @@ import (
"github.com/tdewolff/canvas/renderers/pdf" "github.com/tdewolff/canvas/renderers/pdf"
) )
// pdfRenderer PDF渲染器
type pdfRenderer struct {
*pdf.PDF
glyphPaths map[*canvas.Path]*canvas.Path
}
// glyphPath 复用相似变换下的PDF字形圆弧转换
// 入参: path 缓存字形路径, matrix 字形变换
// 返回: *canvas.Path PDF字形路径
func (r *pdfRenderer) glyphPath(path *canvas.Path, matrix canvas.Matrix) *canvas.Path {
if !matrix.IsSimilarity() {
return path
}
if cached, ok := r.glyphPaths[path]; ok {
return cached
}
converted := path.ReplaceArcs()
r.glyphPaths[path] = converted
return converted
}
// pdfPage PDF页面数据 // pdfPage PDF页面数据
type pdfPage struct { type pdfPage struct {
Content *PageContent Content *PageContent
+5
View File
@@ -396,6 +396,11 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
scaleX = advanceLimit / glyphWidth scaleX = advanceLimit / glyphWidth
} }
textWidth = glyphWidth * scaleX textWidth = glyphWidth * scaleX
if face.FauxBold != 0 {
if renderer, ok := ctx.Renderer.(*pdfRenderer); ok {
glyphPath = renderer.glyphPath(glyphPath, ctx.View().Scale(scaleX, 1))
}
}
if scaleX != 1 { if scaleX != 1 {
ctx.Push() ctx.Push()
ctx.Translate(x, y) ctx.Translate(x, y)