fix(转换能力): 修复PDF字体及细线渲染
build.yaml / build (push) Successful in 2m4s

This commit is contained in:
xiaoqidun committed 2026-10-21 15:18:52 +08:00
1 parent 201082daa0
commit c250ca914e
7 files changed
+185 -17

No files matched your search

+26 -7
View File
@@ -260,6 +260,21 @@ func SanitizeCFF(data []byte) ([]byte, error) {
if kind == 1 {
return normalizeCFFType1(data, topDict)
}
private, err := readType2Private(data, topDict[18], &type2Font{})
if err != nil {
return nil, err
}
count := len(private)
if err := normalizeCFFPrivate(private); err != nil {
return nil, err
}
if len(private) != count {
font, err := readType2Font(data)
if err != nil {
return nil, err
}
return rebuildNamedCFF(data, font, font.chars, nil)
}
return data, nil
}
fdArrOff, err := cffDictOffset(data, topDict, 1236)
@@ -342,17 +357,21 @@ func SanitizeCFF(data []byte) ([]byte, error) {
return encodeSanitizedCFF(data[:hdrSize], nameIndexData, topDict, stringIndexData, globalSubrIndexData, charStringsData, finalPrivData, localSubrData), nil
}
// normalizeCFFPrivate 移除旧版CFF中不生效的缺省字段,拒绝需要额外解释的取值
// normalizeCFFPrivate 移除废弃的加粗阈值及未加密标记,拒绝加密字形程序
// 入参: dict 私有字典
// 返回: error 不支持的旧版行为
func normalizeCFFPrivate(dict cffDict) error {
for op, value := range map[int]float64{1215: 0, 1216: -1} {
if values, ok := dict[op]; ok {
if len(values) != 1 || values[0] != value {
return fmt.Errorf("unsupported legacy CFF private operator %d", op)
}
delete(dict, op)
if values, ok := dict[1215]; ok {
if len(values) != 1 || !finite(values[0]) {
return fmt.Errorf("invalid legacy CFF bold threshold")
}
delete(dict, 1215)
}
if values, ok := dict[1216]; ok {
if len(values) != 1 || values[0] != -1 {
return fmt.Errorf("unsupported legacy CFF private operator 1216")
}
delete(dict, 1216)
}
return nil
}
+3
View File
@@ -231,6 +231,9 @@ func rebuildNamedCFF(data []byte, font *type2Font, chars [][]byte, ids []uint16)
if err != nil {
return nil, err
}
if err := normalizeCFFPrivate(private); err != nil {
return nil, err
}
privateData, err := encodeCFFSubsetPrivate(private)
if err != nil {
return nil, err
+1 -1
View File
@@ -235,7 +235,7 @@ func (f *Outliner) phantomPoints(id uint16, data []byte) [4]ttPoint {
return [4]ttPoint{{x: left * 64, ox: left * 64}, {x: (left + int32(f.Font.GlyphAdvance(id))) * 64, ox: (left + int32(f.Font.GlyphAdvance(id))) * 64}, {y: top * 64, oy: top * 64}, {y: (top - int32(f.Font.GlyphVerticalAdvance(id))) * 64, oy: (top - int32(f.Font.GlyphVerticalAdvance(id))) * 64}}
}
// ttRecoverableHint 判断栈参数、指令引用或控制流错误是否允许保留执行前轮廓
// ttRecoverableHint 判断栈参数、区点轮廓及函数引用或控制流错误是否允许保留执行前轮廓
// 入参: err 指令错误
// 返回: bool 是否可恢复
func ttRecoverableHint(err error) bool {
+5 -4
View File
@@ -25,7 +25,7 @@ import (
// errTTStackUnderflow 表示字形程序缺少必需的栈参数
var errTTStackUnderflow = errors.New("TrueType instruction stack underflow")
// errTTInvalidReference 表示字形指令引用不存在的点或函数
// errTTInvalidReference 表示字形指令引用不存在的区、点、轮廓或函数
var errTTInvalidReference = errors.New("invalid TrueType instruction reference")
// errTTInvalidControlFlow 表示条件分支未闭合或跳转超出字节码范围
@@ -380,7 +380,8 @@ func (v *ttInterpreter) execute(code []byte, depth int) error {
case op >= 0x13 && op <= 0x16:
z := v.pop()
if z < 0 || z > 1 {
return fmt.Errorf("invalid TrueType zone")
v.err = fmt.Errorf("%w: zone %d", errTTInvalidReference, z)
break
}
if op == 0x16 {
g.zone = [3]int32{z, z, z}
@@ -854,7 +855,7 @@ func (v *ttInterpreter) shift(op byte) {
if op <= 0x35 {
contour := v.pop()
if contour < 0 || int64(contour) >= int64(len(v.ends)) {
v.err = fmt.Errorf("invalid TrueType contour reference")
v.err = fmt.Errorf("%w: contour %d", errTTInvalidReference, contour)
return
}
if contour > 0 {
@@ -864,7 +865,7 @@ func (v *ttInterpreter) shift(op byte) {
} else {
target = v.pop()
if target < 0 || target > 1 {
v.err = fmt.Errorf("invalid TrueType zone")
v.err = fmt.Errorf("%w: zone %d", errTTInvalidReference, target)
return
}
to = len(v.zones[target])