~sbinet/star-tex

25a01eba11f4796a3411da32c116d080f74386f9 — Sebastien Binet 4 months ago 98d6207
all: migrate to font/fixed package

Signed-off-by: Sebastien Binet <s@sbinet.org>
M dvi/machine.go => dvi/machine.go +2 -1
@@ 11,6 11,7 @@ import (
	"sort"
	"strings"

	"star-tex.org/x/tex/font/fixed"
	"star-tex.org/x/tex/font/tfm"
	"star-tex.org/x/tex/kpath"
)


@@ 1079,7 1080,7 @@ func (m *Machine) loadFont(i int) (*tfm.Face, error) {
		return nil, fmt.Errorf("could not parse TFM font %q: %w", def.Name, err)
	}
	face := tfm.NewFace(&font, &tfm.FaceOptions{
		Size: tfm.Int12_20(def.Size),
		Size: fixed.Int12_20(def.Size),
	})
	def.font = &font
	def.face = &face

M font/tfm/encoder.go => font/tfm/encoder.go +3 -1
@@ 10,6 10,8 @@ import (
	"io"
	"sort"
	"strings"

	"star-tex.org/x/tex/font/fixed"
)

type label struct {


@@ 97,7 99,7 @@ func (te *textEncoder) face(v byte) string {
	return "F " + string(mblString[b%3]) + string(riString[s]) + string(rceString[b/3])
}

func (te *textEncoder) fword(v Int12_20) string {
func (te *textEncoder) fword(v fixed.Int12_20) string {
	var (
		j     byte
		delta = int32(10)

M font/tfm/face.go => font/tfm/face.go +8 -4
@@ 4,10 4,14 @@

package tfm

import (
	"star-tex.org/x/tex/font/fixed"
)

// Face is a TFM font face.
type Face struct {
	font  *Font
	scale Int12_20
	scale fixed.Int12_20

	buf []byte
}


@@ 15,7 19,7 @@ type Face struct {
// FaceOptions describes the possible options given to NewFace when
// creating a new Face from a Font.
type FaceOptions struct {
	Size Int12_20 // Size is the font size in DVI points.
	Size fixed.Int12_20 // Size is the font size in DVI points.
}

func defaultFaceOptions(font *Font) *FaceOptions {


@@ 46,10 50,10 @@ func (face *Face) Name() string {
// GlyphAdvance returns the advance width of r's glyph.
//
// It returns !ok if the face does not contain a glyph for r.
func (face *Face) GlyphAdvance(r rune) (adv Int12_20, ok bool) {
func (face *Face) GlyphAdvance(r rune) (adv fixed.Int12_20, ok bool) {
	adv, ok = face.font.GlyphAdvance(r)
	if !ok {
		return 0, ok
	}
	return Int12_20((int64(adv) * int64(face.scale)) >> 20), true
	return fixed.Int12_20((int64(adv) * int64(face.scale)) >> 20), true
}

M font/tfm/font.go => font/tfm/font.go +12 -11
@@ 9,6 9,7 @@ import (
	"fmt"
	"io"

	"star-tex.org/x/tex/font/fixed"
	"star-tex.org/x/tex/internal/iobuf"
)



@@ 64,7 65,7 @@ func Parse(r io.Reader) (Font, error) {
	return fnt, nil
}

func (fnt *Font) DesignSize() Int12_20 {
func (fnt *Font) DesignSize() fixed.Int12_20 {
	return fnt.body.header.designSize
}



@@ 100,7 101,7 @@ func (fnt *Font) glyph(x GlyphIndex) glyphInfo {
// GlyphAdvance returns the advance width of r's glyph.
//
// It returns !ok if the face does not contain a glyph for r.
func (fnt *Font) GlyphAdvance(x rune) (Int12_20, bool) {
func (fnt *Font) GlyphAdvance(x rune) (fixed.Int12_20, bool) {
	i := int(x)
	if !(int(fnt.hdr.bc) <= i && i <= int(fnt.hdr.ec)) {
		return 0, false


@@ 136,30 137,30 @@ func (fnt *Font) readHeader(r *iobuf.Reader) error {
type fileBody struct {
	header  header
	glyphs  []glyphInfo
	width   []Int12_20
	height  []Int12_20
	depth   []Int12_20
	italic  []Int12_20
	width   []fixed.Int12_20
	height  []fixed.Int12_20
	depth   []fixed.Int12_20
	italic  []fixed.Int12_20
	ligKern []ligKernCmd
	kern    []Int12_20
	kern    []fixed.Int12_20
	exten   []extensible
	param   []Int12_20
	param   []fixed.Int12_20
}

type header struct {
	chksum       uint32
	designSize   Int12_20
	designSize   fixed.Int12_20
	codingScheme string
	fontID       string
	sevenBitSafe bool
	face         byte

	extra []Int12_20
	extra []fixed.Int12_20
}

func (fnt *Font) readBody(r *iobuf.Reader) error {
	fnt.body.header.chksum = r.ReadU32()
	fnt.body.header.designSize = Int12_20(r.ReadU32())
	fnt.body.header.designSize = fixed.Int12_20(r.ReadU32())
	if fnt.hdr.lh > 2 {
		fnt.body.header.codingScheme = readStr(r, 40)
		fnt.body.header.fontID = readStr(r, 20)

M font/tfm/font_test.go => font/tfm/font_test.go +17 -15
@@ 9,6 9,8 @@ import (
	"reflect"
	"strings"
	"testing"

	"star-tex.org/x/tex/font/fixed"
)

func TestFont(t *testing.T) {


@@ 17,42 19,42 @@ func TestFont(t *testing.T) {
		numglyphs int
		family    string
		scheme    string
		size      Int12_20
		size      fixed.Int12_20
	}{
		{
			name:      "testdata/simple.tfm",
			numglyphs: 1,
			family:    "hi parc",
			scheme:    "testing",
			size:      Int12_20(5 << 20),
			size:      fixed.I12_20(5),
		},
		{
			name:      "testdata/cmr10.tfm",
			numglyphs: 128,
			family:    "CMR",
			scheme:    "TeX text",
			size:      Int12_20(10 << 20),
			size:      fixed.I12_20(10),
		},
		{
			name:      "testdata/cmex10.tfm",
			numglyphs: 128,
			family:    "CMEX",
			scheme:    "TeX math extension",
			size:      Int12_20(10 << 20),
			size:      fixed.I12_20(10),
		},
		{
			name:      "testdata/cmbsy10.tfm",
			numglyphs: 128,
			family:    "CMBSY",
			scheme:    "TeX math symbols",
			size:      Int12_20(10 << 20),
			size:      fixed.I12_20(10),
		},
		{
			name:      "testdata/lmroman10-regular.tfm",
			numglyphs: 256,
			family:    "lmroman10-regular",
			scheme:    "Unspecified",
			size:      Int12_20(10 << 20),
			size:      fixed.I12_20(10),
		},
	} {
		t.Run(tc.name, func(t *testing.T) {


@@ 126,7 128,7 @@ func TestParse(t *testing.T) {
				body: fileBody{
					header: header{
						chksum:       0xABCDEFAB,
						designSize:   Int12_20(5 << 20),
						designSize:   fixed.I12_20(5),
						codingScheme: "testing",
						fontID:       "hi parc",
						sevenBitSafe: true,


@@ 147,7 149,7 @@ func TestParse(t *testing.T) {
				body: fileBody{
					header: header{
						chksum:       1274110073,
						designSize:   Int12_20(10 << 20),
						designSize:   fixed.I12_20(10),
						codingScheme: "TeX text",
						fontID:       "CMR",
						sevenBitSafe: false,


@@ 168,7 170,7 @@ func TestParse(t *testing.T) {
				body: fileBody{
					header: header{
						chksum:       4205933842,
						designSize:   Int12_20(10 << 20),
						designSize:   fixed.I12_20(10),
						codingScheme: "TeX math extension",
						fontID:       "CMEX",
						sevenBitSafe: false,


@@ 189,7 191,7 @@ func TestParse(t *testing.T) {
				body: fileBody{
					header: header{
						chksum:       3771304972,
						designSize:   Int12_20(10 << 20),
						designSize:   fixed.I12_20(10),
						codingScheme: "TeX math symbols",
						fontID:       "CMBSY",
						sevenBitSafe: false,


@@ 210,12 212,12 @@ func TestParse(t *testing.T) {
				body: fileBody{
					header: header{
						chksum:       1674865313,
						designSize:   Int12_20(10 << 20),
						designSize:   fixed.I12_20(10),
						codingScheme: "Unspecified",
						fontID:       "lmroman10-regular",
						sevenBitSafe: false,
						face:         0,
						extra: []Int12_20{
						extra: []fixed.Int12_20{
							2806215269, 1635018084, 543324448, 1618244710,
							846489197, 539977839, 1835347810, 1768842612,
							796356466, 1798268783, 1853189423, 1936876335,


@@ 264,15 266,15 @@ func TestParse(t *testing.T) {
				t.Fatalf("invalid TFM body header:\ngot= %+v\nwant=%+v\n", got, want)
			}

			if got, want := fnt.body.width[0], Int12_20(0); got != want {
			if got, want := fnt.body.width[0], fixed.Int12_20(0); got != want {
				t.Fatalf("invalid TFM width: got=%v, want=%v", got, want)
			}

			if got, want := fnt.body.height[0], Int12_20(0); got != want {
			if got, want := fnt.body.height[0], fixed.Int12_20(0); got != want {
				t.Fatalf("invalid TFM height: got=%v, want=%v", got, want)
			}

			if got, want := fnt.body.depth[0], Int12_20(0); got != want {
			if got, want := fnt.body.depth[0], fixed.Int12_20(0); got != want {
				t.Fatalf("invalid TFM depth: got=%v, want=%v", got, want)
			}


M font/tfm/reader.go => font/tfm/reader.go +4 -3
@@ 7,6 7,7 @@ package tfm
import (
	"io"

	"star-tex.org/x/tex/font/fixed"
	"star-tex.org/x/tex/internal/iobuf"
)



@@ 64,14 65,14 @@ func readCharInfos(r *iobuf.Reader, n int) []glyphInfo {
	return out
}

func readFWs(r *iobuf.Reader, n int) []Int12_20 {
func readFWs(r *iobuf.Reader, n int) []fixed.Int12_20 {
	if len(r.Bytes()) < n*4 {
		return nil
	}

	out := make([]Int12_20, n)
	out := make([]fixed.Int12_20, n)
	for i := range out {
		out[i] = Int12_20(r.ReadU32())
		out[i] = fixed.Int12_20(r.ReadU32())
	}
	return out
}

M font/tfm/tfm.go => font/tfm/tfm.go +0 -46
@@ 9,52 9,6 @@ import (
	"fmt"
)

// Int12_20 is a signed 26.6 fixed-point number.
//
// The integer part ranges from -2048 to 2047, inclusive. The
// fractional part has 20 bits of precision.
type Int12_20 uint32

func (x Int12_20) Float64() float64 {
	v := int32(x)
	return float64(v) / (1 << 20)

	//	const (
	//		signMask = 0b1000_0000_0000_0000_0000_0000_0000_0000
	//		intMask  = 0b0111_1111_1111_0000_0000_0000_0000_0000
	//		fracMask = 0b0000_0000_0000_1111_1111_1111_1111_1111
	//	)
	//
	//	var (
	//		num  = uint32(x)
	//		sign = 1.0
	//	)
	//	if num&signMask == signMask {
	//		num = ^num + 1
	//		sign = -1
	//	}
	//
	//	ip := float64((num & intMask) >> 20)
	//	fp := float64(num&fracMask) / float64(1<<20)
	//	return sign * (ip + fp)
}

// String returns a human-readable representation of a 12.20 fixed-point number.
func (x Int12_20) String() string {
	const (
		shift = 12
		mask  = 1<<shift - 1
	)
	if x >= 0 {
		return fmt.Sprintf("%d:%02d", int32(x>>shift), int32(x&mask))
	}
	x = -x
	if x >= 0 {
		return fmt.Sprintf("-%d:%02d", int32(x>>shift), int32(x&mask))
	}
	return "-2048:00" // The minimum value is -(1<<(12-1)).
}

type glyphKind uint8

const (