mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 08:46:55 +08:00
1 parent
a4f979ed2f
commit
460701f4d9
7 files changed
+83
-68
No files matched your search
@@ -36,6 +36,13 @@ type Face struct {
|
||||
// 入参: data 名称表数据, index 零起始字体索引
|
||||
// 返回: Face 字体信息
|
||||
func FaceInfo(data []byte, index int) Face {
|
||||
return faceInfoLanguage(data, index, 0xffff, 0xffff)
|
||||
}
|
||||
|
||||
// faceInfoLanguage 优先读取指定平台和语言的显示名称,保留标识及全部别名
|
||||
// 入参: data 名称表数据, index 字体索引, platform 平台标识, language 语言标识
|
||||
// 返回: Face 字体信息
|
||||
func faceInfoLanguage(data []byte, index int, platform, language uint16) Face {
|
||||
records, values := fontNameValues(data)
|
||||
name := func(ids ...uint16) string {
|
||||
for _, id := range ids {
|
||||
@@ -49,7 +56,19 @@ func FaceInfo(data []byte, index int) Face {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
return Face{Index: index, FullName: name(4, 6, 16, 1), Family: name(16, 1), Style: name(17, 2), PostScriptName: name(6), Names: fontNamesFromValues(records, values)}
|
||||
localized := func(ids ...uint16) string {
|
||||
for _, id := range ids {
|
||||
for _, record := range records {
|
||||
if record.Platform == platform && record.Language == language && record.Name == id {
|
||||
if value := strings.TrimSpace(values[[4]uint16{record.Platform, record.Encoding, record.Language, id}]); value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return name(ids...)
|
||||
}
|
||||
return Face{Index: index, FullName: localized(4, 6, 16, 1), Family: localized(16, 1), Style: localized(17, 2), PostScriptName: name(6), Names: fontNamesFromValues(records, values)}
|
||||
}
|
||||
|
||||
// FileCount 校验字体或集合头并读取字体数量
|
||||
@@ -78,6 +97,13 @@ func FileCount(data []byte) (int, error) {
|
||||
// 入参: data OpenType数据
|
||||
// 返回: []Face 字体列表, error 格式或名称表错误
|
||||
func ReadFaces(data []byte) ([]Face, error) {
|
||||
return ReadLocalizedFaces(data, 0xffff, 0xffff)
|
||||
}
|
||||
|
||||
// ReadLocalizedFaces 读取指定平台和语言的字体名称,缺失时沿用名称表顺序
|
||||
// 入参: data OpenType数据, platform 名称表平台标识, language 名称表语言标识
|
||||
// 返回: []Face 字体列表, error 格式或名称表错误
|
||||
func ReadLocalizedFaces(data []byte, platform, language uint16) ([]Face, error) {
|
||||
count, err := FileCount(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -88,7 +114,7 @@ func ReadFaces(data []byte) ([]Face, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
face := FaceInfo(tables["name"], index)
|
||||
face := faceInfoLanguage(tables["name"], index, platform, language)
|
||||
if face.FullName == "" {
|
||||
return nil, fmt.Errorf("font %d has no usable name", index)
|
||||
}
|
||||
|
||||
@@ -687,12 +687,13 @@ func (h *Host) cleanupOutput(ctx context.Context, target webui.NativeOutputTarge
|
||||
|
||||
// readFonts 建立系统字体目录并登记按需读取资源
|
||||
func (h *Host) readFonts() {
|
||||
platform, language := fontNameLanguage()
|
||||
for _, name := range ofdgo.FontSystemFiles() {
|
||||
data, err := os.ReadFile(name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
faces, err := (ofdgo.FontFile{Name: filepath.Base(name), Data: data}).Faces()
|
||||
faces, err := (ofdgo.FontFile{Name: filepath.Base(name), Data: data}).LocalizedFaces(platform, language)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
// 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.
|
||||
|
||||
//go:build !windows
|
||||
|
||||
package webview
|
||||
|
||||
// conversionMemory 未提供系统内存探测时仅按并行数调度
|
||||
var conversionMemory func() int64
|
||||
@@ -1,45 +0,0 @@
|
||||
// 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 webview
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// memoryStatusProc 查询系统物理内存和提交额度
|
||||
var memoryStatusProc = syscall.NewLazyDLL("kernel32.dll").NewProc("GlobalMemoryStatusEx")
|
||||
|
||||
// conversionMemory 预留系统内存后返回可用于新增转换的额度
|
||||
// 返回: int64 可用字节数,查询失败时暂停扩容
|
||||
func conversionMemory() int64 {
|
||||
status := struct {
|
||||
length uint32
|
||||
load uint32
|
||||
total uint64
|
||||
available uint64
|
||||
totalPage uint64
|
||||
availablePage uint64
|
||||
totalVirtual uint64
|
||||
availableVirtual uint64
|
||||
extended uint64
|
||||
}{}
|
||||
status.length = uint32(unsafe.Sizeof(status))
|
||||
ok, _, _ := memoryStatusProc.Call(uintptr(unsafe.Pointer(&status)))
|
||||
if ok == 0 {
|
||||
return 0
|
||||
}
|
||||
return max(0, int64(min(status.available, status.availablePage))-int64(status.total/8))
|
||||
}
|
||||
@@ -18,6 +18,9 @@ package webview
|
||||
|
||||
import "os"
|
||||
|
||||
// conversionMemory 未提供系统内存探测时仅按并行数调度
|
||||
var conversionMemory func() int64
|
||||
|
||||
// openReadFile 打开独立读取句柄
|
||||
func openReadFile(name string) (*os.File, error) {
|
||||
return os.Open(name)
|
||||
@@ -27,3 +30,9 @@ func openReadFile(name string) (*os.File, error) {
|
||||
func replaceFile(source, target string) error {
|
||||
return os.Rename(source, target)
|
||||
}
|
||||
|
||||
// fontNameLanguage 未指定系统显示语言时沿用字体名称表顺序
|
||||
// 返回: uint16 未指定平台标识, uint16 未指定语言标识
|
||||
func fontNameLanguage() (uint16, uint16) {
|
||||
return 0xffff, 0xffff
|
||||
}
|
||||
@@ -25,6 +25,9 @@ import (
|
||||
// replaceFileProc 保留目标文件属性并替换文件内容
|
||||
var replaceFileProc = syscall.NewLazyDLL("kernel32.dll").NewProc("ReplaceFileW")
|
||||
|
||||
// memoryStatusProc 查询系统物理内存和提交额度
|
||||
var memoryStatusProc = syscall.NewLazyDLL("kernel32.dll").NewProc("GlobalMemoryStatusEx")
|
||||
|
||||
// openReadFile 允许原子替换路径,同时保持已有读取句柄有效
|
||||
func openReadFile(name string) (*os.File, error) {
|
||||
path, err := nativeFilePath(name)
|
||||
@@ -73,3 +76,32 @@ func nativeFilePath(name string) (*uint16, error) {
|
||||
}
|
||||
return syscall.UTF16PtrFromString(path)
|
||||
}
|
||||
|
||||
// fontNameLanguage 获取系统显示语言对应的OpenType名称表标识
|
||||
// 返回: uint16 名称表平台标识, uint16 系统显示语言标识
|
||||
func fontNameLanguage() (uint16, uint16) {
|
||||
language, _, _ := syscall.NewLazyDLL("kernel32.dll").NewProc("GetUserDefaultUILanguage").Call()
|
||||
return 3, uint16(language)
|
||||
}
|
||||
|
||||
// conversionMemory 预留系统内存后返回可用于新增转换的额度
|
||||
// 返回: int64 可用字节数,查询失败时暂停扩容
|
||||
func conversionMemory() int64 {
|
||||
status := struct {
|
||||
length uint32
|
||||
load uint32
|
||||
total uint64
|
||||
available uint64
|
||||
totalPage uint64
|
||||
availablePage uint64
|
||||
totalVirtual uint64
|
||||
availableVirtual uint64
|
||||
extended uint64
|
||||
}{}
|
||||
status.length = uint32(unsafe.Sizeof(status))
|
||||
ok, _, _ := memoryStatusProc.Call(uintptr(unsafe.Pointer(&status)))
|
||||
if ok == 0 {
|
||||
return 0
|
||||
}
|
||||
return max(0, int64(min(status.available, status.availablePage))-int64(status.total/8))
|
||||
}
|
||||
@@ -44,6 +44,18 @@ func (f FontFile) Faces() ([]FontFace, error) {
|
||||
return basefont.ReadFaces(data)
|
||||
}
|
||||
|
||||
// LocalizedFaces 读取指定语言的显示名称,保留PostScript名称、全部别名和集合索引
|
||||
// 未找到对应名称时沿用Faces的名称选择规则,不修改字体数据
|
||||
// 入参: platform OpenType名称表平台标识, language 该平台的语言标识
|
||||
// 返回: []FontFace 字体列表, error 格式或名称表错误
|
||||
func (f FontFile) LocalizedFaces(platform, language uint16) ([]FontFace, error) {
|
||||
data, err := decodeFontContainer(f.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return basefont.ReadLocalizedFaces(data, platform, language)
|
||||
}
|
||||
|
||||
// Face 提取指定字体,返回独立的OpenType数据,可用于预览或AddFont,且不修改原文件
|
||||
// 入参: index 零起始字体索引,非集合文件只能为0
|
||||
// 返回: []byte 独立字体数据, error 格式或索引错误
|
||||
|
||||
Reference in new issue
Block a user