From 565b7f6db41037c935b2cbf54241bc13f56b4e65 Mon Sep 17 00:00:00 2001 From: xiaoqidun Date: Sat, 12 Sep 2026 12:25:18 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96):=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=92=99=E7=89=88=E5=A4=84=E7=90=86=E4=B8=8E?= =?UTF-8?q?=E5=AD=97=E4=BD=93=E6=9B=B4=E6=96=B0=E6=80=A7=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E4=BF=9D=E6=8C=81=E6=B8=B2=E6=9F=93=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/webui/webui.go | 9 +++------ ofdgo.go | 12 +----------- ofdgo_renderer.go | 20 ++++++++++++++++++++ ofdgo_renderer_image.go | 12 ++++++++++++ 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/internal/webui/webui.go b/internal/webui/webui.go index 048690c..07b6fe0 100644 --- a/internal/webui/webui.go +++ b/internal/webui/webui.go @@ -237,18 +237,15 @@ func (s *Session) Close() error { // 入参: fonts 字体文件列表 // 返回: error 错误信息 func (s *Session) SetFonts(fonts []FontFile) error { - opts := []ofdgo.RendererOption{ - ofdgo.WithDPI(s.Renderer.DPI), - ofdgo.WithAnnotations(s.Renderer.RenderAnnotations), - } if len(fonts) > 0 { fontFS := ofdgo.NewFontFS(fonts) if fontFS.Len() == 0 { return fmt.Errorf("invalid font file") } - opts = append(opts, ofdgo.WithFontFS(fontFS)) + s.Renderer.SetFontFS(fontFS) + } else { + s.Renderer.SetFontFS() } - s.Renderer = ofdgo.NewRenderer(s.Reader, opts...) return nil } diff --git a/ofdgo.go b/ofdgo.go index 74d2712..eec37e0 100644 --- a/ofdgo.go +++ b/ofdgo.go @@ -20,8 +20,6 @@ import ( "image" "io" "io/fs" - - "github.com/tdewolff/canvas" ) // Open 打开OFD文件 @@ -71,18 +69,10 @@ func NewRenderer(reader *Reader, opts ...RendererOption) *Renderer { RenderAnnotations: true, DrawParams: reader.drawParamCache, CompositeGraphicUnits: reader.compositeGraphicUnitCache, - FontMap: make(map[string]*canvas.FontFamily), - FontGIDMap: make(map[string]map[uint16]rune), - FontCIDMap: make(map[string]map[uint16]rune), - fontCache: make(map[fontCacheKey]*canvas.FontFamily), - fontSourceCache: make(map[string][]fontSource), - fontSourceUsed: make(map[string]fontSource), - fontDirCandidates: make(map[string][]fontFileCandidate), - fontFSCandidates: make(map[int][]fontFileCandidate), - textGlyphPathCache: make(map[textGlyphPathCacheKey]textGlyphPathCacheValue), templatePageCache: make(map[string]*PageContent), imageCache: make(map[string]image.Image), } + r.resetFontCache() for _, opt := range opts { opt(r) } diff --git a/ofdgo_renderer.go b/ofdgo_renderer.go index 7d5c1c5..6ed9cb2 100644 --- a/ofdgo_renderer.go +++ b/ofdgo_renderer.go @@ -50,6 +50,26 @@ type Renderer struct { // RendererOption 渲染器配置选项 type RendererOption func(*Renderer) +// SetFontFS 替换外部字体文件系统并重置字体缓存 +// 入参: fsys 字体文件系统 +func (r *Renderer) SetFontFS(fsys ...fs.FS) { + r.fontFS = append([]fs.FS(nil), fsys...) + r.resetFontCache() +} + +// resetFontCache 重置字体匹配、加载和字形缓存 +func (r *Renderer) resetFontCache() { + r.FontMap = make(map[string]*canvas.FontFamily) + r.FontGIDMap = make(map[string]map[uint16]rune) + r.FontCIDMap = make(map[string]map[uint16]rune) + r.fontCache = make(map[fontCacheKey]*canvas.FontFamily) + r.fontSourceCache = make(map[string][]fontSource) + r.fontSourceUsed = make(map[string]fontSource) + r.fontDirCandidates = make(map[string][]fontFileCandidate) + r.fontFSCandidates = make(map[int][]fontFileCandidate) + r.textGlyphPathCache = make(map[textGlyphPathCacheKey]textGlyphPathCacheValue) +} + // RenderPage 渲染特定页面内容 // 入参: page 页面内容 // 返回: *canvas.Canvas 画布实例, error 错误信息 diff --git a/ofdgo_renderer_image.go b/ofdgo_renderer_image.go index aaf4763..1f5ebef 100644 --- a/ofdgo_renderer_image.go +++ b/ofdgo_renderer_image.go @@ -140,6 +140,18 @@ func imageWithMask(img, mask image.Image) image.Image { maskBounds = bounds } out := image.NewNRGBA(bounds) + if src, ok := source.(*image.NRGBA); ok { + for y := 0; y < bounds.Dy(); y++ { + offset := src.PixOffset(bounds.Min.X, bounds.Min.Y+y) + row := out.Pix[y*out.Stride : (y+1)*out.Stride] + copy(row, src.Pix[offset:offset+len(row)]) + for x := 3; x < len(row); x += 4 { + a := imageGrayAt(opacity, maskBounds.Min.X+x/4, maskBounds.Min.Y+y).Y + row[x] = uint8(int(row[x]) * int(a) / 255) + } + } + return out + } for y := bounds.Min.Y; y < bounds.Max.Y; y++ { for x := bounds.Min.X; x < bounds.Max.X; x++ { mx := maskBounds.Min.X + x - bounds.Min.X