blog/go/fonts/main.go

218 lines
4.2 KiB
Go

package main
import (
"bytes"
"encoding/binary"
"fmt"
"os"
)
func readInt8(fp *os.File) (int8, error) {
buff := make([]byte, 1)
_, err := fp.Read(buff)
if err != nil {
return 0, err
}
reader := bytes.NewReader(buff)
n := int8(0)
return n, binary.Read(reader, binary.LittleEndian, &n)
}
func readInt16(fp *os.File) (int16, error) {
buff := make([]byte, 2)
_, err := fp.Read(buff)
if err != nil {
return 0, err
}
reader := bytes.NewReader(buff)
n := int16(0)
return n, binary.Read(reader, binary.LittleEndian, &n)
}
func readInt32(fp *os.File) (int32, error) {
buff := make([]byte, 4)
_, err := fp.Read(buff)
if err != nil {
return 0, err
}
reader := bytes.NewReader(buff)
n := int32(0)
return n, binary.Read(reader, binary.LittleEndian, &n)
}
func readInt64(fp *os.File) (int64, error) {
buff := make([]byte, 8)
_, err := fp.Read(buff)
if err != nil {
return 0, err
}
reader := bytes.NewReader(buff)
n := int64(0)
return n, binary.Read(reader, binary.LittleEndian, &n)
}
func readUint8(fp *os.File) (uint8, error) {
buff := make([]byte, 1)
_, err := fp.Read(buff)
if err != nil {
return 0, err
}
return uint8(buff[0]), nil
}
func readUint16(fp *os.File) (uint16, error) {
buff := make([]byte, 2)
_, err := fp.Read(buff)
if err != nil {
return 0, err
}
return binary.BigEndian.Uint16(buff), nil
}
func readUint32(fp *os.File) (uint32, error) {
buff := make([]byte, 4)
_, err := fp.Read(buff)
if err != nil {
return 0, err
}
return binary.BigEndian.Uint32(buff), nil
}
func readUint64(fp *os.File) (uint64, error) {
buff := make([]byte, 8)
_, err := fp.Read(buff)
if err != nil {
return 0, err
}
return binary.BigEndian.Uint64(buff), nil
}
func readString(fp *os.File, len int) (string, error) {
buff := make([]byte, len)
_, err := fp.Read(buff)
if err != nil {
return "", err
}
return string(buff), nil
}
func readBytes(fp *os.File, len int) ([]byte, error) {
buff := make([]byte, len)
_, err := fp.Read(buff)
if err != nil {
return []byte{}, err
}
return buff, nil
}
func readFontSearchArgs(fp *os.File) ([]uint16, error) {
ret := []uint16{}
arg1, err := readUint16(fp)
if err != nil {
return ret, err
}
ret = append(ret, arg1)
arg1, err = readUint16(fp)
if err != nil {
return ret, err
}
ret = append(ret, arg1)
arg1, err = readUint16(fp)
if err != nil {
return ret, err
}
ret = append(ret, arg1)
return ret, nil
}
type ftable struct {
Name string
Sum uint32
Offset uint32
Length uint32
}
func readFontTables(fp *os.File, tables uint16) ([]ftable, error) {
ret := []ftable{}
for i := 0; i < int(tables); i++ {
t := ftable{}
name, err := readString(fp, 4)
if err != nil {
return ret, err
}
t.Name = name
sum, err := readUint32(fp)
if err != nil {
return ret, err
}
t.Sum = sum
addr, err := readUint32(fp)
if err != nil {
return ret, err
}
t.Offset = addr
length, err := readUint32(fp)
if err != nil {
return ret, err
}
t.Length = length
ret = append(ret, t)
}
return ret, nil
}
func readNameTable(fp *os.File, offset uint32, length uint32) ([]byte, error) {
fp.Seek(int64(offset), 0)
return readBytes(fp, int(length))
}
func readFont(file string) error {
fp, err := os.OpenFile(file, os.O_RDONLY, os.ModePerm)
if err != nil {
return err
}
defer fp.Close()
verB, err := readUint16(fp)
if err != nil {
return err
}
verL, err := readInt16(fp)
if err != nil {
return err
}
fmt.Println("font head version is", fmt.Sprintf("%d.%d", verB, verL))
tableCount, err := readUint16(fp)
if err != nil {
return err
}
fmt.Println("font table count is", tableCount)
args, err := readFontSearchArgs(fp)
if err != nil {
return err
}
fmt.Println("font search args is", args)
tables, err := readFontTables(fp, tableCount)
if err != nil {
return err
}
nameBuff := []byte{}
for n, table := range tables {
fmt.Println("font table", n+1, ": name: ", table.Name, " sum: ", table.Sum, " offset: ", table.Offset, " length: ", table.Length)
if table.Name == "name" {
nameBuff, err = readNameTable(fp, table.Offset, table.Length)
}
}
if err != nil {
return err
}
fmt.Println("name table: ", string(nameBuff))
return nil
}
func main() {
err := readFont("文鼎中黑.ttf")
if err != nil {
panic(err)
}
}