From 92149b220eea90570db456554acef8298e29c5cc Mon Sep 17 00:00:00 2001 From: xiaoqidun Date: Mon, 12 Oct 2026 16:55:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=AD=97=E4=BD=93=E5=A4=84=E7=90=86):=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AD=97=E4=BD=93=E8=A3=81=E5=89=AA=E4=B8=8E?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdgo_font_resource_sfnt.go | 35 ++++++++++++++--------------------- ofdgo_font_sfnt.go | 26 +++++++++++++++++--------- ofdgo_font_variable.go | 16 ++++++++-------- 3 files changed, 39 insertions(+), 38 deletions(-) diff --git a/ofdgo_font_resource_sfnt.go b/ofdgo_font_resource_sfnt.go index de67309..6fad1fa 100644 --- a/ofdgo_font_resource_sfnt.go +++ b/ofdgo_font_resource_sfnt.go @@ -283,17 +283,12 @@ func subsetSourceSFNTFont(data []byte, usage *editorFontUsage) []byte { return nil } } - for id := range glyphs { - if id >= sfnt.NumGlyphs() { - return nil - } - dependencies, err := sfnt.glyphDependencies(id) - if err != nil { - return nil - } - for _, dependency := range dependencies { - glyphs[dependency] = true - } + dependencies, err := sfnt.glyphDependencies(slices.Collect(maps.Keys(glyphs))...) + if err != nil { + return nil + } + for _, dependency := range dependencies { + glyphs[dependency] = true } var glyf, loca []byte for id := 0; id <= int(sfnt.NumGlyphs()); id++ { @@ -426,16 +421,14 @@ func subsetCompactSFNTFont(sfnt *sfntFont, glyphs []uint16) ([]byte, error) { ids = append(ids, id) } } - for index := 0; index < len(ids); index++ { - dependencies, err := sfnt.glyphDependencies(ids[index]) - if err != nil { - return nil, err - } - for _, id := range dependencies { - if _, ok := remap[id]; !ok { - remap[id] = uint16(len(ids)) - ids = append(ids, id) - } + dependencies, err := sfnt.glyphDependencies(ids...) + if err != nil { + return nil, err + } + for _, id := range dependencies { + if _, ok := remap[id]; !ok { + remap[id] = uint16(len(ids)) + ids = append(ids, id) } } table := make(map[string][]byte) diff --git a/ofdgo_font_sfnt.go b/ofdgo_font_sfnt.go index ad164c0..9c88a18 100644 --- a/ofdgo_font_sfnt.go +++ b/ofdgo_font_sfnt.go @@ -263,21 +263,24 @@ func (f *sfntFont) VerticalMetrics() (uint16, uint16, uint16) { // 返回: []byte 独立字体 func (f *sfntFont) Write() []byte { data, _ := serializeOTF(f.Tables); return data } -// glyphDependencies 收集复合字形依赖,拒绝循环引用和截断记录 -// 入参: gid 字形编号 +// glyphDependencies 批量收集复合字形依赖,校验引用、记录长度和嵌套深度 +// 入参: glyphs 字形编号 // 返回: []uint16 依赖字形, error 字形错误 -func (f *sfntFont) glyphDependencies(gid uint16) ([]uint16, error) { - seen, active := make(map[uint16]bool), make(map[uint16]bool) +func (f *sfntFont) glyphDependencies(glyphs ...uint16) ([]uint16, error) { + heights, active := make(map[uint16]int), make(map[uint16]bool) var result []uint16 var visit func(uint16) error visit = func(id uint16) error { if id >= f.count || active[id] || len(active) > 64 { return fmt.Errorf("invalid composite glyph reference") } - if seen[id] { + if height := heights[id]; height != 0 { + if len(active)+height > 65 { + return fmt.Errorf("invalid composite glyph reference") + } return nil } - seen[id], active[id] = true, true + heights[id], active[id] = 1, true defer delete(active, id) data, err := trueTypeGlyphData(f.Tables, id) if err != nil { @@ -315,18 +318,23 @@ func (f *sfntFont) glyphDependencies(gid uint16) ([]uint16, error) { if pos > len(data) { return fmt.Errorf("truncated composite transform") } - if !seen[child] { + if heights[child] == 0 { result = append(result, child) } if err := visit(child); err != nil { return err } + heights[id] = max(heights[id], heights[child]+1) if flags&0x20 == 0 { break } } return nil } - err := visit(gid) - return result, err + for _, id := range glyphs { + if err := visit(id); err != nil { + return nil, err + } + } + return result, nil } diff --git a/ofdgo_font_variable.go b/ofdgo_font_variable.go index fd65a59..1a54e87 100644 --- a/ofdgo_font_variable.go +++ b/ofdgo_font_variable.go @@ -17,6 +17,8 @@ package ofdgo import ( "encoding/binary" "fmt" + "maps" + "slices" ) // variableSFNTSubsettable 核对TrueType可变轴与字形变化表的基本结构 @@ -51,14 +53,12 @@ func subsetVariableSFNTFont(sfnt *sfntFont, glyphs []uint16) ([]byte, error) { usage.chars[char] = true } } - for gid := range usage.glyphs { - dependencies, err := sfnt.glyphDependencies(gid) - if err != nil { - return nil, err - } - for _, dependency := range dependencies { - usage.glyphs[dependency] = true - } + dependencies, err := sfnt.glyphDependencies(slices.Collect(maps.Keys(usage.glyphs))...) + if err != nil { + return nil, err + } + for _, dependency := range dependencies { + usage.glyphs[dependency] = true } mapping := make(map[rune]uint16, len(usage.chars)) for char := range usage.chars {