From a5f51294eb5d369dc83d32b12669225608ab497d Mon Sep 17 00:00:00 2001 From: xiaoqidun Date: Sat, 10 Oct 2026 15:52:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=AD=97=E4=BD=93=E6=B8=B2=E6=9F=93):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AD=97=E4=BD=93=E5=BC=95=E7=94=A8=E4=B8=8E?= =?UTF-8?q?=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdgo_editor.go | 3 +++ ofdgo_editor_open.go | 8 +++++++- ofdgo_font_backend.go | 20 ++++++++++++++++---- ofdgo_font_fs.go | 2 +- ofdgo_font_info.go | 20 ++++++++++++++++++-- ofdgo_font_source.go | 4 ++-- ofdgo_render_text.go | 2 +- ofdgo_renderer_font_loader_canvas.go | 2 +- ofdgo_renderer_text_canvas.go | 2 +- 9 files changed, 50 insertions(+), 13 deletions(-) diff --git a/ofdgo_editor.go b/ofdgo_editor.go index be29d13..d37b718 100644 --- a/ofdgo_editor.go +++ b/ofdgo_editor.go @@ -1080,6 +1080,9 @@ func scaleTextNumbers(value string, scale float64) string { // 入参: obj 文字对象 // 返回: error 错误信息 func (e *Editor) prepareText(obj *TextObject) error { + if id := editorResourceID(obj.Font); id != "" { + obj.Font = id + } var sfnt FontMetrics external := false for _, resource := range e.resources { diff --git a/ofdgo_editor_open.go b/ofdgo_editor_open.go index 41c1a27..a0d1bc5 100644 --- a/ofdgo_editor_open.go +++ b/ofdgo_editor_open.go @@ -179,13 +179,16 @@ func (e *Editor) ObjectCapabilities(page int, id string) (ObjectCapabilities, er // 入参: id 字体资源标识 // 返回: []byte 独立字体数据, error 错误信息 func (e *Editor) FontData(id string) ([]byte, error) { + if key := editorResourceID(id); key != "" { + id = key + } for _, resource := range e.resources { if resource.font != nil && resource.font.ID == id && len(resource.data) != 0 { return bytes.Clone(resource.data), nil } } if e.source != nil { - if definition := e.source.reader.fontCache[id]; definition != nil && definition.FontFile != "" { + if definition := e.source.reader.fontDefinition(id); definition != nil && definition.FontFile != "" { return e.source.reader.FontData(id) } } @@ -799,6 +802,9 @@ func editorGeometry(object GraphicObject) (string, string) { // 入参: id 字体资源标识 // 返回: FontMetrics 字体度量, error 错误信息 func (e *Editor) editorFont(id string) (FontMetrics, error) { + if key := editorResourceID(id); key != "" { + id = key + } if metrics := e.fontMetrics[id]; metrics != nil { return metrics, nil } diff --git a/ofdgo_font_backend.go b/ofdgo_font_backend.go index 29eea13..99cee9d 100644 --- a/ofdgo_font_backend.go +++ b/ofdgo_font_backend.go @@ -146,12 +146,18 @@ func (r *Renderer) ResolveFont(id string, exact bool) (ResolvedFont, error) { if r.backends.Fonts == nil { return ResolvedFont{}, fmt.Errorf("fonts: %w", ErrBackendUnavailable) } - key := resolvedFontKey{id: id, exact: exact, definition: r.Reader.fontCache[id]} + key := resolvedFontKey{id: id, exact: exact, definition: r.Reader.fontDefinition(id)} + if key.definition != nil && key.definition.ID != "" { + key.id = key.definition.ID + } if cached, ok := r.resolvedFonts[key]; ok { return cached.font, cached.err } - resolved, err := r.backends.Fonts.ResolveFont(r, id, exact) - key.definition = r.Reader.fontCache[id] + resolved, err := r.backends.Fonts.ResolveFont(r, key.id, exact) + key.definition = r.Reader.fontDefinition(id) + if key.definition != nil && key.definition.ID != "" { + key.id = key.definition.ID + } r.resolvedFonts[key] = resolvedFontResult{font: resolved, err: err} return resolved, err } @@ -161,6 +167,9 @@ func (r *Renderer) ResolveFont(id string, exact bool) (ResolvedFont, error) { // 入参: id 字体资源标识 // 返回: *PreparedFont 绘制字体, error 字体解析错误 func (r *Renderer) PrepareFont(id string) (*PreparedFont, error) { + if definition := r.Reader.fontDefinition(id); definition != nil && definition.ID != "" { + id = definition.ID + } if cached := r.preparedFonts[id]; cached != nil { return cached, nil } @@ -168,8 +177,11 @@ func (r *Renderer) PrepareFont(id string) (*PreparedFont, error) { if err != nil { return nil, err } + definition := r.Reader.fontDefinition(id) + if definition != nil && definition.ID != "" { + id = definition.ID + } prepared := &PreparedFont{ResolvedFont: resolved} - definition := r.Reader.fontCache[id] if definition != nil && definition.FontFile != "" { key := r.fontDigest(resolved.Data) if content, ok := r.fontPreparations.get(key); ok { diff --git a/ofdgo_font_fs.go b/ofdgo_font_fs.go index e9e870a..7263787 100644 --- a/ofdgo_font_fs.go +++ b/ofdgo_font_fs.go @@ -262,7 +262,7 @@ func (r *Reader) MatchFontFiles(files []string, ids ...string) ([]string, error) return nil, err } for _, id := range ids { - if r.fontCache[id] == nil { + if r.fontDefinition(id) == nil { fonts = append(fonts, Font{ID: id}) } } diff --git a/ofdgo_font_info.go b/ofdgo_font_info.go index 8d686ee..113e86e 100644 --- a/ofdgo_font_info.go +++ b/ofdgo_font_info.go @@ -111,12 +111,12 @@ func (r *Reader) FontData(id string) ([]byte, error) { // 入参: id 字体资源标识, readonly 是否允许借用只读资源 // 返回: []byte 字体数据, error 资源或集合错误 func (r *Reader) fontData(id string, readonly bool) ([]byte, error) { - if r.fontCache[id] == nil { + if r.fontDefinition(id) == nil { if _, err := r.Fonts(); err != nil { return nil, err } } - f := r.fontCache[id] + f := r.fontDefinition(id) if f == nil || f.FontFile == "" { return nil, fmt.Errorf("embedded font %q not found", id) } @@ -135,6 +135,14 @@ func (r *Reader) fontData(id string, readonly bool) ([]byte, error) { return data, nil } +// fontDefinition 按资源标识查找已加载的字体,数值等价的引用共用同一定义 +// 入参: id 字体资源标识 +// 返回: *Font 字体定义,未找到或别名冲突时为nil +func (r *Reader) fontDefinition(id string) *Font { + font, _ := resourceValue(r.fontCache, id) + return font +} + // FontInfos 获取OFD字体诊断信息 // 返回: []FontInfo 字体诊断列表, error 错误信息 func (r *Renderer) FontInfos() ([]FontInfo, error) { @@ -293,6 +301,14 @@ func (r *Renderer) fontInfos(usage map[string]int) ([]FontInfo, error) { if err != nil { return nil, err } + counts := make(map[string]int, len(usage)) + for id, used := range usage { + if font := r.Reader.fontDefinition(id); font != nil { + id = font.ID + } + counts[id] += used + } + usage = counts infos := make([]FontInfo, 0, len(fonts)+len(usage)) seen := make(map[string]bool) for _, font := range fonts { diff --git a/ofdgo_font_source.go b/ofdgo_font_source.go index 5985bf9..187fe24 100644 --- a/ofdgo_font_source.go +++ b/ofdgo_font_source.go @@ -158,12 +158,12 @@ func (r *Renderer) fontSourceMatch(backend FontBackend, fontID string, definitio // 入参: backend 字体后端, id 字体ID, exact 是否禁止无关回退 // 返回: ResolvedFont 字体及来源, error 解析错误 func (r *Renderer) resolveFontSource(backend FontBackend, id string, exact bool) (ResolvedFont, error) { - definition := r.Reader.fontCache[id] + definition := r.Reader.fontDefinition(id) if definition == nil && !r.Reader.fontResourcesRead && r.Reader.OFD != nil { if _, err := r.Reader.Fonts(); err != nil { return ResolvedFont{}, err } - definition = r.Reader.fontCache[id] + definition = r.Reader.fontDefinition(id) } if definition == nil { definition = &Font{ID: id} diff --git a/ofdgo_render_text.go b/ofdgo_render_text.go index c5ad2ce..11276b3 100644 --- a/ofdgo_render_text.go +++ b/ofdgo_render_text.go @@ -118,7 +118,7 @@ func (r *Renderer) PositionText(object TextObject, state RenderState) (*Position italic = italic || defaults.Italic } bold := weight >= 700 - if definition := r.Reader.fontCache[id]; definition != nil { + if definition := r.Reader.fontDefinition(id); definition != nil { bold = bold && !definition.Bold if definition.FontFile == "" && fontNoSyntheticBold(definition.FontName, definition.FamilyName) { bold = false diff --git a/ofdgo_renderer_font_loader_canvas.go b/ofdgo_renderer_font_loader_canvas.go index 4940459..0ba9e20 100644 --- a/ofdgo_renderer_font_loader_canvas.go +++ b/ofdgo_renderer_font_loader_canvas.go @@ -32,7 +32,7 @@ func (r *Renderer) loadFont(fontID string) *canvas.FontFamily { r.renderError = err return nil } - of := r.Reader.fontCache[fontID] + of := r.Reader.fontDefinition(fontID) if len(resolved.Data) == 0 { return nil } diff --git a/ofdgo_renderer_text_canvas.go b/ofdgo_renderer_text_canvas.go index c83e0e4..0abaf67 100644 --- a/ofdgo_renderer_text_canvas.go +++ b/ofdgo_renderer_text_canvas.go @@ -142,7 +142,7 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64 } fontID := r.textObjectFontID(obj) embeddedFont := false - if of, ok := r.Reader.fontCache[fontID]; ok { + if of := r.Reader.fontDefinition(fontID); of != nil { embeddedFont = of.FontFile != "" if syntheticBold && !embeddedFont && fontNoSyntheticBold(of.FontName, of.FamilyName) { syntheticBold = false