mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 08:46:55 +08:00
90 lines
3.2 KiB
Go
90 lines
3.2 KiB
Go
// Copyright 2025-2026 肖其顿 (XIAO QI DUN)
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package ofdgo
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
|
|
basefont "github.com/xiaoqidun/ofdgo/internal/base/font"
|
|
)
|
|
|
|
// SFNTBackend 提供独立的OpenType字体度量、轮廓和资源处理
|
|
type SFNTBackend struct{}
|
|
|
|
// sfntResourceMetrics 隔离资源解析器的度量实现
|
|
type sfntResourceMetrics struct{ *basefont.SFNT }
|
|
|
|
// Name 返回资源后端标识
|
|
// 返回: string 后端标识
|
|
func (SFNTBackend) Name() string { return "sfnt" }
|
|
|
|
// OpenFontResource 提取独立字体并读取名称、样式和裁剪能力
|
|
// CFF2使用默认实例的静态轮廓,不改变原字体文件
|
|
// 入参: file 字体文件, index 集合索引
|
|
// 返回: *FontResource 字体资源, error 解析错误
|
|
func (SFNTBackend) OpenFontResource(file FontFile, index int) (*FontResource, error) {
|
|
data, err := file.Face(index)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
data, err = basefont.DefaultCFF2Font(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sfnt, err := basefont.ParseSFNT(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
name := basefont.SFNTName(sfnt, 6, 4, 1)
|
|
if name == "" {
|
|
return nil, fmt.Errorf("font has no name")
|
|
}
|
|
extension := ".ttf"
|
|
if sfnt.IsCFF {
|
|
extension = ".otf"
|
|
}
|
|
return &FontResource{
|
|
FontMetrics: sfntResourceMetrics{sfnt}, Data: data, Extension: extension,
|
|
Font: Font{FontName: name, FamilyName: basefont.SFNTName(sfnt, 16, 1), Charset: "unicode", Bold: binary.BigEndian.Uint16(sfnt.Tables["head"][44:])&1 != 0, Italic: binary.BigEndian.Uint16(sfnt.Tables["head"][44:])&2 != 0, FixedWidth: len(sfnt.Tables["post"]) >= 16 && binary.BigEndian.Uint32(sfnt.Tables["post"][12:]) != 0},
|
|
CanSubset: basefont.Subsettable(sfnt),
|
|
}, nil
|
|
}
|
|
|
|
// SubsetFont 裁剪新建字体并按要求保留显式字形编号
|
|
// 入参: data 字体数据, glyphs 用字, preserve 是否保留编号
|
|
// 返回: []byte 子集, error 裁剪错误
|
|
func (SFNTBackend) SubsetFont(data []byte, glyphs []uint16, preserve bool) ([]byte, error) {
|
|
return basefont.SubsetSFNT(data, glyphs, preserve)
|
|
}
|
|
|
|
// SubsetSourceFont 按全包引用裁剪原字体,不确定时保留原资源
|
|
// 入参: data 字体数据, usage 用字信息
|
|
// 返回: []byte 子集, error 裁剪错误
|
|
func (SFNTBackend) SubsetSourceFont(data []byte, usage FontUsage) ([]byte, error) {
|
|
u := &basefont.Usage{Characters: make(map[rune]bool), Glyphs: make(map[uint16]bool), Unsafe: usage.Unsafe}
|
|
for _, char := range usage.Characters {
|
|
u.Characters[char] = true
|
|
}
|
|
for _, glyph := range usage.Glyphs {
|
|
u.Glyphs[glyph] = true
|
|
}
|
|
return basefont.SubsetSourceSFNT(data, u), nil
|
|
}
|
|
|
|
// Write 返回未改动元信息的字体数据
|
|
// 返回: []byte 字体数据
|
|
func (f sfntResourceMetrics) Write() []byte { return f.SFNT.Write() }
|