mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 08:46:55 +08:00
1 parent
62c81e7061
commit
226688bbdc
2 files changed
+33
-5
No files matched your search
@@ -51,7 +51,7 @@ func subsetNamedCFFFont(sfnt *sfntFont, glyphs []uint16) ([]byte, error) {
|
||||
return serializeOTF(tables)
|
||||
}
|
||||
|
||||
// subsetCFFCharstrings 清空未引用的Type2轮廓,保留原字宽、提示和子程序
|
||||
// subsetCFFCharstrings 清空未引用的Type2轮廓及子程序,保留原字宽、提示和编号
|
||||
// 入参: data 非CID的CFF数据, keep 保留的字形,调用后包含组合组件
|
||||
// 返回: []byte 重建的CFF数据, error 结构或依赖错误
|
||||
func subsetCFFCharstrings(data []byte, keep map[uint16]bool) ([]byte, error) {
|
||||
@@ -60,12 +60,15 @@ func subsetCFFCharstrings(data []byte, keep map[uint16]bool) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
keep[0] = true
|
||||
locals := make([]bool, len(font.locals))
|
||||
globals := make([]bool, len(font.globals))
|
||||
var stack [48]float64
|
||||
for gid := range keep {
|
||||
if int(gid) >= len(font.chars) {
|
||||
return nil, fmt.Errorf("CFF glyph index out of range")
|
||||
}
|
||||
steps := 0
|
||||
state := type2State{font: font, width: font.def, seed: font.seed + uint64(gid), steps: &steps, dependencies: keep}
|
||||
state := type2State{font: font, args: stack[:0], width: font.def, seed: font.seed + uint64(gid), steps: &steps, dependencies: keep, localUsage: locals, globalUsage: globals}
|
||||
if _, err := state.run(font.chars[gid], 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -78,7 +81,7 @@ func subsetCFFCharstrings(data []byte, keep map[uint16]bool) ([]byte, error) {
|
||||
continue
|
||||
}
|
||||
steps := 0
|
||||
state := type2State{font: font, width: font.def, widthOnly: true, seed: font.seed + uint64(gid), steps: &steps, dependencies: keep}
|
||||
state := type2State{font: font, args: stack[:0], width: font.def, widthOnly: true, seed: font.seed + uint64(gid), steps: &steps, dependencies: keep}
|
||||
if _, err := state.run(program, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -100,9 +103,27 @@ func subsetCFFCharstrings(data []byte, keep map[uint16]bool) ([]byte, error) {
|
||||
chars[gid] = encoded.Bytes()
|
||||
empty[state.width] = chars[gid]
|
||||
}
|
||||
font.locals = subsetCFFSubroutines(font.locals, locals)
|
||||
font.globals = subsetCFFSubroutines(font.globals, globals)
|
||||
return rebuildNamedCFF(data, font, chars)
|
||||
}
|
||||
|
||||
// subsetCFFSubroutines 将未引用的子程序替换为空返回,保持调用编号及偏移基数
|
||||
// 入参: programs 子程序索引, used 引用标记
|
||||
// 返回: [][]byte 裁剪后的子程序索引
|
||||
func subsetCFFSubroutines(programs [][]byte, used []bool) [][]byte {
|
||||
result := make([][]byte, len(programs))
|
||||
empty := []byte{11}
|
||||
for index, program := range programs {
|
||||
if used[index] {
|
||||
result[index] = program
|
||||
} else {
|
||||
result[index] = empty
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// rebuildNamedCFF 重建非CID的CFF偏移,保留字符集、编码和私有提示参数
|
||||
// 入参: data 原始CFF数据, font 执行资源, chars 替换后的字形程序
|
||||
// 返回: []byte 重建的CFF数据, error 不支持的结构
|
||||
@@ -142,7 +163,7 @@ func rebuildNamedCFF(data []byte, font *type2Font, chars [][]byte) ([]byte, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
private, err := readType2Private(data, dict[18], font)
|
||||
private, err := readType2Private(data, dict[18], &type2Font{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+8
-1
@@ -55,6 +55,8 @@ type type2State struct {
|
||||
seed uint64
|
||||
steps *int
|
||||
dependencies map[uint16]bool
|
||||
localUsage []bool
|
||||
globalUsage []bool
|
||||
}
|
||||
|
||||
// readType2Index 读取并校验CFF索引的全部偏移,不复制程序字节
|
||||
@@ -336,13 +338,18 @@ func (s *type2State) run(data []byte, depth int) (bool, error) {
|
||||
value := s.args[len(s.args)-1]
|
||||
s.args = s.args[:len(s.args)-1]
|
||||
subrs := s.font.locals
|
||||
usage := s.localUsage
|
||||
if op == 29 {
|
||||
subrs = s.font.globals
|
||||
usage = s.globalUsage
|
||||
}
|
||||
value += float64(cffSubrBias(len(subrs)))
|
||||
if value < 0 || value >= float64(len(subrs)) || value != math.Trunc(value) {
|
||||
return false, fmt.Errorf("invalid Type2 subroutine number")
|
||||
}
|
||||
if usage != nil {
|
||||
usage[int(value)] = true
|
||||
}
|
||||
ended, err := s.run(subrs[int(value)], depth+1)
|
||||
if ended || err != nil {
|
||||
return ended, err
|
||||
@@ -503,7 +510,7 @@ func (s *type2State) appendComponent(code, x, y float64) error {
|
||||
if s.dependencies != nil {
|
||||
s.dependencies[uint16(gid)] = true
|
||||
}
|
||||
child := type2State{font: s.font, matrix: s.matrix, width: s.font.def, component: true, output: s.output, originX: x, originY: y, outX: s.outX, outY: s.outY, seed: s.font.seed + uint64(gid), steps: s.steps, stripHints: s.stripHints, dependencies: s.dependencies}
|
||||
child := type2State{font: s.font, matrix: s.matrix, width: s.font.def, component: true, output: s.output, originX: x, originY: y, outX: s.outX, outY: s.outY, seed: s.font.seed + uint64(gid), steps: s.steps, stripHints: s.stripHints, dependencies: s.dependencies, localUsage: s.localUsage, globalUsage: s.globalUsage}
|
||||
_, err := child.run(s.font.chars[gid], 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid Type2 component %s: %w", name, err)
|
||||
|
||||
Reference in new issue
Block a user