From ef901bea0f54c2466439f004c2b434b8ab7cb31e Mon Sep 17 00:00:00 2001 From: xiaoqidun Date: Wed, 14 Oct 2026 18:46:22 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=BD=AC=E6=8D=A2=E8=83=BD=E5=8A=9B):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8DPDF=E5=AD=97=E4=BD=93=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/base/font/ttf.go | 36 ++++++++++++++++++++++++++++++++++++ internal/codec/pdf/font.go | 4 ++++ 2 files changed, 40 insertions(+) diff --git a/internal/base/font/ttf.go b/internal/base/font/ttf.go index 3d44d87..c6dab1e 100644 --- a/internal/base/font/ttf.go +++ b/internal/base/font/ttf.go @@ -19,6 +19,38 @@ import ( "encoding/binary" ) +// NormalizeOS2 去除已知版本OS/2表的冗余零尾部,保留所有标准字段 +// 入参: data 原始表数据 +// 返回: []byte 规范化表数据,未知版本、截断或非零尾部保持原样 +func NormalizeOS2(data []byte) []byte { + if len(data) < 2 { + return data + } + var size int + switch binary.BigEndian.Uint16(data) { + case 0: + // 旧式68字节表保持原样,不将截断的78字节表推断为旧式表。 + size = 78 + case 1: + size = 86 + case 2, 3, 4: + size = 96 + case 5: + size = 100 + default: + return data + } + if len(data) <= size { + return data + } + for _, value := range data[size:] { + if value != 0 { + return data + } + } + return data[:size] +} + // fixTrueType 尝试修复TrueType/OpenType字体数据 // 入参: data 原始字体数据, fixCmap 是否修复cmap, fixName 是否修复name // 返回: bool 是否修复, []byte 修复后数据, map[rune]uint16 字符映射, bool 是否缺失cmap, error 错误信息 @@ -83,6 +115,10 @@ func fixTrueType(data []byte, fixCmap, fixName bool) (bool, []byte, map[rune]uin existingTables["cmap"] = cmap malformedDirectory = true } + if os2 := NormalizeOS2(existingTables["OS/2"]); len(os2) != len(existingTables["OS/2"]) { + existingTables["OS/2"] = os2 + malformedDirectory = true + } missingHead := existingTables["head"] == nil if !missingHead { head := existingTables["head"] diff --git a/internal/codec/pdf/font.go b/internal/codec/pdf/font.go index 207dee6..bc18827 100644 --- a/internal/codec/pdf/font.go +++ b/internal/codec/pdf/font.go @@ -91,6 +91,10 @@ func FontProgram(source *pdfgo.Font, type1 *basefont.Type1Program) ([]byte, Font return nil, repair, err } changed := repair.Locations + if os2 := basefont.NormalizeOS2(tables["OS/2"]); len(os2) != len(tables["OS/2"]) { + tables["OS/2"] = os2 + changed = true + } if head := tables["head"]; len(head) == 56 && binary.BigEndian.Uint32(head[:4]) == 0x00010000 && head[54] == 0 && head[55] == 0 { tables["head"] = head[:54] changed = true