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