pbnjay / pixfont

A simple, lightweight Pixel Font package for Go that works with the standard image/draw package.
MIT License
105 stars 9 forks source link

[PROPOSAL] Font parsing overhaul: split parsers into packages, migrate BDF to a parser package #9

Open DHowett opened 4 years ago

DHowett commented 4 years ago

Hey @pbnjay! Sorry, this took longer than I intended thanks to wandering priorities and interests.

I've been working on a branch here that moderately overhauls font parsing in fontgen.

The core of the change revolves around the isolation of text and image parsing code into individual packages (with tests!) that offer a top-level Decode function. Decode produces a *bitfont.Font, which is...

// Font is the internal representation of an entire pixel font, as generated by the parsing packages.
type Font struct {
        Width, Height int
        Glyphs        map[rune]Glyph
}

type Glyph struct {
        Mask []uint32
        // eventually: Advance? Some way to store variable glyphs; BDF has a lot of info that we may want to preserve
}

bitfont.Font wouldn't be used outside of the parsing/generating code; the internal packed representation would continue to be used in generated packages and for efficient lookup.

This would let us move the core parsing logic of bdf2pixfont into another package that just produces a *bitfont.Font. After that, fontgen becomes a thin wrapper around the parser packages -- it serves to direct commandline arguments into the right places. I cobbled together a bit of that code here (though it targets an earlier version of the code where I had named it cmd/fontgen/internal/parser instead of internal/bitfont)[1].

Right now, the API shape for image.Decode leaves a bit to be desired; I couldn't decide how to handle offsets and chops in a particularly ergonomic fashion. text.Decode and bdf.Decode are relatively sane, though.

doc for packages text, image ### text ``` package text // import "github.com/pbnjay/pixfont/internal/bitfont/text" FUNCTIONS func Decode(r io.Reader) (*bitfont.Font, error) ``` ### image ``` package image // import "github.com/pbnjay/pixfont/internal/bitfont/image" FUNCTIONS func Decode(r io.Reader, alphabet string, options *Options) (*bitfont.Font, error) TYPES type Options struct { Offset image.Point Size image.Point // 0 in X or Y is treated as "max"; ew } ```

[1] the cmd/fontgen/internal/parser version also had an interface, parser.Parser (naming is the hardest part of software engineering 🙄), that Decode could hang off of.

What do you think? Is this worth pursuing, and would you consider upstreaming some version of it? Or should I hold on to it and keep a friendly fork?

DHowett commented 4 years ago

Incidentally, with the changes above bdf2pixfont is subsumed by fontgen -bdf blah.bdf in its default text output mode, which produces the textual representation from bitfont/text.