~sbinet/star-tex

45a548507c2b22e1dd114cffca93bf84916fd108 — Sebastien Binet 4 months ago 86bb800
dvi: implement glyph advance in dvi.Font

Signed-off-by: Sebastien Binet <s@sbinet.org>
3 files changed, 33 insertions(+), 32 deletions(-)

M dvi/font.go
M dvi/machine.go
M dvi/state.go
M dvi/font.go => dvi/font.go +15 -2
@@ 5,12 5,25 @@
package dvi

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

// Font describes a DVI font, with TeX Font Metrics and its
// associated font glyph data.
type Font struct {
	font *tfm.Font
	face *tfm.Face
	font  tfm.Font
	scale fixed.Int12_20
}

func (fnt *Font) name() string {
	return fnt.font.Name()
}

func (fnt *Font) advance(r rune) (fixed.Int12_20, bool) {
	w, _, _, ok := fnt.font.Box(r)
	if !ok {
		return 0, ok
	}
	return fixed.Int12_20((int64(w) * int64(fnt.scale)) >> 20), true
}

M dvi/machine.go => dvi/machine.go +17 -24
@@ 920,16 920,16 @@ func (m *Machine) drawGlyph(op opCode, cmd int32) error {

	cur := m.state.cur()

	face, err := m.face(m.state.f)
	fnt, err := m.loadFont(m.state.f)
	if err != nil {
		return err
	}

	m.rdr.DrawGlyph(cur.h, cur.v, m.font(), rune(cmd), color.Black)
	m.rdr.DrawGlyph(cur.h, cur.v, *fnt, rune(cmd), color.Black)

	adv, ok := face.GlyphAdvance(rune(cmd))
	adv, ok := fnt.advance(rune(cmd))
	if !ok {
		return fmt.Errorf("dvi: font %q has no glyph %c", face.Name(), cmd)
		return fmt.Errorf("dvi: font %q has no glyph %c", fnt.name(), cmd)
	}

	if op >= opPut1 {


@@ 1052,17 1052,12 @@ func (m *Machine) defineFont(i int, def fntdef) error {
	return nil
}

func (m *Machine) face(i int) (*tfm.Face, error) {
	fnt := m.state.fonts[i]
	if fnt.face != nil {
		return fnt.face, nil
func (m *Machine) loadFont(i int) (*Font, error) {
	def := m.state.fonts[i]
	if def.font != nil {
		return def.font, nil
	}

	return m.loadFont(i)
}

func (m *Machine) loadFont(i int) (*tfm.Face, error) {
	def := m.state.fonts[i]
	// FIXME: add support for non-TFM fonts?
	name, err := m.ktx.Find(def.Name + ".tfm")
	if err != nil {


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

	def.font = &Font{
		font:  font,
		scale: fixed.Int12_20(def.Size),
	}
	m.state.fonts[i] = def

	return def.face, nil
	return def.font, nil
}

func (m *Machine) font() Font {
	face, err := m.face(m.state.f)
func (m *Machine) font(i int) *Font {
	fnt, err := m.loadFont(i)
	if err != nil {
		panic(err)
	}
	return Font{
		face: face,
	}
	return fnt
}

func (m *Machine) outText(c uint8) {

M dvi/state.go => dvi/state.go +1 -6
@@ 4,10 4,6 @@

package dvi

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

// regs is the set of DVI registers.
type regs struct {
	h int32 // h is the current horizontal position on the page.


@@ 31,8 27,7 @@ type fntdef struct {
	Name     string

	mag  int32
	font *tfm.Font
	face *tfm.Face
	font *Font
}

type state struct {