diff --git a/ofdgo_renderer_output.go b/ofdgo_renderer_output.go index e4167fb..b7eca0c 100644 --- a/ofdgo_renderer_output.go +++ b/ofdgo_renderer_output.go @@ -244,13 +244,14 @@ func (r *Renderer) renderPDFPages(pages []pdfPage, writer io.Writer) error { } start := buf.Len() 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") for i, page := range pages { if i > 0 { p.NewPage(page.Box.W, page.Box.H) } 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) return fmt.Errorf("failed to render page %d: %w", i+1, err) } diff --git a/ofdgo_renderer_pdf.go b/ofdgo_renderer_pdf.go index b55a4c4..d7b749f 100644 --- a/ofdgo_renderer_pdf.go +++ b/ofdgo_renderer_pdf.go @@ -21,6 +21,27 @@ import ( "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页面数据 type pdfPage struct { Content *PageContent diff --git a/ofdgo_renderer_text.go b/ofdgo_renderer_text.go index ce29d71..ae8b01e 100644 --- a/ofdgo_renderer_text.go +++ b/ofdgo_renderer_text.go @@ -396,6 +396,11 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64 scaleX = advanceLimit / glyphWidth } 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 { ctx.Push() ctx.Translate(x, y)