blog/go/fonts/main.go

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