add Atlas doc

This commit is contained in:
faiface 2017-05-09 15:25:08 +02:00
parent dcdc812af5
commit 80735cfc0c
1 changed files with 22 additions and 0 deletions

View File

@ -11,12 +11,14 @@ import (
"golang.org/x/image/math/fixed" "golang.org/x/image/math/fixed"
) )
// Glyph describes one glyph in an Atlas.
type Glyph struct { type Glyph struct {
Dot pixel.Vec Dot pixel.Vec
Frame pixel.Rect Frame pixel.Rect
Advance float64 Advance float64
} }
// Atlas is a set of pre-drawn glyphs of a fixed set of runes. This allows for efficient text drawing.
type Atlas struct { type Atlas struct {
face font.Face face font.Face
pic pixel.Picture pic pixel.Picture
@ -26,6 +28,8 @@ type Atlas struct {
lineHeight float64 lineHeight float64
} }
// NewAtlas creates a new Atlas containing glyphs of the given set of runes from the given font
// face.
func NewAtlas(face font.Face, runes []rune) *Atlas { func NewAtlas(face font.Face, runes []rune) *Atlas {
fixedMapping, fixedBounds := makeSquareMapping(face, runes, fixed.I(2)) fixedMapping, fixedBounds := makeSquareMapping(face, runes, fixed.I(2))
@ -75,35 +79,48 @@ func NewAtlas(face font.Face, runes []rune) *Atlas {
} }
} }
// Picture returns the underlying Picture containing an arrangement of all the glyphs contained
// within the Atlas.
func (a *Atlas) Picture() pixel.Picture { func (a *Atlas) Picture() pixel.Picture {
return a.pic return a.pic
} }
// Contains reports wheter r in contained within the Atlas.
func (a *Atlas) Contains(r rune) bool { func (a *Atlas) Contains(r rune) bool {
_, ok := a.mapping[r] _, ok := a.mapping[r]
return ok return ok
} }
// Glyph returns the description of r within the Atlas.
func (a *Atlas) Glyph(r rune) Glyph { func (a *Atlas) Glyph(r rune) Glyph {
return a.mapping[r] return a.mapping[r]
} }
// Kern returns the kerning distance between runes r0 and r1. Positive distance means, that the
// glyphs should be further apart.
func (a *Atlas) Kern(r0, r1 rune) float64 { func (a *Atlas) Kern(r0, r1 rune) float64 {
return i2f(a.face.Kern(r0, r1)) return i2f(a.face.Kern(r0, r1))
} }
// Ascent returns the distance from the top of the line to the baseline.
func (a *Atlas) Ascent() float64 { func (a *Atlas) Ascent() float64 {
return a.ascent return a.ascent
} }
// Descent returns the distance from the baseline to the bottom of the line.
func (a *Atlas) Descent() float64 { func (a *Atlas) Descent() float64 {
return a.descent return a.descent
} }
// LineHeight returns the recommended vertical distance between two lines of text.
func (a *Atlas) LineHeight() float64 { func (a *Atlas) LineHeight() float64 {
return a.lineHeight return a.lineHeight
} }
// DrawRune returns parameters necessary for drawing a rune glyph.
//
// Rect is a rectangle where the glyph should be positioned. Frame is the glyph frame inside the
// Atlas's Picture. NewDot is the new position of the dot.
func (a *Atlas) DrawRune(prevR, r rune, dot pixel.Vec) (rect, frame, bounds pixel.Rect, newDot pixel.Vec) { func (a *Atlas) DrawRune(prevR, r rune, dot pixel.Vec) (rect, frame, bounds pixel.Rect, newDot pixel.Vec) {
if !a.Contains(r) { if !a.Contains(r) {
r = unicode.ReplacementChar r = unicode.ReplacementChar
@ -144,6 +161,8 @@ type fixedGlyph struct {
advance fixed.Int26_6 advance fixed.Int26_6
} }
// makeSquareMapping finds an optimal glyph arrangement of the given runes, so that their common
// bounding box is as square as possible.
func makeSquareMapping(face font.Face, runes []rune, padding fixed.Int26_6) (map[rune]fixedGlyph, fixed.Rectangle26_6) { func makeSquareMapping(face font.Face, runes []rune, padding fixed.Int26_6) (map[rune]fixedGlyph, fixed.Rectangle26_6) {
width := sort.Search(int(fixed.I(1024*1024)), func(i int) bool { width := sort.Search(int(fixed.I(1024*1024)), func(i int) bool {
width := fixed.Int26_6(i) width := fixed.Int26_6(i)
@ -153,6 +172,9 @@ func makeSquareMapping(face font.Face, runes []rune, padding fixed.Int26_6) (map
return makeMapping(face, runes, padding, fixed.Int26_6(width)) return makeMapping(face, runes, padding, fixed.Int26_6(width))
} }
// makeMapping arranges glyphs of the given runes into rows in such a way, that no glyph is located
// fully to the right of the specified width. Specifically, it places glyphs in a row one by one and
// once it reaches the specified width, it starts a new row.
func makeMapping(face font.Face, runes []rune, padding, width fixed.Int26_6) (map[rune]fixedGlyph, fixed.Rectangle26_6) { func makeMapping(face font.Face, runes []rune, padding, width fixed.Int26_6) (map[rune]fixedGlyph, fixed.Rectangle26_6) {
mapping := make(map[rune]fixedGlyph) mapping := make(map[rune]fixedGlyph)
bounds := fixed.Rectangle26_6{} bounds := fixed.Rectangle26_6{}