func (fnt *Font) Kern(r0, r1 rune) xfix.Int26_6 {
	i0 := fnt.index(r0)
	if i0 < 0 {
		return 0
	}
	i1 := fnt.index(r1)
	if i1 < 0 {
		return 0
	}
	g0 := fnt.glyph(i0)
	c1 := int(r1)
	if g0.raw[2]&3 == 1 {
		ii := int(g0.raw[3])
		rr := fnt.body.ligKern[ii]
		if rr.raw[0] > 128 {
			ii = int(rr.raw[2])*256 + int(rr.raw[3])
		}
		for {
			lk := fnt.body.ligKern[ii]
			switch {
			case lk.raw[2] >= 128:
				if int(lk.raw[1]) == c1 {
					rr := lk.nextIndex()
					kern := fnt.body.kern[rr]
					return fixed.Int12_20(kern).ToInt26_6()
				}
			default:
			}
			switch {
			case lk.raw[0] >= 128:
				ii = len(fnt.body.ligKern)
			default:
				ii += int(lk.raw[0]) + 1
			}
			if ii >= len(fnt.body.ligKern) {
				return 0
			}
		}
	}
	return 0
}
Kern returns the horizontal adjustment for the kerning pair (r0, r1). A
positive kern means to move the glyphs further apart.
package tfm
import (
	"bytes"
	"fmt"
	"image"
	"io"
	"math"
	"golang.org/x/image/font"
	xfix "golang.org/x/image/math/fixed"
	"star-tex.org/x/tex/font/fixed"
	"star-tex.org/x/tex/internal/iobuf"
)
type fontFamily string
const (
	fontTypeVanilla fontFamily = "TEX TEXT"
	fontTypeMathSym fontFamily = "TEX MATH SYMBOLS"
	fontTypeMathExt fontFamily = "TEX MATH EXTENSION"
)
type Font struct {
	hdr  fileHeader
	body fileBody
	metSet  bool  
	metrics font.Metrics
}
type fileHeader struct {
	lf uint16  
	lh uint16  
	bc uint16  
	ec uint16  
	nw uint16  
	nh uint16  
	nd uint16  
	ni uint16  
	nl uint16  
	nk uint16  
	ne uint16  
	np uint16  
}
func Parse(r io.Reader) (Font, error) {
	var (
		fnt     Font
		rr, err = newReader(r)
	)
	if err != nil {
		return fnt, fmt.Errorf("could not read TFM file: %w", err)
	}
	err = fnt.readHeader(rr)
	if err != nil {
		return fnt, fmt.Errorf("could not parse TFM file header: %w", err)
	}
	err = fnt.readBody(rr)
	if err != nil {
		return fnt, fmt.Errorf("could not parse TFM file body: %w", err)
	}
	return fnt, nil
}
func (fnt *Font) DesignSize() fixed.Int12_20 {
	return fnt.body.header.designSize
}
func (fnt *Font) CodingScheme() string {
	return fnt.body.header.codingScheme
}
func (fnt *Font) Name() string {
	return fnt.body.header.fontID
}
func (fnt *Font) Checksum() uint32 {
	return fnt.body.header.chksum
}
func (fnt *Font) NumGlyphs() int {
	return int(fnt.hdr.ec) + 1 - int(fnt.hdr.bc)
}
func (fnt *Font) index(r rune) glyphIndex {
	i := int(r)
	if !(int(fnt.hdr.bc) <= i && i <= int(fnt.hdr.ec)) {
		panic(fmt.Errorf("glyph out of range"))
	}
	i -= int(fnt.hdr.bc)
	return glyphIndex(i)
}
func (fnt *Font) glyph(x glyphIndex) glyphInfo {
	return fnt.body.glyphs[x]
}
func (fnt *Font) Box(r rune) (w, h, d fixed.Int12_20, ok bool) {
	i := int(r)
	if !(int(fnt.hdr.bc) <= i && i <= int(fnt.hdr.ec)) {
		return 0, 0, 0, false
	}
	i -= int(fnt.hdr.bc)
	g := fnt.body.glyphs[i]
	w = fnt.body.width[g.wd()]  
	h = fnt.body.height[g.ht()]
	d = fnt.body.depth[g.dp()]
	return w, h, d, true
}
func (fnt *Font) GlyphAdvance(r rune) (xfix.Int26_6, bool) {
	i := int(r)
	if !(int(fnt.hdr.bc) <= i && i <= int(fnt.hdr.ec)) {
		return 0, false
	}
	i -= int(fnt.hdr.bc)
	var (
		g  = fnt.body.glyphs[i]
		ic = fnt.body.italic[g.ic()]
		w  = fnt.body.width[g.wd()] + ic
	)
	return w.ToInt26_6(), true
}
func (fnt *Font) GlyphBounds(r rune) (bounds xfix.Rectangle26_6, advance xfix.Int26_6, ok bool) {
	i := fnt.index(r)
	if i < 0 {
		return
	}
	ok = true
	g := fnt.body.glyphs[i]
	var (
		ic = fnt.body.italic[g.ic()]
		w  = fnt.body.width[g.wd()] + ic
		h  = fnt.body.height[g.ht()]
		d  = fnt.body.depth[g.dp()]
	)
	bounds = xfix.Rectangle26_6{
		Min: xfix.Point26_6{
			X: 0,  
			Y: -h.ToInt26_6(),
		},
		Max: xfix.Point26_6{
			X: w.ToInt26_6(),
			Y: d.ToInt26_6(),
		},
	}
	advance = w.ToInt26_6()
	return
}