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) } }